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_ATTRLIST_H 16 #define LLVM_CLANG_SEMA_ATTRLIST_H 17 18 #include "clang/Basic/SourceLocation.h" 19 #include "clang/Basic/VersionTuple.h" 20 #include "clang/Sema/Ownership.h" 21 #include "llvm/ADT/PointerUnion.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/ADT/Triple.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 /// #pragma ... 85 AS_Pragma 86 }; 87 88 private: 89 IdentifierInfo *AttrName; 90 IdentifierInfo *ScopeName; 91 SourceRange AttrRange; 92 SourceLocation ScopeLoc; 93 SourceLocation EllipsisLoc; 94 95 /// The number of expression arguments this attribute has. 96 /// The expressions themselves are stored after the object. 97 unsigned NumArgs : 16; 98 99 /// Corresponds to the Syntax enum. 100 unsigned SyntaxUsed : 2; 101 102 /// True if already diagnosed as invalid. 103 mutable unsigned Invalid : 1; 104 105 /// True if this attribute was used as a type attribute. 106 mutable unsigned UsedAsTypeAttr : 1; 107 108 /// True if this has the extra information associated with an 109 /// availability attribute. 110 unsigned IsAvailability : 1; 111 112 /// True if this has extra information associated with a 113 /// type_tag_for_datatype attribute. 114 unsigned IsTypeTagForDatatype : 1; 115 116 /// True if this has extra information associated with a 117 /// Microsoft __delcspec(property) attribute. 118 unsigned IsProperty : 1; 119 120 /// True if this has a ParsedType 121 unsigned HasParsedType : 1; 122 123 unsigned AttrKind : 8; 124 125 /// \brief The location of the 'unavailable' keyword in an 126 /// availability attribute. 127 SourceLocation UnavailableLoc; 128 129 const Expr *MessageExpr; 130 131 /// The next attribute in the current position. 132 AttributeList *NextInPosition; 133 134 /// The next attribute allocated in the current Pool. 135 AttributeList *NextInPool; 136 137 /// Arguments, if any, are stored immediately following the object. getArgsBuffer()138 ArgsUnion *getArgsBuffer() { 139 return reinterpret_cast<ArgsUnion*>(this+1); 140 } 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 &) LLVM_DELETED_FUNCTION; 208 void operator=(const AttributeList &) LLVM_DELETED_FUNCTION; 209 void operator delete(void *) LLVM_DELETED_FUNCTION; 210 ~AttributeList() LLVM_DELETED_FUNCTION; 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 && SyntaxUsed == AS_Keyword; 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 { return SyntaxUsed == AS_Keyword; } 354 isInvalid()355 bool isInvalid() const { return Invalid; } 356 void setInvalid(bool b = true) const { Invalid = b; } 357 isUsedAsTypeAttr()358 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } setUsedAsTypeAttr()359 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 360 isPackExpansion()361 bool isPackExpansion() const { return EllipsisLoc.isValid(); } getEllipsisLoc()362 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 363 getKind()364 Kind getKind() const { return Kind(AttrKind); } 365 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, 366 Syntax SyntaxUsed); 367 getNext()368 AttributeList *getNext() const { return NextInPosition; } setNext(AttributeList * N)369 void setNext(AttributeList *N) { NextInPosition = N; } 370 371 /// getNumArgs - Return the number of actual arguments to this attribute. getNumArgs()372 unsigned getNumArgs() const { return NumArgs; } 373 374 /// getArg - Return the specified argument. getArg(unsigned Arg)375 ArgsUnion getArg(unsigned Arg) const { 376 assert(Arg < NumArgs && "Arg access out of range!"); 377 return getArgsBuffer()[Arg]; 378 } 379 isArgExpr(unsigned Arg)380 bool isArgExpr(unsigned Arg) const { 381 return Arg < NumArgs && getArg(Arg).is<Expr*>(); 382 } getArgAsExpr(unsigned Arg)383 Expr *getArgAsExpr(unsigned Arg) const { 384 return getArg(Arg).get<Expr*>(); 385 } 386 isArgIdent(unsigned Arg)387 bool isArgIdent(unsigned Arg) const { 388 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); 389 } getArgAsIdent(unsigned Arg)390 IdentifierLoc *getArgAsIdent(unsigned Arg) const { 391 return getArg(Arg).get<IdentifierLoc*>(); 392 } 393 getAvailabilityIntroduced()394 const AvailabilityChange &getAvailabilityIntroduced() const { 395 assert(getKind() == AT_Availability && "Not an availability attribute"); 396 return getAvailabilitySlot(IntroducedSlot); 397 } 398 getAvailabilityDeprecated()399 const AvailabilityChange &getAvailabilityDeprecated() const { 400 assert(getKind() == AT_Availability && "Not an availability attribute"); 401 return getAvailabilitySlot(DeprecatedSlot); 402 } 403 getAvailabilityObsoleted()404 const AvailabilityChange &getAvailabilityObsoleted() const { 405 assert(getKind() == AT_Availability && "Not an availability attribute"); 406 return getAvailabilitySlot(ObsoletedSlot); 407 } 408 getUnavailableLoc()409 SourceLocation getUnavailableLoc() const { 410 assert(getKind() == AT_Availability && "Not an availability attribute"); 411 return UnavailableLoc; 412 } 413 getMessageExpr()414 const Expr * getMessageExpr() const { 415 assert(getKind() == AT_Availability && "Not an availability attribute"); 416 return MessageExpr; 417 } 418 getMatchingCType()419 const ParsedType &getMatchingCType() const { 420 assert(getKind() == AT_TypeTagForDatatype && 421 "Not a type_tag_for_datatype attribute"); 422 return *getTypeTagForDatatypeDataSlot().MatchingCType; 423 } 424 getLayoutCompatible()425 bool getLayoutCompatible() const { 426 assert(getKind() == AT_TypeTagForDatatype && 427 "Not a type_tag_for_datatype attribute"); 428 return getTypeTagForDatatypeDataSlot().LayoutCompatible; 429 } 430 getMustBeNull()431 bool getMustBeNull() const { 432 assert(getKind() == AT_TypeTagForDatatype && 433 "Not a type_tag_for_datatype attribute"); 434 return getTypeTagForDatatypeDataSlot().MustBeNull; 435 } 436 getTypeArg()437 const ParsedType &getTypeArg() const { 438 assert(HasParsedType && "Not a type attribute"); 439 return getTypeBuffer(); 440 } 441 getPropertyData()442 const PropertyData &getPropertyData() const { 443 assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute"); 444 return getPropertyDataBuffer(); 445 } 446 447 /// \brief Get an index into the attribute spelling list 448 /// defined in Attr.td. This index is used by an attribute 449 /// to pretty print itself. 450 unsigned getAttributeSpellingListIndex() const; 451 452 bool isTargetSpecificAttr() const; 453 bool isTypeAttr() const; 454 455 bool hasCustomParsing() const; 456 unsigned getMinArgs() const; 457 unsigned getMaxArgs() const; 458 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 459 bool diagnoseLangOpts(class Sema &S) const; 460 bool existsInTarget(const llvm::Triple &T) const; 461 bool isKnownToGCC() const; 462 463 /// \brief If the parsed attribute has a semantic equivalent, and it would 464 /// have a semantic Spelling enumeration (due to having semantically-distinct 465 /// spelling variations), return the value of that semantic spelling. If the 466 /// parsed attribute does not have a semantic equivalent, or would not have 467 /// a Spelling enumeration, the value UINT_MAX is returned. 468 unsigned getSemanticSpelling() const; 469 }; 470 471 /// A factory, from which one makes pools, from which one creates 472 /// individual attributes which are deallocated with the pool. 473 /// 474 /// Note that it's tolerably cheap to create and destroy one of 475 /// these as long as you don't actually allocate anything in it. 476 class AttributeFactory { 477 public: 478 enum { 479 /// The required allocation size of an availability attribute, 480 /// which we want to ensure is a multiple of sizeof(void*). 481 AvailabilityAllocSize = 482 sizeof(AttributeList) 483 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + 484 sizeof(ArgsUnion) - 1) 485 / sizeof(void*) * sizeof(void*)), 486 TypeTagForDatatypeAllocSize = 487 sizeof(AttributeList) 488 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + 489 sizeof(ArgsUnion) - 1) 490 / sizeof(void*) * sizeof(void*), 491 PropertyAllocSize = 492 sizeof(AttributeList) 493 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) 494 / sizeof(void*) * sizeof(void*) 495 }; 496 497 private: 498 enum { 499 /// The number of free lists we want to be sure to support 500 /// inline. This is just enough that availability attributes 501 /// don't surpass it. It's actually very unlikely we'll see an 502 /// attribute that needs more than that; on x86-64 you'd need 10 503 /// expression arguments, and on i386 you'd need 19. 504 InlineFreeListsCapacity = 505 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 506 }; 507 508 llvm::BumpPtrAllocator Alloc; 509 510 /// Free lists. The index is determined by the following formula: 511 /// (size - sizeof(AttributeList)) / sizeof(void*) 512 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 513 514 // The following are the private interface used by AttributePool. 515 friend class AttributePool; 516 517 /// Allocate an attribute of the given size. 518 void *allocate(size_t size); 519 520 /// Reclaim all the attributes in the given pool chain, which is 521 /// non-empty. Note that the current implementation is safe 522 /// against reclaiming things which were not actually allocated 523 /// with the allocator, although of course it's important to make 524 /// sure that their allocator lives at least as long as this one. 525 void reclaimPool(AttributeList *head); 526 527 public: 528 AttributeFactory(); 529 ~AttributeFactory(); 530 }; 531 532 class AttributePool { 533 AttributeFactory &Factory; 534 AttributeList *Head; 535 allocate(size_t size)536 void *allocate(size_t size) { 537 return Factory.allocate(size); 538 } 539 add(AttributeList * attr)540 AttributeList *add(AttributeList *attr) { 541 // We don't care about the order of the pool. 542 attr->NextInPool = Head; 543 Head = attr; 544 return attr; 545 } 546 547 void takePool(AttributeList *pool); 548 549 public: 550 /// Create a new pool for a factory. AttributePool(AttributeFactory & factory)551 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} 552 553 /// Move the given pool's allocations to this pool. AttributePool(AttributePool & pool)554 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 555 pool.Head = nullptr; 556 } 557 getFactory()558 AttributeFactory &getFactory() const { return Factory; } 559 clear()560 void clear() { 561 if (Head) { 562 Factory.reclaimPool(Head); 563 Head = nullptr; 564 } 565 } 566 567 /// Take the given pool's allocations and add them to this pool. takeAllFrom(AttributePool & pool)568 void takeAllFrom(AttributePool &pool) { 569 if (pool.Head) { 570 takePool(pool.Head); 571 pool.Head = nullptr; 572 } 573 } 574 ~AttributePool()575 ~AttributePool() { 576 if (Head) Factory.reclaimPool(Head); 577 } 578 579 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 580 IdentifierInfo *scopeName, SourceLocation scopeLoc, 581 ArgsUnion *args, unsigned numArgs, 582 AttributeList::Syntax syntax, 583 SourceLocation ellipsisLoc = SourceLocation()) { 584 void *memory = allocate(sizeof(AttributeList) 585 + numArgs * sizeof(ArgsUnion)); 586 return add(new (memory) AttributeList(attrName, attrRange, 587 scopeName, scopeLoc, 588 args, numArgs, syntax, 589 ellipsisLoc)); 590 } 591 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)592 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 593 IdentifierInfo *scopeName, SourceLocation scopeLoc, 594 IdentifierLoc *Param, 595 const AvailabilityChange &introduced, 596 const AvailabilityChange &deprecated, 597 const AvailabilityChange &obsoleted, 598 SourceLocation unavailable, 599 const Expr *MessageExpr, 600 AttributeList::Syntax syntax) { 601 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 602 return add(new (memory) AttributeList(attrName, attrRange, 603 scopeName, scopeLoc, 604 Param, introduced, deprecated, 605 obsoleted, unavailable, MessageExpr, 606 syntax)); 607 } 608 create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)609 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 610 IdentifierInfo *scopeName, SourceLocation scopeLoc, 611 IdentifierLoc *Param1, 612 IdentifierLoc *Param2, 613 IdentifierLoc *Param3, 614 AttributeList::Syntax syntax) { 615 size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); 616 void *memory = allocate(size); 617 return add(new (memory) AttributeList(attrName, attrRange, 618 scopeName, scopeLoc, 619 Param1, Param2, Param3, 620 syntax)); 621 } 622 createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)623 AttributeList *createTypeTagForDatatype( 624 IdentifierInfo *attrName, SourceRange attrRange, 625 IdentifierInfo *scopeName, SourceLocation scopeLoc, 626 IdentifierLoc *argumentKind, ParsedType matchingCType, 627 bool layoutCompatible, bool mustBeNull, 628 AttributeList::Syntax syntax) { 629 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 630 return add(new (memory) AttributeList(attrName, attrRange, 631 scopeName, scopeLoc, 632 argumentKind, matchingCType, 633 layoutCompatible, mustBeNull, 634 syntax)); 635 } 636 createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)637 AttributeList *createTypeAttribute( 638 IdentifierInfo *attrName, SourceRange attrRange, 639 IdentifierInfo *scopeName, SourceLocation scopeLoc, 640 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 641 void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); 642 return add(new (memory) AttributeList(attrName, attrRange, 643 scopeName, scopeLoc, 644 typeArg, syntaxUsed)); 645 } 646 createPropertyAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)647 AttributeList *createPropertyAttribute( 648 IdentifierInfo *attrName, SourceRange attrRange, 649 IdentifierInfo *scopeName, SourceLocation scopeLoc, 650 IdentifierInfo *getterId, IdentifierInfo *setterId, 651 AttributeList::Syntax syntaxUsed) { 652 void *memory = allocate(AttributeFactory::PropertyAllocSize); 653 return add(new (memory) AttributeList(attrName, attrRange, 654 scopeName, scopeLoc, 655 getterId, setterId, 656 syntaxUsed)); 657 } 658 }; 659 660 /// ParsedAttributes - A collection of parsed attributes. Currently 661 /// we don't differentiate between the various attribute syntaxes, 662 /// which is basically silly. 663 /// 664 /// Right now this is a very lightweight container, but the expectation 665 /// is that this will become significantly more serious. 666 class ParsedAttributes { 667 public: ParsedAttributes(AttributeFactory & factory)668 ParsedAttributes(AttributeFactory &factory) 669 : pool(factory), list(nullptr) { 670 } 671 672 ParsedAttributes(const ParsedAttributes &) LLVM_DELETED_FUNCTION; 673 getPool()674 AttributePool &getPool() const { return pool; } 675 empty()676 bool empty() const { return list == nullptr; } 677 add(AttributeList * newAttr)678 void add(AttributeList *newAttr) { 679 assert(newAttr); 680 assert(newAttr->getNext() == nullptr); 681 newAttr->setNext(list); 682 list = newAttr; 683 } 684 addAll(AttributeList * newList)685 void addAll(AttributeList *newList) { 686 if (!newList) return; 687 688 AttributeList *lastInNewList = newList; 689 while (AttributeList *next = lastInNewList->getNext()) 690 lastInNewList = next; 691 692 lastInNewList->setNext(list); 693 list = newList; 694 } 695 set(AttributeList * newList)696 void set(AttributeList *newList) { 697 list = newList; 698 } 699 takeAllFrom(ParsedAttributes & attrs)700 void takeAllFrom(ParsedAttributes &attrs) { 701 addAll(attrs.list); 702 attrs.list = nullptr; 703 pool.takeAllFrom(attrs.pool); 704 } 705 clear()706 void clear() { list = nullptr; pool.clear(); } getList()707 AttributeList *getList() const { return list; } 708 709 /// Returns a reference to the attribute list. Try not to introduce 710 /// dependencies on this method, it may not be long-lived. getListRef()711 AttributeList *&getListRef() { return list; } 712 713 /// Add attribute with expression arguments. 714 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 715 IdentifierInfo *scopeName, SourceLocation scopeLoc, 716 ArgsUnion *args, unsigned numArgs, 717 AttributeList::Syntax syntax, 718 SourceLocation ellipsisLoc = SourceLocation()) { 719 AttributeList *attr = 720 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, 721 syntax, ellipsisLoc); 722 add(attr); 723 return attr; 724 } 725 726 /// 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)727 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 728 IdentifierInfo *scopeName, SourceLocation scopeLoc, 729 IdentifierLoc *Param, 730 const AvailabilityChange &introduced, 731 const AvailabilityChange &deprecated, 732 const AvailabilityChange &obsoleted, 733 SourceLocation unavailable, 734 const Expr *MessageExpr, 735 AttributeList::Syntax syntax) { 736 AttributeList *attr = 737 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, 738 deprecated, obsoleted, unavailable, MessageExpr, syntax); 739 add(attr); 740 return attr; 741 } 742 743 /// Add objc_bridge_related attribute. addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)744 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 745 IdentifierInfo *scopeName, SourceLocation scopeLoc, 746 IdentifierLoc *Param1, 747 IdentifierLoc *Param2, 748 IdentifierLoc *Param3, 749 AttributeList::Syntax syntax) { 750 AttributeList *attr = 751 pool.create(attrName, attrRange, scopeName, scopeLoc, 752 Param1, Param2, Param3, syntax); 753 add(attr); 754 return attr; 755 } 756 757 /// 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)758 AttributeList *addNewTypeTagForDatatype( 759 IdentifierInfo *attrName, SourceRange attrRange, 760 IdentifierInfo *scopeName, SourceLocation scopeLoc, 761 IdentifierLoc *argumentKind, ParsedType matchingCType, 762 bool layoutCompatible, bool mustBeNull, 763 AttributeList::Syntax syntax) { 764 AttributeList *attr = 765 pool.createTypeTagForDatatype(attrName, attrRange, 766 scopeName, scopeLoc, 767 argumentKind, matchingCType, 768 layoutCompatible, mustBeNull, syntax); 769 add(attr); 770 return attr; 771 } 772 773 /// Add an attribute with a single type argument. 774 AttributeList * addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)775 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 776 IdentifierInfo *scopeName, SourceLocation scopeLoc, 777 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 778 AttributeList *attr = 779 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, 780 typeArg, syntaxUsed); 781 add(attr); 782 return attr; 783 } 784 785 /// Add microsoft __delspec(property) attribute. 786 AttributeList * addNewPropertyAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)787 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 788 IdentifierInfo *scopeName, SourceLocation scopeLoc, 789 IdentifierInfo *getterId, IdentifierInfo *setterId, 790 AttributeList::Syntax syntaxUsed) { 791 AttributeList *attr = 792 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 793 getterId, setterId, syntaxUsed); 794 add(attr); 795 return attr; 796 } 797 798 private: 799 mutable AttributePool pool; 800 AttributeList *list; 801 }; 802 803 /// These constants match the enumerated choices of 804 /// err_attribute_argument_n_type and err_attribute_argument_type. 805 enum AttributeArgumentNType { 806 AANT_ArgumentIntOrBool, 807 AANT_ArgumentIntegerConstant, 808 AANT_ArgumentString, 809 AANT_ArgumentIdentifier 810 }; 811 812 /// These constants match the enumerated choices of 813 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 814 enum AttributeDeclKind { 815 ExpectedFunction, 816 ExpectedUnion, 817 ExpectedVariableOrFunction, 818 ExpectedFunctionOrMethod, 819 ExpectedParameter, 820 ExpectedFunctionMethodOrBlock, 821 ExpectedFunctionMethodOrClass, 822 ExpectedFunctionMethodOrParameter, 823 ExpectedClass, 824 ExpectedVariable, 825 ExpectedMethod, 826 ExpectedVariableFunctionOrLabel, 827 ExpectedFieldOrGlobalVar, 828 ExpectedStruct, 829 ExpectedVariableFunctionOrTag, 830 ExpectedTLSVar, 831 ExpectedVariableOrField, 832 ExpectedVariableFieldOrTag, 833 ExpectedTypeOrNamespace, 834 ExpectedObjectiveCInterface, 835 ExpectedMethodOrProperty, 836 ExpectedStructOrUnion, 837 ExpectedStructOrUnionOrClass, 838 ExpectedType, 839 ExpectedObjCInstanceMethod, 840 ExpectedObjCInterfaceDeclInitMethod, 841 ExpectedFunctionVariableOrClass, 842 ExpectedObjectiveCProtocol, 843 ExpectedFunctionGlobalVarMethodOrProperty, 844 ExpectedStructOrTypedef 845 }; 846 847 } // end namespace clang 848 849 #endif 850