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/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 : 15; 98 99 /// Corresponds to the Syntax enum. 100 unsigned SyntaxUsed : 3; 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 &) = 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 && 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 hasVariadicArg() const; 459 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 460 bool diagnoseLangOpts(class Sema &S) const; 461 bool existsInTarget(const llvm::Triple &T) const; 462 bool isKnownToGCC() const; 463 464 /// \brief If the parsed attribute has a semantic equivalent, and it would 465 /// have a semantic Spelling enumeration (due to having semantically-distinct 466 /// spelling variations), return the value of that semantic spelling. If the 467 /// parsed attribute does not have a semantic equivalent, or would not have 468 /// a Spelling enumeration, the value UINT_MAX is returned. 469 unsigned getSemanticSpelling() const; 470 }; 471 472 /// A factory, from which one makes pools, from which one creates 473 /// individual attributes which are deallocated with the pool. 474 /// 475 /// Note that it's tolerably cheap to create and destroy one of 476 /// these as long as you don't actually allocate anything in it. 477 class AttributeFactory { 478 public: 479 enum { 480 /// The required allocation size of an availability attribute, 481 /// which we want to ensure is a multiple of sizeof(void*). 482 AvailabilityAllocSize = 483 sizeof(AttributeList) 484 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + 485 sizeof(ArgsUnion) - 1) 486 / sizeof(void*) * sizeof(void*)), 487 TypeTagForDatatypeAllocSize = 488 sizeof(AttributeList) 489 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + 490 sizeof(ArgsUnion) - 1) 491 / sizeof(void*) * sizeof(void*), 492 PropertyAllocSize = 493 sizeof(AttributeList) 494 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) 495 / sizeof(void*) * sizeof(void*) 496 }; 497 498 private: 499 enum { 500 /// The number of free lists we want to be sure to support 501 /// inline. This is just enough that availability attributes 502 /// don't surpass it. It's actually very unlikely we'll see an 503 /// attribute that needs more than that; on x86-64 you'd need 10 504 /// expression arguments, and on i386 you'd need 19. 505 InlineFreeListsCapacity = 506 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 507 }; 508 509 llvm::BumpPtrAllocator Alloc; 510 511 /// Free lists. The index is determined by the following formula: 512 /// (size - sizeof(AttributeList)) / sizeof(void*) 513 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 514 515 // The following are the private interface used by AttributePool. 516 friend class AttributePool; 517 518 /// Allocate an attribute of the given size. 519 void *allocate(size_t size); 520 521 /// Reclaim all the attributes in the given pool chain, which is 522 /// non-empty. Note that the current implementation is safe 523 /// against reclaiming things which were not actually allocated 524 /// with the allocator, although of course it's important to make 525 /// sure that their allocator lives at least as long as this one. 526 void reclaimPool(AttributeList *head); 527 528 public: 529 AttributeFactory(); 530 ~AttributeFactory(); 531 }; 532 533 class AttributePool { 534 AttributeFactory &Factory; 535 AttributeList *Head; 536 allocate(size_t size)537 void *allocate(size_t size) { 538 return Factory.allocate(size); 539 } 540 add(AttributeList * attr)541 AttributeList *add(AttributeList *attr) { 542 // We don't care about the order of the pool. 543 attr->NextInPool = Head; 544 Head = attr; 545 return attr; 546 } 547 548 void takePool(AttributeList *pool); 549 550 public: 551 /// Create a new pool for a factory. AttributePool(AttributeFactory & factory)552 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} 553 554 /// Move the given pool's allocations to this pool. AttributePool(AttributePool & pool)555 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 556 pool.Head = nullptr; 557 } 558 getFactory()559 AttributeFactory &getFactory() const { return Factory; } 560 clear()561 void clear() { 562 if (Head) { 563 Factory.reclaimPool(Head); 564 Head = nullptr; 565 } 566 } 567 568 /// Take the given pool's allocations and add them to this pool. takeAllFrom(AttributePool & pool)569 void takeAllFrom(AttributePool &pool) { 570 if (pool.Head) { 571 takePool(pool.Head); 572 pool.Head = nullptr; 573 } 574 } 575 ~AttributePool()576 ~AttributePool() { 577 if (Head) Factory.reclaimPool(Head); 578 } 579 580 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 581 IdentifierInfo *scopeName, SourceLocation scopeLoc, 582 ArgsUnion *args, unsigned numArgs, 583 AttributeList::Syntax syntax, 584 SourceLocation ellipsisLoc = SourceLocation()) { 585 void *memory = allocate(sizeof(AttributeList) 586 + numArgs * sizeof(ArgsUnion)); 587 return add(new (memory) AttributeList(attrName, attrRange, 588 scopeName, scopeLoc, 589 args, numArgs, syntax, 590 ellipsisLoc)); 591 } 592 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)593 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 594 IdentifierInfo *scopeName, SourceLocation scopeLoc, 595 IdentifierLoc *Param, 596 const AvailabilityChange &introduced, 597 const AvailabilityChange &deprecated, 598 const AvailabilityChange &obsoleted, 599 SourceLocation unavailable, 600 const Expr *MessageExpr, 601 AttributeList::Syntax syntax) { 602 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 603 return add(new (memory) AttributeList(attrName, attrRange, 604 scopeName, scopeLoc, 605 Param, introduced, deprecated, 606 obsoleted, unavailable, MessageExpr, 607 syntax)); 608 } 609 create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)610 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 611 IdentifierInfo *scopeName, SourceLocation scopeLoc, 612 IdentifierLoc *Param1, 613 IdentifierLoc *Param2, 614 IdentifierLoc *Param3, 615 AttributeList::Syntax syntax) { 616 size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); 617 void *memory = allocate(size); 618 return add(new (memory) AttributeList(attrName, attrRange, 619 scopeName, scopeLoc, 620 Param1, Param2, Param3, 621 syntax)); 622 } 623 createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)624 AttributeList *createTypeTagForDatatype( 625 IdentifierInfo *attrName, SourceRange attrRange, 626 IdentifierInfo *scopeName, SourceLocation scopeLoc, 627 IdentifierLoc *argumentKind, ParsedType matchingCType, 628 bool layoutCompatible, bool mustBeNull, 629 AttributeList::Syntax syntax) { 630 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 631 return add(new (memory) AttributeList(attrName, attrRange, 632 scopeName, scopeLoc, 633 argumentKind, matchingCType, 634 layoutCompatible, mustBeNull, 635 syntax)); 636 } 637 createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)638 AttributeList *createTypeAttribute( 639 IdentifierInfo *attrName, SourceRange attrRange, 640 IdentifierInfo *scopeName, SourceLocation scopeLoc, 641 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 642 void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); 643 return add(new (memory) AttributeList(attrName, attrRange, 644 scopeName, scopeLoc, 645 typeArg, syntaxUsed)); 646 } 647 createPropertyAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)648 AttributeList *createPropertyAttribute( 649 IdentifierInfo *attrName, SourceRange attrRange, 650 IdentifierInfo *scopeName, SourceLocation scopeLoc, 651 IdentifierInfo *getterId, IdentifierInfo *setterId, 652 AttributeList::Syntax syntaxUsed) { 653 void *memory = allocate(AttributeFactory::PropertyAllocSize); 654 return add(new (memory) AttributeList(attrName, attrRange, 655 scopeName, scopeLoc, 656 getterId, setterId, 657 syntaxUsed)); 658 } 659 }; 660 661 /// ParsedAttributes - A collection of parsed attributes. Currently 662 /// we don't differentiate between the various attribute syntaxes, 663 /// which is basically silly. 664 /// 665 /// Right now this is a very lightweight container, but the expectation 666 /// is that this will become significantly more serious. 667 class ParsedAttributes { 668 public: ParsedAttributes(AttributeFactory & factory)669 ParsedAttributes(AttributeFactory &factory) 670 : pool(factory), list(nullptr) { 671 } 672 673 ParsedAttributes(const ParsedAttributes &) = delete; 674 getPool()675 AttributePool &getPool() const { return pool; } 676 empty()677 bool empty() const { return list == nullptr; } 678 add(AttributeList * newAttr)679 void add(AttributeList *newAttr) { 680 assert(newAttr); 681 assert(newAttr->getNext() == nullptr); 682 newAttr->setNext(list); 683 list = newAttr; 684 } 685 addAll(AttributeList * newList)686 void addAll(AttributeList *newList) { 687 if (!newList) return; 688 689 AttributeList *lastInNewList = newList; 690 while (AttributeList *next = lastInNewList->getNext()) 691 lastInNewList = next; 692 693 lastInNewList->setNext(list); 694 list = newList; 695 } 696 set(AttributeList * newList)697 void set(AttributeList *newList) { 698 list = newList; 699 } 700 takeAllFrom(ParsedAttributes & attrs)701 void takeAllFrom(ParsedAttributes &attrs) { 702 addAll(attrs.list); 703 attrs.list = nullptr; 704 pool.takeAllFrom(attrs.pool); 705 } 706 clear()707 void clear() { list = nullptr; pool.clear(); } getList()708 AttributeList *getList() const { return list; } 709 710 /// Returns a reference to the attribute list. Try not to introduce 711 /// dependencies on this method, it may not be long-lived. getListRef()712 AttributeList *&getListRef() { return list; } 713 714 /// Add attribute with expression arguments. 715 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 716 IdentifierInfo *scopeName, SourceLocation scopeLoc, 717 ArgsUnion *args, unsigned numArgs, 718 AttributeList::Syntax syntax, 719 SourceLocation ellipsisLoc = SourceLocation()) { 720 AttributeList *attr = 721 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, 722 syntax, ellipsisLoc); 723 add(attr); 724 return attr; 725 } 726 727 /// 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)728 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 729 IdentifierInfo *scopeName, SourceLocation scopeLoc, 730 IdentifierLoc *Param, 731 const AvailabilityChange &introduced, 732 const AvailabilityChange &deprecated, 733 const AvailabilityChange &obsoleted, 734 SourceLocation unavailable, 735 const Expr *MessageExpr, 736 AttributeList::Syntax syntax) { 737 AttributeList *attr = 738 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, 739 deprecated, obsoleted, unavailable, MessageExpr, syntax); 740 add(attr); 741 return attr; 742 } 743 744 /// Add objc_bridge_related attribute. addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)745 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 746 IdentifierInfo *scopeName, SourceLocation scopeLoc, 747 IdentifierLoc *Param1, 748 IdentifierLoc *Param2, 749 IdentifierLoc *Param3, 750 AttributeList::Syntax syntax) { 751 AttributeList *attr = 752 pool.create(attrName, attrRange, scopeName, scopeLoc, 753 Param1, Param2, Param3, syntax); 754 add(attr); 755 return attr; 756 } 757 758 /// 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)759 AttributeList *addNewTypeTagForDatatype( 760 IdentifierInfo *attrName, SourceRange attrRange, 761 IdentifierInfo *scopeName, SourceLocation scopeLoc, 762 IdentifierLoc *argumentKind, ParsedType matchingCType, 763 bool layoutCompatible, bool mustBeNull, 764 AttributeList::Syntax syntax) { 765 AttributeList *attr = 766 pool.createTypeTagForDatatype(attrName, attrRange, 767 scopeName, scopeLoc, 768 argumentKind, matchingCType, 769 layoutCompatible, mustBeNull, syntax); 770 add(attr); 771 return attr; 772 } 773 774 /// Add an attribute with a single type argument. 775 AttributeList * addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)776 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 777 IdentifierInfo *scopeName, SourceLocation scopeLoc, 778 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 779 AttributeList *attr = 780 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, 781 typeArg, syntaxUsed); 782 add(attr); 783 return attr; 784 } 785 786 /// Add microsoft __delspec(property) attribute. 787 AttributeList * addNewPropertyAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)788 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 789 IdentifierInfo *scopeName, SourceLocation scopeLoc, 790 IdentifierInfo *getterId, IdentifierInfo *setterId, 791 AttributeList::Syntax syntaxUsed) { 792 AttributeList *attr = 793 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 794 getterId, setterId, syntaxUsed); 795 add(attr); 796 return attr; 797 } 798 799 private: 800 mutable AttributePool pool; 801 AttributeList *list; 802 }; 803 804 /// These constants match the enumerated choices of 805 /// err_attribute_argument_n_type and err_attribute_argument_type. 806 enum AttributeArgumentNType { 807 AANT_ArgumentIntOrBool, 808 AANT_ArgumentIntegerConstant, 809 AANT_ArgumentString, 810 AANT_ArgumentIdentifier 811 }; 812 813 /// These constants match the enumerated choices of 814 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 815 enum AttributeDeclKind { 816 ExpectedFunction, 817 ExpectedUnion, 818 ExpectedVariableOrFunction, 819 ExpectedFunctionOrMethod, 820 ExpectedParameter, 821 ExpectedFunctionMethodOrBlock, 822 ExpectedFunctionMethodOrClass, 823 ExpectedFunctionMethodOrParameter, 824 ExpectedClass, 825 ExpectedEnum, 826 ExpectedVariable, 827 ExpectedMethod, 828 ExpectedVariableFunctionOrLabel, 829 ExpectedFieldOrGlobalVar, 830 ExpectedStruct, 831 ExpectedVariableOrTypedef, 832 ExpectedTLSVar, 833 ExpectedVariableOrField, 834 ExpectedVariableFieldOrTag, 835 ExpectedTypeOrNamespace, 836 ExpectedObjectiveCInterface, 837 ExpectedMethodOrProperty, 838 ExpectedStructOrUnion, 839 ExpectedStructOrUnionOrClass, 840 ExpectedType, 841 ExpectedObjCInstanceMethod, 842 ExpectedObjCInterfaceDeclInitMethod, 843 ExpectedFunctionVariableOrClass, 844 ExpectedObjectiveCProtocol, 845 ExpectedFunctionGlobalVarMethodOrProperty, 846 ExpectedStructOrUnionOrTypedef, 847 ExpectedStructOrTypedef, 848 ExpectedObjectiveCInterfaceOrProtocol, 849 ExpectedKernelFunction 850 }; 851 852 } // end namespace clang 853 854 #endif 855