1 //======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the ParsedAttr class, which is used to collect 10 // parsed attributes. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H 15 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H 16 17 #include "clang/Basic/AttrSubjectMatchRules.h" 18 #include "clang/Basic/AttributeCommonInfo.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. 55 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 69 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 88 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 : public AttributeCommonInfo, 119 private llvm::TrailingObjects< 120 ParsedAttr, ArgsUnion, detail::AvailabilityData, 121 detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> { 122 friend TrailingObjects; 123 124 size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; } 125 size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const { 126 return IsAvailability; 127 } 128 size_t 129 numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const { 130 return IsTypeTagForDatatype; 131 } 132 size_t numTrailingObjects(OverloadToken<ParsedType>) const { 133 return HasParsedType; 134 } 135 size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const { 136 return IsProperty; 137 } 138 139 private: 140 IdentifierInfo *MacroII = nullptr; 141 SourceLocation MacroExpansionLoc; 142 SourceLocation EllipsisLoc; 143 144 /// The number of expression arguments this attribute has. 145 /// The expressions themselves are stored after the object. 146 unsigned NumArgs : 16; 147 148 /// True if already diagnosed as invalid. 149 mutable unsigned Invalid : 1; 150 151 /// True if this attribute was used as a type attribute. 152 mutable unsigned UsedAsTypeAttr : 1; 153 154 /// True if this has the extra information associated with an 155 /// availability attribute. 156 unsigned IsAvailability : 1; 157 158 /// True if this has extra information associated with a 159 /// type_tag_for_datatype attribute. 160 unsigned IsTypeTagForDatatype : 1; 161 162 /// True if this has extra information associated with a 163 /// Microsoft __delcspec(property) attribute. 164 unsigned IsProperty : 1; 165 166 /// True if this has a ParsedType 167 unsigned HasParsedType : 1; 168 169 /// True if the processing cache is valid. 170 mutable unsigned HasProcessingCache : 1; 171 172 /// A cached value. 173 mutable unsigned ProcessingCache : 8; 174 175 /// True if the attribute is specified using '#pragma clang attribute'. 176 mutable unsigned IsPragmaClangAttribute : 1; 177 178 /// The location of the 'unavailable' keyword in an 179 /// availability attribute. 180 SourceLocation UnavailableLoc; 181 182 const Expr *MessageExpr; 183 184 ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); } 185 ArgsUnion const *getArgsBuffer() const { 186 return getTrailingObjects<ArgsUnion>(); 187 } 188 189 detail::AvailabilityData *getAvailabilityData() { 190 return getTrailingObjects<detail::AvailabilityData>(); 191 } 192 const detail::AvailabilityData *getAvailabilityData() const { 193 return getTrailingObjects<detail::AvailabilityData>(); 194 } 195 196 private: 197 friend class AttributeFactory; 198 friend class AttributePool; 199 200 /// Constructor for attributes with expression arguments. 201 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 202 IdentifierInfo *scopeName, SourceLocation scopeLoc, 203 ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, 204 SourceLocation ellipsisLoc) 205 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 206 syntaxUsed), 207 EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false), 208 UsedAsTypeAttr(false), IsAvailability(false), 209 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 210 HasProcessingCache(false), IsPragmaClangAttribute(false) { 211 if (numArgs) 212 memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); 213 } 214 215 /// Constructor for availability attributes. 216 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 217 IdentifierInfo *scopeName, SourceLocation scopeLoc, 218 IdentifierLoc *Parm, const AvailabilityChange &introduced, 219 const AvailabilityChange &deprecated, 220 const AvailabilityChange &obsoleted, SourceLocation unavailable, 221 const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, 222 const Expr *replacementExpr) 223 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 224 syntaxUsed), 225 NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 226 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 227 HasProcessingCache(false), IsPragmaClangAttribute(false), 228 UnavailableLoc(unavailable), MessageExpr(messageExpr) { 229 ArgsUnion PVal(Parm); 230 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 231 new (getAvailabilityData()) detail::AvailabilityData( 232 introduced, deprecated, obsoleted, strict, replacementExpr); 233 } 234 235 /// Constructor for objc_bridge_related attributes. 236 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 237 IdentifierInfo *scopeName, SourceLocation scopeLoc, 238 IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, 239 Syntax syntaxUsed) 240 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 241 syntaxUsed), 242 NumArgs(3), Invalid(false), UsedAsTypeAttr(false), 243 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 244 HasParsedType(false), HasProcessingCache(false), 245 IsPragmaClangAttribute(false) { 246 ArgsUnion *Args = getArgsBuffer(); 247 Args[0] = Parm1; 248 Args[1] = Parm2; 249 Args[2] = Parm3; 250 } 251 252 /// Constructor for type_tag_for_datatype attribute. 253 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 254 IdentifierInfo *scopeName, SourceLocation scopeLoc, 255 IdentifierLoc *ArgKind, ParsedType matchingCType, 256 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) 257 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 258 syntaxUsed), 259 NumArgs(1), Invalid(false), UsedAsTypeAttr(false), 260 IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), 261 HasParsedType(false), HasProcessingCache(false), 262 IsPragmaClangAttribute(false) { 263 ArgsUnion PVal(ArgKind); 264 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 265 detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); 266 new (&ExtraData.MatchingCType) ParsedType(matchingCType); 267 ExtraData.LayoutCompatible = layoutCompatible; 268 ExtraData.MustBeNull = mustBeNull; 269 } 270 271 /// Constructor for attributes with a single type argument. 272 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 273 IdentifierInfo *scopeName, SourceLocation scopeLoc, 274 ParsedType typeArg, Syntax syntaxUsed) 275 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 276 syntaxUsed), 277 NumArgs(0), Invalid(false), UsedAsTypeAttr(false), 278 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 279 HasParsedType(true), HasProcessingCache(false), 280 IsPragmaClangAttribute(false) { 281 new (&getTypeBuffer()) ParsedType(typeArg); 282 } 283 284 /// Constructor for microsoft __declspec(property) attribute. 285 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 286 IdentifierInfo *scopeName, SourceLocation scopeLoc, 287 IdentifierInfo *getterId, IdentifierInfo *setterId, 288 Syntax syntaxUsed) 289 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 290 syntaxUsed), 291 NumArgs(0), Invalid(false), UsedAsTypeAttr(false), 292 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), 293 HasParsedType(false), HasProcessingCache(false), 294 IsPragmaClangAttribute(false) { 295 new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId); 296 } 297 298 /// Type tag information is stored immediately following the arguments, if 299 /// any, at the end of the object. They are mutually exclusive with 300 /// availability slots. 301 detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { 302 return *getTrailingObjects<detail::TypeTagForDatatypeData>(); 303 } 304 const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { 305 return *getTrailingObjects<detail::TypeTagForDatatypeData>(); 306 } 307 308 /// The type buffer immediately follows the object and are mutually exclusive 309 /// with arguments. 310 ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); } 311 const ParsedType &getTypeBuffer() const { 312 return *getTrailingObjects<ParsedType>(); 313 } 314 315 /// The property data immediately follows the object is is mutually exclusive 316 /// with arguments. 317 detail::PropertyData &getPropertyDataBuffer() { 318 assert(IsProperty); 319 return *getTrailingObjects<detail::PropertyData>(); 320 } 321 const detail::PropertyData &getPropertyDataBuffer() const { 322 assert(IsProperty); 323 return *getTrailingObjects<detail::PropertyData>(); 324 } 325 326 size_t allocated_size() const; 327 328 public: 329 ParsedAttr(const ParsedAttr &) = delete; 330 ParsedAttr(ParsedAttr &&) = delete; 331 ParsedAttr &operator=(const ParsedAttr &) = delete; 332 ParsedAttr &operator=(ParsedAttr &&) = delete; 333 ~ParsedAttr() = delete; 334 335 void operator delete(void *) = delete; 336 337 bool hasParsedType() const { return HasParsedType; } 338 339 /// Is this the Microsoft __declspec(property) attribute? 340 bool isDeclspecPropertyAttribute() const { 341 return IsProperty; 342 } 343 344 bool isInvalid() const { return Invalid; } 345 void setInvalid(bool b = true) const { Invalid = b; } 346 347 bool hasProcessingCache() const { return HasProcessingCache; } 348 349 unsigned getProcessingCache() const { 350 assert(hasProcessingCache()); 351 return ProcessingCache; 352 } 353 354 void setProcessingCache(unsigned value) const { 355 ProcessingCache = value; 356 HasProcessingCache = true; 357 } 358 359 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } 360 void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; } 361 362 /// True if the attribute is specified using '#pragma clang attribute'. 363 bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; } 364 365 void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; } 366 367 bool isPackExpansion() const { return EllipsisLoc.isValid(); } 368 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 369 370 /// getNumArgs - Return the number of actual arguments to this attribute. 371 unsigned getNumArgs() const { return NumArgs; } 372 373 /// getArg - Return the specified argument. 374 ArgsUnion getArg(unsigned Arg) const { 375 assert(Arg < NumArgs && "Arg access out of range!"); 376 return getArgsBuffer()[Arg]; 377 } 378 379 bool isArgExpr(unsigned Arg) const { 380 return Arg < NumArgs && getArg(Arg).is<Expr*>(); 381 } 382 383 Expr *getArgAsExpr(unsigned Arg) const { 384 return getArg(Arg).get<Expr*>(); 385 } 386 387 bool isArgIdent(unsigned Arg) const { 388 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); 389 } 390 391 IdentifierLoc *getArgAsIdent(unsigned Arg) const { 392 return getArg(Arg).get<IdentifierLoc*>(); 393 } 394 395 const AvailabilityChange &getAvailabilityIntroduced() const { 396 assert(getParsedKind() == AT_Availability && 397 "Not an availability attribute"); 398 return getAvailabilityData()->Changes[detail::IntroducedSlot]; 399 } 400 401 const AvailabilityChange &getAvailabilityDeprecated() const { 402 assert(getParsedKind() == AT_Availability && 403 "Not an availability attribute"); 404 return getAvailabilityData()->Changes[detail::DeprecatedSlot]; 405 } 406 407 const AvailabilityChange &getAvailabilityObsoleted() const { 408 assert(getParsedKind() == AT_Availability && 409 "Not an availability attribute"); 410 return getAvailabilityData()->Changes[detail::ObsoletedSlot]; 411 } 412 413 SourceLocation getStrictLoc() const { 414 assert(getParsedKind() == AT_Availability && 415 "Not an availability attribute"); 416 return getAvailabilityData()->StrictLoc; 417 } 418 419 SourceLocation getUnavailableLoc() const { 420 assert(getParsedKind() == AT_Availability && 421 "Not an availability attribute"); 422 return UnavailableLoc; 423 } 424 425 const Expr * getMessageExpr() const { 426 assert(getParsedKind() == AT_Availability && 427 "Not an availability attribute"); 428 return MessageExpr; 429 } 430 431 const Expr *getReplacementExpr() const { 432 assert(getParsedKind() == AT_Availability && 433 "Not an availability attribute"); 434 return getAvailabilityData()->Replacement; 435 } 436 437 const ParsedType &getMatchingCType() const { 438 assert(getParsedKind() == AT_TypeTagForDatatype && 439 "Not a type_tag_for_datatype attribute"); 440 return getTypeTagForDatatypeDataSlot().MatchingCType; 441 } 442 443 bool getLayoutCompatible() const { 444 assert(getParsedKind() == AT_TypeTagForDatatype && 445 "Not a type_tag_for_datatype attribute"); 446 return getTypeTagForDatatypeDataSlot().LayoutCompatible; 447 } 448 449 bool getMustBeNull() const { 450 assert(getParsedKind() == AT_TypeTagForDatatype && 451 "Not a type_tag_for_datatype attribute"); 452 return getTypeTagForDatatypeDataSlot().MustBeNull; 453 } 454 455 const ParsedType &getTypeArg() const { 456 assert(HasParsedType && "Not a type attribute"); 457 return getTypeBuffer(); 458 } 459 460 IdentifierInfo *getPropertyDataGetter() const { 461 assert(isDeclspecPropertyAttribute() && 462 "Not a __delcspec(property) attribute"); 463 return getPropertyDataBuffer().GetterId; 464 } 465 466 IdentifierInfo *getPropertyDataSetter() const { 467 assert(isDeclspecPropertyAttribute() && 468 "Not a __delcspec(property) attribute"); 469 return getPropertyDataBuffer().SetterId; 470 } 471 472 /// Set the macro identifier info object that this parsed attribute was 473 /// declared in if it was declared in a macro. Also set the expansion location 474 /// of the macro. 475 void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) { 476 MacroII = MacroName; 477 MacroExpansionLoc = Loc; 478 } 479 480 /// Returns true if this attribute was declared in a macro. 481 bool hasMacroIdentifier() const { return MacroII != nullptr; } 482 483 /// Return the macro identifier if this attribute was declared in a macro. 484 /// nullptr is returned if it was not declared in a macro. 485 IdentifierInfo *getMacroIdentifier() const { return MacroII; } 486 487 SourceLocation getMacroExpansionLoc() const { 488 assert(hasMacroIdentifier() && "Can only get the macro expansion location " 489 "if this attribute has a macro identifier."); 490 return MacroExpansionLoc; 491 } 492 493 bool isTargetSpecificAttr() const; 494 bool isTypeAttr() const; 495 bool isStmtAttr() const; 496 497 bool hasCustomParsing() const; 498 unsigned getMinArgs() const; 499 unsigned getMaxArgs() const; 500 bool hasVariadicArg() const; 501 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 502 bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const; 503 void getMatchRules(const LangOptions &LangOpts, 504 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> 505 &MatchRules) const; 506 bool diagnoseLangOpts(class Sema &S) const; 507 bool existsInTarget(const TargetInfo &Target) const; 508 bool isKnownToGCC() const; 509 bool isSupportedByPragmaAttribute() const; 510 511 /// If the parsed attribute has a semantic equivalent, and it would 512 /// have a semantic Spelling enumeration (due to having semantically-distinct 513 /// spelling variations), return the value of that semantic spelling. If the 514 /// parsed attribute does not have a semantic equivalent, or would not have 515 /// a Spelling enumeration, the value UINT_MAX is returned. 516 unsigned getSemanticSpelling() const; 517 518 /// If this is an OpenCL addr space attribute returns its representation 519 /// in LangAS, otherwise returns default addr space. 520 LangAS asOpenCLLangAS() const { 521 switch (getParsedKind()) { 522 case ParsedAttr::AT_OpenCLConstantAddressSpace: 523 return LangAS::opencl_constant; 524 case ParsedAttr::AT_OpenCLGlobalAddressSpace: 525 return LangAS::opencl_global; 526 case ParsedAttr::AT_OpenCLLocalAddressSpace: 527 return LangAS::opencl_local; 528 case ParsedAttr::AT_OpenCLPrivateAddressSpace: 529 return LangAS::opencl_private; 530 case ParsedAttr::AT_OpenCLGenericAddressSpace: 531 return LangAS::opencl_generic; 532 default: 533 return LangAS::Default; 534 } 535 } 536 537 AttributeCommonInfo::Kind getKind() const { return getParsedKind(); } 538 }; 539 540 class AttributePool; 541 /// A factory, from which one makes pools, from which one creates 542 /// individual attributes which are deallocated with the pool. 543 /// 544 /// Note that it's tolerably cheap to create and destroy one of 545 /// these as long as you don't actually allocate anything in it. 546 class AttributeFactory { 547 public: 548 enum { 549 AvailabilityAllocSize = 550 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 551 detail::TypeTagForDatatypeData, ParsedType, 552 detail::PropertyData>(1, 1, 0, 0, 0), 553 TypeTagForDatatypeAllocSize = 554 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 555 detail::TypeTagForDatatypeData, ParsedType, 556 detail::PropertyData>(1, 0, 1, 0, 0), 557 PropertyAllocSize = 558 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 559 detail::TypeTagForDatatypeData, ParsedType, 560 detail::PropertyData>(0, 0, 0, 0, 1), 561 }; 562 563 private: 564 enum { 565 /// The number of free lists we want to be sure to support 566 /// inline. This is just enough that availability attributes 567 /// don't surpass it. It's actually very unlikely we'll see an 568 /// attribute that needs more than that; on x86-64 you'd need 10 569 /// expression arguments, and on i386 you'd need 19. 570 InlineFreeListsCapacity = 571 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *) 572 }; 573 574 llvm::BumpPtrAllocator Alloc; 575 576 /// Free lists. The index is determined by the following formula: 577 /// (size - sizeof(ParsedAttr)) / sizeof(void*) 578 SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists; 579 580 // The following are the private interface used by AttributePool. 581 friend class AttributePool; 582 583 /// Allocate an attribute of the given size. 584 void *allocate(size_t size); 585 586 void deallocate(ParsedAttr *AL); 587 588 /// Reclaim all the attributes in the given pool chain, which is 589 /// non-empty. Note that the current implementation is safe 590 /// against reclaiming things which were not actually allocated 591 /// with the allocator, although of course it's important to make 592 /// sure that their allocator lives at least as long as this one. 593 void reclaimPool(AttributePool &head); 594 595 public: 596 AttributeFactory(); 597 ~AttributeFactory(); 598 }; 599 600 class AttributePool { 601 friend class AttributeFactory; 602 friend class ParsedAttributes; 603 AttributeFactory &Factory; 604 llvm::TinyPtrVector<ParsedAttr *> Attrs; 605 606 void *allocate(size_t size) { 607 return Factory.allocate(size); 608 } 609 610 ParsedAttr *add(ParsedAttr *attr) { 611 Attrs.push_back(attr); 612 return attr; 613 } 614 615 void remove(ParsedAttr *attr) { 616 assert(llvm::is_contained(Attrs, attr) && 617 "Can't take attribute from a pool that doesn't own it!"); 618 Attrs.erase(llvm::find(Attrs, attr)); 619 } 620 621 void takePool(AttributePool &pool); 622 623 public: 624 /// Create a new pool for a factory. 625 AttributePool(AttributeFactory &factory) : Factory(factory) {} 626 627 AttributePool(const AttributePool &) = delete; 628 629 ~AttributePool() { Factory.reclaimPool(*this); } 630 631 /// Move the given pool's allocations to this pool. 632 AttributePool(AttributePool &&pool) = default; 633 634 AttributeFactory &getFactory() const { return Factory; } 635 636 void clear() { 637 Factory.reclaimPool(*this); 638 Attrs.clear(); 639 } 640 641 /// Take the given pool's allocations and add them to this pool. 642 void takeAllFrom(AttributePool &pool) { 643 takePool(pool); 644 pool.Attrs.clear(); 645 } 646 647 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 648 IdentifierInfo *scopeName, SourceLocation scopeLoc, 649 ArgsUnion *args, unsigned numArgs, 650 ParsedAttr::Syntax syntax, 651 SourceLocation ellipsisLoc = SourceLocation()) { 652 size_t temp = 653 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 654 detail::TypeTagForDatatypeData, ParsedType, 655 detail::PropertyData>(numArgs, 0, 0, 0, 0); 656 (void)temp; 657 void *memory = allocate( 658 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 659 detail::TypeTagForDatatypeData, ParsedType, 660 detail::PropertyData>(numArgs, 0, 0, 0, 661 0)); 662 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 663 args, numArgs, syntax, ellipsisLoc)); 664 } 665 666 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 667 IdentifierInfo *scopeName, SourceLocation scopeLoc, 668 IdentifierLoc *Param, const AvailabilityChange &introduced, 669 const AvailabilityChange &deprecated, 670 const AvailabilityChange &obsoleted, 671 SourceLocation unavailable, const Expr *MessageExpr, 672 ParsedAttr::Syntax syntax, SourceLocation strict, 673 const Expr *ReplacementExpr) { 674 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 675 return add(new (memory) ParsedAttr( 676 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, 677 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); 678 } 679 680 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 681 IdentifierInfo *scopeName, SourceLocation scopeLoc, 682 IdentifierLoc *Param1, IdentifierLoc *Param2, 683 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { 684 void *memory = allocate( 685 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 686 detail::TypeTagForDatatypeData, ParsedType, 687 detail::PropertyData>(3, 0, 0, 0, 0)); 688 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 689 Param1, Param2, Param3, syntax)); 690 } 691 692 ParsedAttr * 693 createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, 694 IdentifierInfo *scopeName, SourceLocation scopeLoc, 695 IdentifierLoc *argumentKind, 696 ParsedType matchingCType, bool layoutCompatible, 697 bool mustBeNull, ParsedAttr::Syntax syntax) { 698 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 699 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 700 argumentKind, matchingCType, 701 layoutCompatible, mustBeNull, syntax)); 702 } 703 704 ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, 705 SourceRange attrRange, 706 IdentifierInfo *scopeName, 707 SourceLocation scopeLoc, ParsedType typeArg, 708 ParsedAttr::Syntax syntaxUsed) { 709 void *memory = allocate( 710 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 711 detail::TypeTagForDatatypeData, ParsedType, 712 detail::PropertyData>(0, 0, 0, 1, 0)); 713 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 714 typeArg, syntaxUsed)); 715 } 716 717 ParsedAttr * 718 createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, 719 IdentifierInfo *scopeName, SourceLocation scopeLoc, 720 IdentifierInfo *getterId, IdentifierInfo *setterId, 721 ParsedAttr::Syntax syntaxUsed) { 722 void *memory = allocate(AttributeFactory::PropertyAllocSize); 723 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 724 getterId, setterId, syntaxUsed)); 725 } 726 }; 727 728 class ParsedAttributesView { 729 using VecTy = llvm::TinyPtrVector<ParsedAttr *>; 730 using SizeType = decltype(std::declval<VecTy>().size()); 731 732 public: 733 bool empty() const { return AttrList.empty(); } 734 SizeType size() const { return AttrList.size(); } 735 ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } 736 const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; } 737 738 void addAtEnd(ParsedAttr *newAttr) { 739 assert(newAttr); 740 AttrList.push_back(newAttr); 741 } 742 743 void remove(ParsedAttr *ToBeRemoved) { 744 assert(is_contained(AttrList, ToBeRemoved) && 745 "Cannot remove attribute that isn't in the list"); 746 AttrList.erase(llvm::find(AttrList, ToBeRemoved)); 747 } 748 749 void clearListOnly() { AttrList.clear(); } 750 751 struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator, 752 std::random_access_iterator_tag, 753 ParsedAttr> { 754 iterator() : iterator_adaptor_base(nullptr) {} 755 iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} 756 reference operator*() { return **I; } 757 friend class ParsedAttributesView; 758 }; 759 struct const_iterator 760 : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator, 761 std::random_access_iterator_tag, 762 ParsedAttr> { 763 const_iterator() : iterator_adaptor_base(nullptr) {} 764 const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} 765 766 reference operator*() const { return **I; } 767 friend class ParsedAttributesView; 768 }; 769 770 void addAll(iterator B, iterator E) { 771 AttrList.insert(AttrList.begin(), B.I, E.I); 772 } 773 774 void addAll(const_iterator B, const_iterator E) { 775 AttrList.insert(AttrList.begin(), B.I, E.I); 776 } 777 778 void addAllAtEnd(iterator B, iterator E) { 779 AttrList.insert(AttrList.end(), B.I, E.I); 780 } 781 782 void addAllAtEnd(const_iterator B, const_iterator E) { 783 AttrList.insert(AttrList.end(), B.I, E.I); 784 } 785 786 iterator begin() { return iterator(AttrList.begin()); } 787 const_iterator begin() const { return const_iterator(AttrList.begin()); } 788 iterator end() { return iterator(AttrList.end()); } 789 const_iterator end() const { return const_iterator(AttrList.end()); } 790 791 ParsedAttr &front() { 792 assert(!empty()); 793 return *AttrList.front(); 794 } 795 const ParsedAttr &front() const { 796 assert(!empty()); 797 return *AttrList.front(); 798 } 799 ParsedAttr &back() { 800 assert(!empty()); 801 return *AttrList.back(); 802 } 803 const ParsedAttr &back() const { 804 assert(!empty()); 805 return *AttrList.back(); 806 } 807 808 bool hasAttribute(ParsedAttr::Kind K) const { 809 return llvm::any_of(AttrList, [K](const ParsedAttr *AL) { 810 return AL->getParsedKind() == K; 811 }); 812 } 813 814 private: 815 VecTy AttrList; 816 }; 817 818 /// ParsedAttributes - A collection of parsed attributes. Currently 819 /// we don't differentiate between the various attribute syntaxes, 820 /// which is basically silly. 821 /// 822 /// Right now this is a very lightweight container, but the expectation 823 /// is that this will become significantly more serious. 824 class ParsedAttributes : public ParsedAttributesView { 825 public: 826 ParsedAttributes(AttributeFactory &factory) : pool(factory) {} 827 ParsedAttributes(const ParsedAttributes &) = delete; 828 829 AttributePool &getPool() const { return pool; } 830 831 void takeAllFrom(ParsedAttributes &attrs) { 832 addAll(attrs.begin(), attrs.end()); 833 attrs.clearListOnly(); 834 pool.takeAllFrom(attrs.pool); 835 } 836 837 void takeOneFrom(ParsedAttributes &Attrs, ParsedAttr *PA) { 838 Attrs.getPool().remove(PA); 839 Attrs.remove(PA); 840 getPool().add(PA); 841 addAtEnd(PA); 842 } 843 844 void clear() { 845 clearListOnly(); 846 pool.clear(); 847 } 848 849 /// Add attribute with expression arguments. 850 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 851 IdentifierInfo *scopeName, SourceLocation scopeLoc, 852 ArgsUnion *args, unsigned numArgs, 853 ParsedAttr::Syntax syntax, 854 SourceLocation ellipsisLoc = SourceLocation()) { 855 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, 856 args, numArgs, syntax, ellipsisLoc); 857 addAtEnd(attr); 858 return attr; 859 } 860 861 /// Add availability attribute. 862 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 863 IdentifierInfo *scopeName, SourceLocation scopeLoc, 864 IdentifierLoc *Param, const AvailabilityChange &introduced, 865 const AvailabilityChange &deprecated, 866 const AvailabilityChange &obsoleted, 867 SourceLocation unavailable, const Expr *MessageExpr, 868 ParsedAttr::Syntax syntax, SourceLocation strict, 869 const Expr *ReplacementExpr) { 870 ParsedAttr *attr = pool.create( 871 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, 872 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); 873 addAtEnd(attr); 874 return attr; 875 } 876 877 /// Add objc_bridge_related attribute. 878 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 879 IdentifierInfo *scopeName, SourceLocation scopeLoc, 880 IdentifierLoc *Param1, IdentifierLoc *Param2, 881 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { 882 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, 883 Param1, Param2, Param3, syntax); 884 addAtEnd(attr); 885 return attr; 886 } 887 888 /// Add type_tag_for_datatype attribute. 889 ParsedAttr * 890 addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, 891 IdentifierInfo *scopeName, SourceLocation scopeLoc, 892 IdentifierLoc *argumentKind, 893 ParsedType matchingCType, bool layoutCompatible, 894 bool mustBeNull, ParsedAttr::Syntax syntax) { 895 ParsedAttr *attr = pool.createTypeTagForDatatype( 896 attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, 897 layoutCompatible, mustBeNull, syntax); 898 addAtEnd(attr); 899 return attr; 900 } 901 902 /// Add an attribute with a single type argument. 903 ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 904 IdentifierInfo *scopeName, SourceLocation scopeLoc, 905 ParsedType typeArg, 906 ParsedAttr::Syntax syntaxUsed) { 907 ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, 908 scopeLoc, typeArg, syntaxUsed); 909 addAtEnd(attr); 910 return attr; 911 } 912 913 /// Add microsoft __delspec(property) attribute. 914 ParsedAttr * 915 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 916 IdentifierInfo *scopeName, SourceLocation scopeLoc, 917 IdentifierInfo *getterId, IdentifierInfo *setterId, 918 ParsedAttr::Syntax syntaxUsed) { 919 ParsedAttr *attr = 920 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 921 getterId, setterId, syntaxUsed); 922 addAtEnd(attr); 923 return attr; 924 } 925 926 private: 927 mutable AttributePool pool; 928 }; 929 930 /// These constants match the enumerated choices of 931 /// err_attribute_argument_n_type and err_attribute_argument_type. 932 enum AttributeArgumentNType { 933 AANT_ArgumentIntOrBool, 934 AANT_ArgumentIntegerConstant, 935 AANT_ArgumentString, 936 AANT_ArgumentIdentifier 937 }; 938 939 /// These constants match the enumerated choices of 940 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 941 enum AttributeDeclKind { 942 ExpectedFunction, 943 ExpectedUnion, 944 ExpectedVariableOrFunction, 945 ExpectedFunctionOrMethod, 946 ExpectedFunctionMethodOrBlock, 947 ExpectedFunctionMethodOrParameter, 948 ExpectedVariable, 949 ExpectedVariableOrField, 950 ExpectedVariableFieldOrTag, 951 ExpectedTypeOrNamespace, 952 ExpectedFunctionVariableOrClass, 953 ExpectedKernelFunction, 954 ExpectedFunctionWithProtoType, 955 }; 956 957 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 958 const ParsedAttr &At) { 959 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()), 960 DiagnosticsEngine::ak_identifierinfo); 961 return DB; 962 } 963 964 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, 965 const ParsedAttr &At) { 966 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getAttrName()), 967 DiagnosticsEngine::ak_identifierinfo); 968 return PD; 969 } 970 971 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 972 const ParsedAttr *At) { 973 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()), 974 DiagnosticsEngine::ak_identifierinfo); 975 return DB; 976 } 977 978 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, 979 const ParsedAttr *At) { 980 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()), 981 DiagnosticsEngine::ak_identifierinfo); 982 return PD; 983 } 984 985 } // namespace clang 986 987 #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H 988