1 //===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the AttributeList class, which is used to collect 11 // parsed attributes. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H 16 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H 17 18 #include "clang/Basic/SourceLocation.h" 19 #include "clang/Basic/TargetInfo.h" 20 #include "clang/Basic/VersionTuple.h" 21 #include "clang/Sema/Ownership.h" 22 #include "llvm/ADT/PointerUnion.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/Support/Allocator.h" 25 #include <cassert> 26 27 namespace clang { 28 class ASTContext; 29 class IdentifierInfo; 30 class Expr; 31 32 /// \brief Represents information about a change in availability for 33 /// an entity, which is part of the encoding of the 'availability' 34 /// attribute. 35 struct AvailabilityChange { 36 /// \brief The location of the keyword indicating the kind of change. 37 SourceLocation KeywordLoc; 38 39 /// \brief The version number at which the change occurred. 40 VersionTuple Version; 41 42 /// \brief The source range covering the version number. 43 SourceRange VersionRange; 44 45 /// \brief Determine whether this availability change is valid. isValidAvailabilityChange46 bool isValid() const { return !Version.empty(); } 47 }; 48 49 /// \brief Wraps an identifier and optional source location for the identifier. 50 struct IdentifierLoc { 51 SourceLocation Loc; 52 IdentifierInfo *Ident; 53 54 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc, 55 IdentifierInfo *Ident); 56 }; 57 58 /// \brief A union of the various pointer types that can be passed to an 59 /// AttributeList as an argument. 60 typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion; 61 typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector; 62 63 /// AttributeList - Represents a syntactic attribute. 64 /// 65 /// For a GNU attribute, there are four forms of this construct: 66 /// 67 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. 68 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. 69 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. 70 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. 71 /// 72 class AttributeList { // TODO: This should really be called ParsedAttribute 73 public: 74 /// The style used to specify an attribute. 75 enum Syntax { 76 /// __attribute__((...)) 77 AS_GNU, 78 /// [[...]] 79 AS_CXX11, 80 /// __declspec(...) 81 AS_Declspec, 82 /// __ptr16, alignas(...), etc. 83 AS_Keyword, 84 /// Context-sensitive version of a keyword attribute. 85 AS_ContextSensitiveKeyword, 86 /// #pragma ... 87 AS_Pragma 88 }; 89 90 private: 91 IdentifierInfo *AttrName; 92 IdentifierInfo *ScopeName; 93 SourceRange AttrRange; 94 SourceLocation ScopeLoc; 95 SourceLocation EllipsisLoc; 96 97 /// The number of expression arguments this attribute has. 98 /// The expressions themselves are stored after the object. 99 unsigned NumArgs : 15; 100 101 /// Corresponds to the Syntax enum. 102 unsigned SyntaxUsed : 3; 103 104 /// True if already diagnosed as invalid. 105 mutable unsigned Invalid : 1; 106 107 /// True if this attribute was used as a type attribute. 108 mutable unsigned UsedAsTypeAttr : 1; 109 110 /// True if this has the extra information associated with an 111 /// availability attribute. 112 unsigned IsAvailability : 1; 113 114 /// True if this has extra information associated with a 115 /// type_tag_for_datatype attribute. 116 unsigned IsTypeTagForDatatype : 1; 117 118 /// True if this has extra information associated with a 119 /// Microsoft __delcspec(property) attribute. 120 unsigned IsProperty : 1; 121 122 /// True if this has a ParsedType 123 unsigned HasParsedType : 1; 124 125 unsigned AttrKind : 8; 126 127 /// \brief The location of the 'unavailable' keyword in an 128 /// availability attribute. 129 SourceLocation UnavailableLoc; 130 131 const Expr *MessageExpr; 132 133 /// The next attribute in the current position. 134 AttributeList *NextInPosition; 135 136 /// The next attribute allocated in the current Pool. 137 AttributeList *NextInPool; 138 139 /// Arguments, if any, are stored immediately following the object. getArgsBuffer()140 ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); } getArgsBuffer()141 ArgsUnion const *getArgsBuffer() const { 142 return reinterpret_cast<ArgsUnion const *>(this + 1); 143 } 144 145 enum AvailabilitySlot { 146 IntroducedSlot, DeprecatedSlot, ObsoletedSlot 147 }; 148 149 /// Availability information is stored immediately following the arguments, 150 /// if any, at the end of the object. getAvailabilitySlot(AvailabilitySlot index)151 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { 152 return reinterpret_cast<AvailabilityChange*>(getArgsBuffer() 153 + NumArgs)[index]; 154 } getAvailabilitySlot(AvailabilitySlot index)155 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { 156 return reinterpret_cast<const AvailabilityChange*>(getArgsBuffer() 157 + NumArgs)[index]; 158 } 159 160 public: 161 struct TypeTagForDatatypeData { 162 ParsedType *MatchingCType; 163 unsigned LayoutCompatible : 1; 164 unsigned MustBeNull : 1; 165 }; 166 struct PropertyData { 167 IdentifierInfo *GetterId, *SetterId; PropertyDataPropertyData168 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) 169 : GetterId(getterId), SetterId(setterId) {} 170 }; 171 172 private: 173 /// Type tag information is stored immediately following the arguments, if 174 /// any, at the end of the object. They are mutually exlusive with 175 /// availability slots. getTypeTagForDatatypeDataSlot()176 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { 177 return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs); 178 } 179 getTypeTagForDatatypeDataSlot()180 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { 181 return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer() 182 + NumArgs); 183 } 184 185 /// The type buffer immediately follows the object and are mutually exclusive 186 /// with arguments. getTypeBuffer()187 ParsedType &getTypeBuffer() { 188 return *reinterpret_cast<ParsedType *>(this + 1); 189 } 190 getTypeBuffer()191 const ParsedType &getTypeBuffer() const { 192 return *reinterpret_cast<const ParsedType *>(this + 1); 193 } 194 195 /// The property data immediately follows the object is is mutually exclusive 196 /// with arguments. getPropertyDataBuffer()197 PropertyData &getPropertyDataBuffer() { 198 assert(IsProperty); 199 return *reinterpret_cast<PropertyData*>(this + 1); 200 } 201 getPropertyDataBuffer()202 const PropertyData &getPropertyDataBuffer() const { 203 assert(IsProperty); 204 return *reinterpret_cast<const PropertyData*>(this + 1); 205 } 206 207 AttributeList(const AttributeList &) = delete; 208 void operator=(const AttributeList &) = delete; 209 void operator delete(void *) = delete; 210 ~AttributeList() = delete; 211 212 size_t allocated_size() const; 213 214 /// Constructor for attributes with expression arguments. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ArgsUnion * args,unsigned numArgs,Syntax syntaxUsed,SourceLocation ellipsisLoc)215 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 216 IdentifierInfo *scopeName, SourceLocation scopeLoc, 217 ArgsUnion *args, unsigned numArgs, 218 Syntax syntaxUsed, SourceLocation ellipsisLoc) 219 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 220 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), 221 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), 222 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 223 HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) { 224 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); 225 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 226 } 227 228 /// Constructor for availability attributes. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Parm,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * messageExpr,Syntax syntaxUsed)229 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 230 IdentifierInfo *scopeName, SourceLocation scopeLoc, 231 IdentifierLoc *Parm, const AvailabilityChange &introduced, 232 const AvailabilityChange &deprecated, 233 const AvailabilityChange &obsoleted, 234 SourceLocation unavailable, 235 const Expr *messageExpr, 236 Syntax syntaxUsed) 237 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 238 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), 239 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 240 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 241 UnavailableLoc(unavailable), MessageExpr(messageExpr), 242 NextInPosition(nullptr), NextInPool(nullptr) { 243 ArgsUnion PVal(Parm); 244 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 245 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); 246 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); 247 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); 248 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 249 } 250 251 /// Constructor for objc_bridge_related attributes. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Parm1,IdentifierLoc * Parm2,IdentifierLoc * Parm3,Syntax syntaxUsed)252 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 253 IdentifierInfo *scopeName, SourceLocation scopeLoc, 254 IdentifierLoc *Parm1, 255 IdentifierLoc *Parm2, 256 IdentifierLoc *Parm3, 257 Syntax syntaxUsed) 258 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 259 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed), 260 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 261 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 262 NextInPosition(nullptr), NextInPool(nullptr) { 263 ArgsVector Args; 264 Args.push_back(Parm1); 265 Args.push_back(Parm2); 266 Args.push_back(Parm3); 267 memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion)); 268 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 269 } 270 271 /// Constructor for type_tag_for_datatype attribute. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * ArgKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,Syntax syntaxUsed)272 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 273 IdentifierInfo *scopeName, SourceLocation scopeLoc, 274 IdentifierLoc *ArgKind, ParsedType matchingCType, 275 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) 276 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 277 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), 278 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 279 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), 280 NextInPosition(nullptr), NextInPool(nullptr) { 281 ArgsUnion PVal(ArgKind); 282 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 283 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); 284 new (&ExtraData.MatchingCType) ParsedType(matchingCType); 285 ExtraData.LayoutCompatible = layoutCompatible; 286 ExtraData.MustBeNull = mustBeNull; 287 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 288 } 289 290 /// Constructor for attributes with a single type argument. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,Syntax syntaxUsed)291 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 292 IdentifierInfo *scopeName, SourceLocation scopeLoc, 293 ParsedType typeArg, Syntax syntaxUsed) 294 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 295 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), 296 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 297 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), 298 NextInPosition(nullptr), NextInPool(nullptr) { 299 new (&getTypeBuffer()) ParsedType(typeArg); 300 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 301 } 302 303 /// Constructor for microsoft __declspec(property) attribute. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,Syntax syntaxUsed)304 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 305 IdentifierInfo *scopeName, SourceLocation scopeLoc, 306 IdentifierInfo *getterId, IdentifierInfo *setterId, 307 Syntax syntaxUsed) 308 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 309 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), 310 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 311 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), 312 NextInPosition(nullptr), NextInPool(nullptr) { 313 new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); 314 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 315 } 316 317 friend class AttributePool; 318 friend class AttributeFactory; 319 320 public: 321 enum Kind { 322 #define PARSED_ATTR(NAME) AT_##NAME, 323 #include "clang/Sema/AttrParsedAttrList.inc" 324 #undef PARSED_ATTR 325 IgnoredAttribute, 326 UnknownAttribute 327 }; 328 getName()329 IdentifierInfo *getName() const { return AttrName; } getLoc()330 SourceLocation getLoc() const { return AttrRange.getBegin(); } getRange()331 SourceRange getRange() const { return AttrRange; } 332 hasScope()333 bool hasScope() const { return ScopeName; } getScopeName()334 IdentifierInfo *getScopeName() const { return ScopeName; } getScopeLoc()335 SourceLocation getScopeLoc() const { return ScopeLoc; } 336 hasParsedType()337 bool hasParsedType() const { return HasParsedType; } 338 339 /// Is this the Microsoft __declspec(property) attribute? isDeclspecPropertyAttribute()340 bool isDeclspecPropertyAttribute() const { 341 return IsProperty; 342 } 343 isAlignasAttribute()344 bool isAlignasAttribute() const { 345 // FIXME: Use a better mechanism to determine this. 346 return getKind() == AT_Aligned && isKeywordAttribute(); 347 } 348 isDeclspecAttribute()349 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } isCXX11Attribute()350 bool isCXX11Attribute() const { 351 return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); 352 } isKeywordAttribute()353 bool isKeywordAttribute() const { 354 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; 355 } 356 isContextSensitiveKeywordAttribute()357 bool isContextSensitiveKeywordAttribute() const { 358 return SyntaxUsed == AS_ContextSensitiveKeyword; 359 } 360 isInvalid()361 bool isInvalid() const { return Invalid; } 362 void setInvalid(bool b = true) const { Invalid = b; } 363 isUsedAsTypeAttr()364 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } setUsedAsTypeAttr()365 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 366 isPackExpansion()367 bool isPackExpansion() const { return EllipsisLoc.isValid(); } getEllipsisLoc()368 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 369 getKind()370 Kind getKind() const { return Kind(AttrKind); } 371 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, 372 Syntax SyntaxUsed); 373 getNext()374 AttributeList *getNext() const { return NextInPosition; } setNext(AttributeList * N)375 void setNext(AttributeList *N) { NextInPosition = N; } 376 377 /// getNumArgs - Return the number of actual arguments to this attribute. getNumArgs()378 unsigned getNumArgs() const { return NumArgs; } 379 380 /// getArg - Return the specified argument. getArg(unsigned Arg)381 ArgsUnion getArg(unsigned Arg) const { 382 assert(Arg < NumArgs && "Arg access out of range!"); 383 return getArgsBuffer()[Arg]; 384 } 385 isArgExpr(unsigned Arg)386 bool isArgExpr(unsigned Arg) const { 387 return Arg < NumArgs && getArg(Arg).is<Expr*>(); 388 } getArgAsExpr(unsigned Arg)389 Expr *getArgAsExpr(unsigned Arg) const { 390 return getArg(Arg).get<Expr*>(); 391 } 392 isArgIdent(unsigned Arg)393 bool isArgIdent(unsigned Arg) const { 394 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); 395 } getArgAsIdent(unsigned Arg)396 IdentifierLoc *getArgAsIdent(unsigned Arg) const { 397 return getArg(Arg).get<IdentifierLoc*>(); 398 } 399 getAvailabilityIntroduced()400 const AvailabilityChange &getAvailabilityIntroduced() const { 401 assert(getKind() == AT_Availability && "Not an availability attribute"); 402 return getAvailabilitySlot(IntroducedSlot); 403 } 404 getAvailabilityDeprecated()405 const AvailabilityChange &getAvailabilityDeprecated() const { 406 assert(getKind() == AT_Availability && "Not an availability attribute"); 407 return getAvailabilitySlot(DeprecatedSlot); 408 } 409 getAvailabilityObsoleted()410 const AvailabilityChange &getAvailabilityObsoleted() const { 411 assert(getKind() == AT_Availability && "Not an availability attribute"); 412 return getAvailabilitySlot(ObsoletedSlot); 413 } 414 getUnavailableLoc()415 SourceLocation getUnavailableLoc() const { 416 assert(getKind() == AT_Availability && "Not an availability attribute"); 417 return UnavailableLoc; 418 } 419 getMessageExpr()420 const Expr * getMessageExpr() const { 421 assert(getKind() == AT_Availability && "Not an availability attribute"); 422 return MessageExpr; 423 } 424 getMatchingCType()425 const ParsedType &getMatchingCType() const { 426 assert(getKind() == AT_TypeTagForDatatype && 427 "Not a type_tag_for_datatype attribute"); 428 return *getTypeTagForDatatypeDataSlot().MatchingCType; 429 } 430 getLayoutCompatible()431 bool getLayoutCompatible() const { 432 assert(getKind() == AT_TypeTagForDatatype && 433 "Not a type_tag_for_datatype attribute"); 434 return getTypeTagForDatatypeDataSlot().LayoutCompatible; 435 } 436 getMustBeNull()437 bool getMustBeNull() const { 438 assert(getKind() == AT_TypeTagForDatatype && 439 "Not a type_tag_for_datatype attribute"); 440 return getTypeTagForDatatypeDataSlot().MustBeNull; 441 } 442 getTypeArg()443 const ParsedType &getTypeArg() const { 444 assert(HasParsedType && "Not a type attribute"); 445 return getTypeBuffer(); 446 } 447 getPropertyData()448 const PropertyData &getPropertyData() const { 449 assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute"); 450 return getPropertyDataBuffer(); 451 } 452 453 /// \brief Get an index into the attribute spelling list 454 /// defined in Attr.td. This index is used by an attribute 455 /// to pretty print itself. 456 unsigned getAttributeSpellingListIndex() const; 457 458 bool isTargetSpecificAttr() const; 459 bool isTypeAttr() const; 460 461 bool hasCustomParsing() const; 462 unsigned getMinArgs() const; 463 unsigned getMaxArgs() const; 464 bool hasVariadicArg() const; 465 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 466 bool diagnoseLangOpts(class Sema &S) const; 467 bool existsInTarget(const TargetInfo &Target) const; 468 bool isKnownToGCC() const; 469 470 /// \brief If the parsed attribute has a semantic equivalent, and it would 471 /// have a semantic Spelling enumeration (due to having semantically-distinct 472 /// spelling variations), return the value of that semantic spelling. If the 473 /// parsed attribute does not have a semantic equivalent, or would not have 474 /// a Spelling enumeration, the value UINT_MAX is returned. 475 unsigned getSemanticSpelling() const; 476 }; 477 478 /// A factory, from which one makes pools, from which one creates 479 /// individual attributes which are deallocated with the pool. 480 /// 481 /// Note that it's tolerably cheap to create and destroy one of 482 /// these as long as you don't actually allocate anything in it. 483 class AttributeFactory { 484 public: 485 enum { 486 /// The required allocation size of an availability attribute, 487 /// which we want to ensure is a multiple of sizeof(void*). 488 AvailabilityAllocSize = 489 sizeof(AttributeList) 490 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + 491 sizeof(ArgsUnion) - 1) 492 / sizeof(void*) * sizeof(void*)), 493 TypeTagForDatatypeAllocSize = 494 sizeof(AttributeList) 495 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + 496 sizeof(ArgsUnion) - 1) 497 / sizeof(void*) * sizeof(void*), 498 PropertyAllocSize = 499 sizeof(AttributeList) 500 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) 501 / sizeof(void*) * sizeof(void*) 502 }; 503 504 private: 505 enum { 506 /// The number of free lists we want to be sure to support 507 /// inline. This is just enough that availability attributes 508 /// don't surpass it. It's actually very unlikely we'll see an 509 /// attribute that needs more than that; on x86-64 you'd need 10 510 /// expression arguments, and on i386 you'd need 19. 511 InlineFreeListsCapacity = 512 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 513 }; 514 515 llvm::BumpPtrAllocator Alloc; 516 517 /// Free lists. The index is determined by the following formula: 518 /// (size - sizeof(AttributeList)) / sizeof(void*) 519 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 520 521 // The following are the private interface used by AttributePool. 522 friend class AttributePool; 523 524 /// Allocate an attribute of the given size. 525 void *allocate(size_t size); 526 527 /// Reclaim all the attributes in the given pool chain, which is 528 /// non-empty. Note that the current implementation is safe 529 /// against reclaiming things which were not actually allocated 530 /// with the allocator, although of course it's important to make 531 /// sure that their allocator lives at least as long as this one. 532 void reclaimPool(AttributeList *head); 533 534 public: 535 AttributeFactory(); 536 ~AttributeFactory(); 537 }; 538 539 class AttributePool { 540 AttributeFactory &Factory; 541 AttributeList *Head; 542 allocate(size_t size)543 void *allocate(size_t size) { 544 return Factory.allocate(size); 545 } 546 add(AttributeList * attr)547 AttributeList *add(AttributeList *attr) { 548 // We don't care about the order of the pool. 549 attr->NextInPool = Head; 550 Head = attr; 551 return attr; 552 } 553 554 void takePool(AttributeList *pool); 555 556 public: 557 /// Create a new pool for a factory. AttributePool(AttributeFactory & factory)558 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} 559 560 AttributePool(const AttributePool &) = delete; 561 562 /// Move the given pool's allocations to this pool. AttributePool(AttributePool && pool)563 AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) { 564 pool.Head = nullptr; 565 } 566 getFactory()567 AttributeFactory &getFactory() const { return Factory; } 568 clear()569 void clear() { 570 if (Head) { 571 Factory.reclaimPool(Head); 572 Head = nullptr; 573 } 574 } 575 576 /// Take the given pool's allocations and add them to this pool. takeAllFrom(AttributePool & pool)577 void takeAllFrom(AttributePool &pool) { 578 if (pool.Head) { 579 takePool(pool.Head); 580 pool.Head = nullptr; 581 } 582 } 583 ~AttributePool()584 ~AttributePool() { 585 if (Head) Factory.reclaimPool(Head); 586 } 587 588 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 589 IdentifierInfo *scopeName, SourceLocation scopeLoc, 590 ArgsUnion *args, unsigned numArgs, 591 AttributeList::Syntax syntax, 592 SourceLocation ellipsisLoc = SourceLocation()) { 593 void *memory = allocate(sizeof(AttributeList) 594 + numArgs * sizeof(ArgsUnion)); 595 return add(new (memory) AttributeList(attrName, attrRange, 596 scopeName, scopeLoc, 597 args, numArgs, syntax, 598 ellipsisLoc)); 599 } 600 create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)601 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 602 IdentifierInfo *scopeName, SourceLocation scopeLoc, 603 IdentifierLoc *Param, 604 const AvailabilityChange &introduced, 605 const AvailabilityChange &deprecated, 606 const AvailabilityChange &obsoleted, 607 SourceLocation unavailable, 608 const Expr *MessageExpr, 609 AttributeList::Syntax syntax) { 610 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 611 return add(new (memory) AttributeList(attrName, attrRange, 612 scopeName, scopeLoc, 613 Param, introduced, deprecated, 614 obsoleted, unavailable, MessageExpr, 615 syntax)); 616 } 617 create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)618 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 619 IdentifierInfo *scopeName, SourceLocation scopeLoc, 620 IdentifierLoc *Param1, 621 IdentifierLoc *Param2, 622 IdentifierLoc *Param3, 623 AttributeList::Syntax syntax) { 624 size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); 625 void *memory = allocate(size); 626 return add(new (memory) AttributeList(attrName, attrRange, 627 scopeName, scopeLoc, 628 Param1, Param2, Param3, 629 syntax)); 630 } 631 createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)632 AttributeList *createTypeTagForDatatype( 633 IdentifierInfo *attrName, SourceRange attrRange, 634 IdentifierInfo *scopeName, SourceLocation scopeLoc, 635 IdentifierLoc *argumentKind, ParsedType matchingCType, 636 bool layoutCompatible, bool mustBeNull, 637 AttributeList::Syntax syntax) { 638 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 639 return add(new (memory) AttributeList(attrName, attrRange, 640 scopeName, scopeLoc, 641 argumentKind, matchingCType, 642 layoutCompatible, mustBeNull, 643 syntax)); 644 } 645 createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)646 AttributeList *createTypeAttribute( 647 IdentifierInfo *attrName, SourceRange attrRange, 648 IdentifierInfo *scopeName, SourceLocation scopeLoc, 649 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 650 void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); 651 return add(new (memory) AttributeList(attrName, attrRange, 652 scopeName, scopeLoc, 653 typeArg, syntaxUsed)); 654 } 655 createPropertyAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)656 AttributeList *createPropertyAttribute( 657 IdentifierInfo *attrName, SourceRange attrRange, 658 IdentifierInfo *scopeName, SourceLocation scopeLoc, 659 IdentifierInfo *getterId, IdentifierInfo *setterId, 660 AttributeList::Syntax syntaxUsed) { 661 void *memory = allocate(AttributeFactory::PropertyAllocSize); 662 return add(new (memory) AttributeList(attrName, attrRange, 663 scopeName, scopeLoc, 664 getterId, setterId, 665 syntaxUsed)); 666 } 667 }; 668 669 /// ParsedAttributes - A collection of parsed attributes. Currently 670 /// we don't differentiate between the various attribute syntaxes, 671 /// which is basically silly. 672 /// 673 /// Right now this is a very lightweight container, but the expectation 674 /// is that this will become significantly more serious. 675 class ParsedAttributes { 676 public: ParsedAttributes(AttributeFactory & factory)677 ParsedAttributes(AttributeFactory &factory) 678 : pool(factory), list(nullptr) { 679 } 680 681 ParsedAttributes(const ParsedAttributes &) = delete; 682 getPool()683 AttributePool &getPool() const { return pool; } 684 empty()685 bool empty() const { return list == nullptr; } 686 add(AttributeList * newAttr)687 void add(AttributeList *newAttr) { 688 assert(newAttr); 689 assert(newAttr->getNext() == nullptr); 690 newAttr->setNext(list); 691 list = newAttr; 692 } 693 addAll(AttributeList * newList)694 void addAll(AttributeList *newList) { 695 if (!newList) return; 696 697 AttributeList *lastInNewList = newList; 698 while (AttributeList *next = lastInNewList->getNext()) 699 lastInNewList = next; 700 701 lastInNewList->setNext(list); 702 list = newList; 703 } 704 set(AttributeList * newList)705 void set(AttributeList *newList) { 706 list = newList; 707 } 708 takeAllFrom(ParsedAttributes & attrs)709 void takeAllFrom(ParsedAttributes &attrs) { 710 addAll(attrs.list); 711 attrs.list = nullptr; 712 pool.takeAllFrom(attrs.pool); 713 } 714 clear()715 void clear() { list = nullptr; pool.clear(); } getList()716 AttributeList *getList() const { return list; } 717 718 /// Returns a reference to the attribute list. Try not to introduce 719 /// dependencies on this method, it may not be long-lived. getListRef()720 AttributeList *&getListRef() { return list; } 721 722 /// Add attribute with expression arguments. 723 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 724 IdentifierInfo *scopeName, SourceLocation scopeLoc, 725 ArgsUnion *args, unsigned numArgs, 726 AttributeList::Syntax syntax, 727 SourceLocation ellipsisLoc = SourceLocation()) { 728 AttributeList *attr = 729 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, 730 syntax, ellipsisLoc); 731 add(attr); 732 return attr; 733 } 734 735 /// Add availability attribute. addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)736 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 737 IdentifierInfo *scopeName, SourceLocation scopeLoc, 738 IdentifierLoc *Param, 739 const AvailabilityChange &introduced, 740 const AvailabilityChange &deprecated, 741 const AvailabilityChange &obsoleted, 742 SourceLocation unavailable, 743 const Expr *MessageExpr, 744 AttributeList::Syntax syntax) { 745 AttributeList *attr = 746 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, 747 deprecated, obsoleted, unavailable, MessageExpr, syntax); 748 add(attr); 749 return attr; 750 } 751 752 /// Add objc_bridge_related attribute. addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)753 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 754 IdentifierInfo *scopeName, SourceLocation scopeLoc, 755 IdentifierLoc *Param1, 756 IdentifierLoc *Param2, 757 IdentifierLoc *Param3, 758 AttributeList::Syntax syntax) { 759 AttributeList *attr = 760 pool.create(attrName, attrRange, scopeName, scopeLoc, 761 Param1, Param2, Param3, syntax); 762 add(attr); 763 return attr; 764 } 765 766 /// Add type_tag_for_datatype attribute. addNewTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)767 AttributeList *addNewTypeTagForDatatype( 768 IdentifierInfo *attrName, SourceRange attrRange, 769 IdentifierInfo *scopeName, SourceLocation scopeLoc, 770 IdentifierLoc *argumentKind, ParsedType matchingCType, 771 bool layoutCompatible, bool mustBeNull, 772 AttributeList::Syntax syntax) { 773 AttributeList *attr = 774 pool.createTypeTagForDatatype(attrName, attrRange, 775 scopeName, scopeLoc, 776 argumentKind, matchingCType, 777 layoutCompatible, mustBeNull, syntax); 778 add(attr); 779 return attr; 780 } 781 782 /// Add an attribute with a single type argument. 783 AttributeList * addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)784 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 785 IdentifierInfo *scopeName, SourceLocation scopeLoc, 786 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 787 AttributeList *attr = 788 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, 789 typeArg, syntaxUsed); 790 add(attr); 791 return attr; 792 } 793 794 /// Add microsoft __delspec(property) attribute. 795 AttributeList * addNewPropertyAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)796 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 797 IdentifierInfo *scopeName, SourceLocation scopeLoc, 798 IdentifierInfo *getterId, IdentifierInfo *setterId, 799 AttributeList::Syntax syntaxUsed) { 800 AttributeList *attr = 801 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 802 getterId, setterId, syntaxUsed); 803 add(attr); 804 return attr; 805 } 806 807 private: 808 mutable AttributePool pool; 809 AttributeList *list; 810 }; 811 812 /// These constants match the enumerated choices of 813 /// err_attribute_argument_n_type and err_attribute_argument_type. 814 enum AttributeArgumentNType { 815 AANT_ArgumentIntOrBool, 816 AANT_ArgumentIntegerConstant, 817 AANT_ArgumentString, 818 AANT_ArgumentIdentifier 819 }; 820 821 /// These constants match the enumerated choices of 822 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 823 enum AttributeDeclKind { 824 ExpectedFunction, 825 ExpectedUnion, 826 ExpectedVariableOrFunction, 827 ExpectedFunctionOrMethod, 828 ExpectedParameter, 829 ExpectedFunctionMethodOrBlock, 830 ExpectedFunctionMethodOrClass, 831 ExpectedFunctionMethodOrParameter, 832 ExpectedClass, 833 ExpectedEnum, 834 ExpectedVariable, 835 ExpectedMethod, 836 ExpectedVariableFunctionOrLabel, 837 ExpectedFieldOrGlobalVar, 838 ExpectedStruct, 839 ExpectedVariableOrTypedef, 840 ExpectedTLSVar, 841 ExpectedVariableOrField, 842 ExpectedVariableFieldOrTag, 843 ExpectedTypeOrNamespace, 844 ExpectedObjectiveCInterface, 845 ExpectedMethodOrProperty, 846 ExpectedStructOrUnion, 847 ExpectedStructOrUnionOrClass, 848 ExpectedType, 849 ExpectedObjCInstanceMethod, 850 ExpectedObjCInterfaceDeclInitMethod, 851 ExpectedFunctionVariableOrClass, 852 ExpectedObjectiveCProtocol, 853 ExpectedFunctionGlobalVarMethodOrProperty, 854 ExpectedStructOrUnionOrTypedef, 855 ExpectedStructOrTypedef, 856 ExpectedObjectiveCInterfaceOrProtocol, 857 ExpectedKernelFunction, 858 ExpectedFunctionWithProtoType 859 }; 860 861 } // end namespace clang 862 863 #endif 864