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