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 /// 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() { 141 return reinterpret_cast<ArgsUnion*>(this+1); 142 } getArgsBuffer()143 ArgsUnion const *getArgsBuffer() const { 144 return reinterpret_cast<ArgsUnion const *>(this+1); 145 } 146 147 enum AvailabilitySlot { 148 IntroducedSlot, DeprecatedSlot, ObsoletedSlot 149 }; 150 151 /// Availability information is stored immediately following the arguments, 152 /// if any, at the end of the object. getAvailabilitySlot(AvailabilitySlot index)153 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { 154 return reinterpret_cast<AvailabilityChange*>(getArgsBuffer() 155 + NumArgs)[index]; 156 } getAvailabilitySlot(AvailabilitySlot index)157 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { 158 return reinterpret_cast<const AvailabilityChange*>(getArgsBuffer() 159 + NumArgs)[index]; 160 } 161 162 public: 163 struct TypeTagForDatatypeData { 164 ParsedType *MatchingCType; 165 unsigned LayoutCompatible : 1; 166 unsigned MustBeNull : 1; 167 }; 168 struct PropertyData { 169 IdentifierInfo *GetterId, *SetterId; PropertyDataPropertyData170 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) 171 : GetterId(getterId), SetterId(setterId) {} 172 }; 173 174 private: 175 /// Type tag information is stored immediately following the arguments, if 176 /// any, at the end of the object. They are mutually exlusive with 177 /// availability slots. getTypeTagForDatatypeDataSlot()178 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { 179 return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs); 180 } 181 getTypeTagForDatatypeDataSlot()182 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { 183 return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer() 184 + NumArgs); 185 } 186 187 /// The type buffer immediately follows the object and are mutually exclusive 188 /// with arguments. getTypeBuffer()189 ParsedType &getTypeBuffer() { 190 return *reinterpret_cast<ParsedType *>(this + 1); 191 } 192 getTypeBuffer()193 const ParsedType &getTypeBuffer() const { 194 return *reinterpret_cast<const ParsedType *>(this + 1); 195 } 196 197 /// The property data immediately follows the object is is mutually exclusive 198 /// with arguments. getPropertyDataBuffer()199 PropertyData &getPropertyDataBuffer() { 200 assert(IsProperty); 201 return *reinterpret_cast<PropertyData*>(this + 1); 202 } 203 getPropertyDataBuffer()204 const PropertyData &getPropertyDataBuffer() const { 205 assert(IsProperty); 206 return *reinterpret_cast<const PropertyData*>(this + 1); 207 } 208 209 AttributeList(const AttributeList &) = delete; 210 void operator=(const AttributeList &) = delete; 211 void operator delete(void *) = delete; 212 ~AttributeList() = delete; 213 214 size_t allocated_size() const; 215 216 /// Constructor for attributes with expression arguments. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ArgsUnion * args,unsigned numArgs,Syntax syntaxUsed,SourceLocation ellipsisLoc)217 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 218 IdentifierInfo *scopeName, SourceLocation scopeLoc, 219 ArgsUnion *args, unsigned numArgs, 220 Syntax syntaxUsed, SourceLocation ellipsisLoc) 221 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 222 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), 223 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), 224 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 225 HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) { 226 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); 227 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 228 } 229 230 /// 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)231 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 232 IdentifierInfo *scopeName, SourceLocation scopeLoc, 233 IdentifierLoc *Parm, const AvailabilityChange &introduced, 234 const AvailabilityChange &deprecated, 235 const AvailabilityChange &obsoleted, 236 SourceLocation unavailable, 237 const Expr *messageExpr, 238 Syntax syntaxUsed) 239 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 240 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), 241 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 242 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 243 UnavailableLoc(unavailable), MessageExpr(messageExpr), 244 NextInPosition(nullptr), NextInPool(nullptr) { 245 ArgsUnion PVal(Parm); 246 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 247 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); 248 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); 249 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); 250 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 251 } 252 253 /// Constructor for objc_bridge_related attributes. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Parm1,IdentifierLoc * Parm2,IdentifierLoc * Parm3,Syntax syntaxUsed)254 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 255 IdentifierInfo *scopeName, SourceLocation scopeLoc, 256 IdentifierLoc *Parm1, 257 IdentifierLoc *Parm2, 258 IdentifierLoc *Parm3, 259 Syntax syntaxUsed) 260 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 261 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed), 262 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 263 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 264 NextInPosition(nullptr), NextInPool(nullptr) { 265 ArgsVector Args; 266 Args.push_back(Parm1); 267 Args.push_back(Parm2); 268 Args.push_back(Parm3); 269 memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion)); 270 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 271 } 272 273 /// 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)274 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 275 IdentifierInfo *scopeName, SourceLocation scopeLoc, 276 IdentifierLoc *ArgKind, ParsedType matchingCType, 277 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) 278 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 279 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), 280 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 281 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), 282 NextInPosition(nullptr), NextInPool(nullptr) { 283 ArgsUnion PVal(ArgKind); 284 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 285 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); 286 new (&ExtraData.MatchingCType) ParsedType(matchingCType); 287 ExtraData.LayoutCompatible = layoutCompatible; 288 ExtraData.MustBeNull = mustBeNull; 289 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 290 } 291 292 /// Constructor for attributes with a single type argument. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,Syntax syntaxUsed)293 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 294 IdentifierInfo *scopeName, SourceLocation scopeLoc, 295 ParsedType typeArg, Syntax syntaxUsed) 296 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 297 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), 298 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 299 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), 300 NextInPosition(nullptr), NextInPool(nullptr) { 301 new (&getTypeBuffer()) ParsedType(typeArg); 302 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 303 } 304 305 /// Constructor for microsoft __declspec(property) attribute. AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,Syntax syntaxUsed)306 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 307 IdentifierInfo *scopeName, SourceLocation scopeLoc, 308 IdentifierInfo *getterId, IdentifierInfo *setterId, 309 Syntax syntaxUsed) 310 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), 311 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), 312 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 313 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), 314 NextInPosition(nullptr), NextInPool(nullptr) { 315 new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); 316 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 317 } 318 319 friend class AttributePool; 320 friend class AttributeFactory; 321 322 public: 323 enum Kind { 324 #define PARSED_ATTR(NAME) AT_##NAME, 325 #include "clang/Sema/AttrParsedAttrList.inc" 326 #undef PARSED_ATTR 327 IgnoredAttribute, 328 UnknownAttribute 329 }; 330 getName()331 IdentifierInfo *getName() const { return AttrName; } getLoc()332 SourceLocation getLoc() const { return AttrRange.getBegin(); } getRange()333 SourceRange getRange() const { return AttrRange; } 334 hasScope()335 bool hasScope() const { return ScopeName; } getScopeName()336 IdentifierInfo *getScopeName() const { return ScopeName; } getScopeLoc()337 SourceLocation getScopeLoc() const { return ScopeLoc; } 338 hasParsedType()339 bool hasParsedType() const { return HasParsedType; } 340 341 /// Is this the Microsoft __declspec(property) attribute? isDeclspecPropertyAttribute()342 bool isDeclspecPropertyAttribute() const { 343 return IsProperty; 344 } 345 isAlignasAttribute()346 bool isAlignasAttribute() const { 347 // FIXME: Use a better mechanism to determine this. 348 return getKind() == AT_Aligned && isKeywordAttribute(); 349 } 350 isDeclspecAttribute()351 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } isCXX11Attribute()352 bool isCXX11Attribute() const { 353 return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); 354 } isKeywordAttribute()355 bool isKeywordAttribute() const { 356 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; 357 } 358 isContextSensitiveKeywordAttribute()359 bool isContextSensitiveKeywordAttribute() const { 360 return SyntaxUsed == AS_ContextSensitiveKeyword; 361 } 362 isInvalid()363 bool isInvalid() const { return Invalid; } 364 void setInvalid(bool b = true) const { Invalid = b; } 365 isUsedAsTypeAttr()366 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } setUsedAsTypeAttr()367 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 368 isPackExpansion()369 bool isPackExpansion() const { return EllipsisLoc.isValid(); } getEllipsisLoc()370 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 371 getKind()372 Kind getKind() const { return Kind(AttrKind); } 373 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, 374 Syntax SyntaxUsed); 375 getNext()376 AttributeList *getNext() const { return NextInPosition; } setNext(AttributeList * N)377 void setNext(AttributeList *N) { NextInPosition = N; } 378 379 /// getNumArgs - Return the number of actual arguments to this attribute. getNumArgs()380 unsigned getNumArgs() const { return NumArgs; } 381 382 /// getArg - Return the specified argument. getArg(unsigned Arg)383 ArgsUnion getArg(unsigned Arg) const { 384 assert(Arg < NumArgs && "Arg access out of range!"); 385 return getArgsBuffer()[Arg]; 386 } 387 isArgExpr(unsigned Arg)388 bool isArgExpr(unsigned Arg) const { 389 return Arg < NumArgs && getArg(Arg).is<Expr*>(); 390 } getArgAsExpr(unsigned Arg)391 Expr *getArgAsExpr(unsigned Arg) const { 392 return getArg(Arg).get<Expr*>(); 393 } 394 isArgIdent(unsigned Arg)395 bool isArgIdent(unsigned Arg) const { 396 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); 397 } getArgAsIdent(unsigned Arg)398 IdentifierLoc *getArgAsIdent(unsigned Arg) const { 399 return getArg(Arg).get<IdentifierLoc*>(); 400 } 401 getAvailabilityIntroduced()402 const AvailabilityChange &getAvailabilityIntroduced() const { 403 assert(getKind() == AT_Availability && "Not an availability attribute"); 404 return getAvailabilitySlot(IntroducedSlot); 405 } 406 getAvailabilityDeprecated()407 const AvailabilityChange &getAvailabilityDeprecated() const { 408 assert(getKind() == AT_Availability && "Not an availability attribute"); 409 return getAvailabilitySlot(DeprecatedSlot); 410 } 411 getAvailabilityObsoleted()412 const AvailabilityChange &getAvailabilityObsoleted() const { 413 assert(getKind() == AT_Availability && "Not an availability attribute"); 414 return getAvailabilitySlot(ObsoletedSlot); 415 } 416 getUnavailableLoc()417 SourceLocation getUnavailableLoc() const { 418 assert(getKind() == AT_Availability && "Not an availability attribute"); 419 return UnavailableLoc; 420 } 421 getMessageExpr()422 const Expr * getMessageExpr() const { 423 assert(getKind() == AT_Availability && "Not an availability attribute"); 424 return MessageExpr; 425 } 426 getMatchingCType()427 const ParsedType &getMatchingCType() const { 428 assert(getKind() == AT_TypeTagForDatatype && 429 "Not a type_tag_for_datatype attribute"); 430 return *getTypeTagForDatatypeDataSlot().MatchingCType; 431 } 432 getLayoutCompatible()433 bool getLayoutCompatible() const { 434 assert(getKind() == AT_TypeTagForDatatype && 435 "Not a type_tag_for_datatype attribute"); 436 return getTypeTagForDatatypeDataSlot().LayoutCompatible; 437 } 438 getMustBeNull()439 bool getMustBeNull() const { 440 assert(getKind() == AT_TypeTagForDatatype && 441 "Not a type_tag_for_datatype attribute"); 442 return getTypeTagForDatatypeDataSlot().MustBeNull; 443 } 444 getTypeArg()445 const ParsedType &getTypeArg() const { 446 assert(HasParsedType && "Not a type attribute"); 447 return getTypeBuffer(); 448 } 449 getPropertyData()450 const PropertyData &getPropertyData() const { 451 assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute"); 452 return getPropertyDataBuffer(); 453 } 454 455 /// \brief Get an index into the attribute spelling list 456 /// defined in Attr.td. This index is used by an attribute 457 /// to pretty print itself. 458 unsigned getAttributeSpellingListIndex() const; 459 460 bool isTargetSpecificAttr() const; 461 bool isTypeAttr() const; 462 463 bool hasCustomParsing() const; 464 unsigned getMinArgs() const; 465 unsigned getMaxArgs() const; 466 bool hasVariadicArg() const; 467 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 468 bool diagnoseLangOpts(class Sema &S) const; 469 bool existsInTarget(const llvm::Triple &T) const; 470 bool isKnownToGCC() const; 471 472 /// \brief If the parsed attribute has a semantic equivalent, and it would 473 /// have a semantic Spelling enumeration (due to having semantically-distinct 474 /// spelling variations), return the value of that semantic spelling. If the 475 /// parsed attribute does not have a semantic equivalent, or would not have 476 /// a Spelling enumeration, the value UINT_MAX is returned. 477 unsigned getSemanticSpelling() const; 478 }; 479 480 /// A factory, from which one makes pools, from which one creates 481 /// individual attributes which are deallocated with the pool. 482 /// 483 /// Note that it's tolerably cheap to create and destroy one of 484 /// these as long as you don't actually allocate anything in it. 485 class AttributeFactory { 486 public: 487 enum { 488 /// The required allocation size of an availability attribute, 489 /// which we want to ensure is a multiple of sizeof(void*). 490 AvailabilityAllocSize = 491 sizeof(AttributeList) 492 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + 493 sizeof(ArgsUnion) - 1) 494 / sizeof(void*) * sizeof(void*)), 495 TypeTagForDatatypeAllocSize = 496 sizeof(AttributeList) 497 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + 498 sizeof(ArgsUnion) - 1) 499 / sizeof(void*) * sizeof(void*), 500 PropertyAllocSize = 501 sizeof(AttributeList) 502 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) 503 / sizeof(void*) * sizeof(void*) 504 }; 505 506 private: 507 enum { 508 /// The number of free lists we want to be sure to support 509 /// inline. This is just enough that availability attributes 510 /// don't surpass it. It's actually very unlikely we'll see an 511 /// attribute that needs more than that; on x86-64 you'd need 10 512 /// expression arguments, and on i386 you'd need 19. 513 InlineFreeListsCapacity = 514 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 515 }; 516 517 llvm::BumpPtrAllocator Alloc; 518 519 /// Free lists. The index is determined by the following formula: 520 /// (size - sizeof(AttributeList)) / sizeof(void*) 521 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 522 523 // The following are the private interface used by AttributePool. 524 friend class AttributePool; 525 526 /// Allocate an attribute of the given size. 527 void *allocate(size_t size); 528 529 /// Reclaim all the attributes in the given pool chain, which is 530 /// non-empty. Note that the current implementation is safe 531 /// against reclaiming things which were not actually allocated 532 /// with the allocator, although of course it's important to make 533 /// sure that their allocator lives at least as long as this one. 534 void reclaimPool(AttributeList *head); 535 536 public: 537 AttributeFactory(); 538 ~AttributeFactory(); 539 }; 540 541 class AttributePool { 542 AttributeFactory &Factory; 543 AttributeList *Head; 544 allocate(size_t size)545 void *allocate(size_t size) { 546 return Factory.allocate(size); 547 } 548 add(AttributeList * attr)549 AttributeList *add(AttributeList *attr) { 550 // We don't care about the order of the pool. 551 attr->NextInPool = Head; 552 Head = attr; 553 return attr; 554 } 555 556 void takePool(AttributeList *pool); 557 558 public: 559 /// Create a new pool for a factory. AttributePool(AttributeFactory & factory)560 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} 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 }; 859 860 } // end namespace clang 861 862 #endif 863