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