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_ATTRLIST_H 16 #define LLVM_CLANG_SEMA_ATTRLIST_H 17 18 #include "clang/Basic/SourceLocation.h" 19 #include "clang/Basic/VersionTuple.h" 20 #include "clang/Sema/Ownership.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/Support/Allocator.h" 23 #include <cassert> 24 25 namespace clang { 26 class ASTContext; 27 class IdentifierInfo; 28 class Expr; 29 30 /// \brief Represents information about a change in availability for 31 /// an entity, which is part of the encoding of the 'availability' 32 /// attribute. 33 struct AvailabilityChange { 34 /// \brief The location of the keyword indicating the kind of change. 35 SourceLocation KeywordLoc; 36 37 /// \brief The version number at which the change occurred. 38 VersionTuple Version; 39 40 /// \brief The source range covering the version number. 41 SourceRange VersionRange; 42 43 /// \brief Determine whether this availability change is valid. 44 bool isValid() const { return !Version.empty(); } 45 }; 46 47 /// AttributeList - Represents a syntactic attribute. 48 /// 49 /// For a GNU attribute, there are four forms of this construct: 50 /// 51 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. 52 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. 53 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. 54 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. 55 /// 56 class AttributeList { // TODO: This should really be called ParsedAttribute 57 public: 58 /// The style used to specify an attribute. 59 enum Syntax { 60 /// __attribute__((...)) 61 AS_GNU, 62 /// [[...]] 63 AS_CXX11, 64 /// __declspec(...) 65 AS_Declspec, 66 /// __ptr16, alignas(...), etc. 67 AS_Keyword 68 }; 69 private: 70 IdentifierInfo *AttrName; 71 IdentifierInfo *ScopeName; 72 IdentifierInfo *ParmName; 73 SourceRange AttrRange; 74 SourceLocation ScopeLoc; 75 SourceLocation ParmLoc; 76 SourceLocation EllipsisLoc; 77 78 /// The number of expression arguments this attribute has. 79 /// The expressions themselves are stored after the object. 80 unsigned NumArgs : 16; 81 82 /// Corresponds to the Syntax enum. 83 unsigned SyntaxUsed : 2; 84 85 /// True if already diagnosed as invalid. 86 mutable unsigned Invalid : 1; 87 88 /// True if this attribute was used as a type attribute. 89 mutable unsigned UsedAsTypeAttr : 1; 90 91 /// True if this has the extra information associated with an 92 /// availability attribute. 93 unsigned IsAvailability : 1; 94 95 /// True if this has extra information associated with a 96 /// type_tag_for_datatype attribute. 97 unsigned IsTypeTagForDatatype : 1; 98 99 unsigned AttrKind : 8; 100 101 /// \brief The location of the 'unavailable' keyword in an 102 /// availability attribute. 103 SourceLocation UnavailableLoc; 104 105 const Expr *MessageExpr; 106 107 /// The next attribute in the current position. 108 AttributeList *NextInPosition; 109 110 /// The next attribute allocated in the current Pool. 111 AttributeList *NextInPool; 112 113 Expr **getArgsBuffer() { 114 return reinterpret_cast<Expr**>(this+1); 115 } 116 Expr * const *getArgsBuffer() const { 117 return reinterpret_cast<Expr* const *>(this+1); 118 } 119 120 enum AvailabilitySlot { 121 IntroducedSlot, DeprecatedSlot, ObsoletedSlot 122 }; 123 124 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { 125 return reinterpret_cast<AvailabilityChange*>(this+1)[index]; 126 } 127 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { 128 return reinterpret_cast<const AvailabilityChange*>(this+1)[index]; 129 } 130 131 public: 132 struct TypeTagForDatatypeData { 133 ParsedType *MatchingCType; 134 unsigned LayoutCompatible : 1; 135 unsigned MustBeNull : 1; 136 }; 137 138 private: 139 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { 140 return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1); 141 } 142 143 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { 144 return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1); 145 } 146 147 ParsedType &getTypeBuffer() { 148 return *reinterpret_cast<ParsedType *>(this + 1); 149 } 150 151 const ParsedType &getTypeBuffer() const { 152 return *reinterpret_cast<const ParsedType *>(this + 1); 153 } 154 155 AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION; 156 void operator=(const AttributeList &) LLVM_DELETED_FUNCTION; 157 void operator delete(void *) LLVM_DELETED_FUNCTION; 158 ~AttributeList() LLVM_DELETED_FUNCTION; 159 160 size_t allocated_size() const; 161 162 /// Constructor for attributes with expression arguments. 163 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 164 IdentifierInfo *scopeName, SourceLocation scopeLoc, 165 IdentifierInfo *parmName, SourceLocation parmLoc, 166 Expr **args, unsigned numArgs, 167 Syntax syntaxUsed, SourceLocation ellipsisLoc) 168 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 169 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 170 EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), 171 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 172 IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) { 173 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); 174 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 175 } 176 177 /// Constructor for availability attributes. 178 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 179 IdentifierInfo *scopeName, SourceLocation scopeLoc, 180 IdentifierInfo *parmName, SourceLocation parmLoc, 181 const AvailabilityChange &introduced, 182 const AvailabilityChange &deprecated, 183 const AvailabilityChange &obsoleted, 184 SourceLocation unavailable, 185 const Expr *messageExpr, 186 Syntax syntaxUsed) 187 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 188 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(), 189 NumArgs(0), SyntaxUsed(syntaxUsed), 190 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 191 IsTypeTagForDatatype(false), 192 UnavailableLoc(unavailable), MessageExpr(messageExpr), 193 NextInPosition(0), NextInPool(0) { 194 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); 195 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); 196 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); 197 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 198 } 199 200 /// Constructor for type_tag_for_datatype attribute. 201 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 202 IdentifierInfo *scopeName, SourceLocation scopeLoc, 203 IdentifierInfo *argumentKindName, 204 SourceLocation argumentKindLoc, 205 ParsedType matchingCType, bool layoutCompatible, 206 bool mustBeNull, Syntax syntaxUsed) 207 : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName), 208 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc), 209 EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), 210 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), 211 IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) { 212 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); 213 new (&ExtraData.MatchingCType) ParsedType(matchingCType); 214 ExtraData.LayoutCompatible = layoutCompatible; 215 ExtraData.MustBeNull = mustBeNull; 216 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 217 } 218 219 /// Constructor for attributes with a single type argument. 220 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 221 IdentifierInfo *scopeName, SourceLocation scopeLoc, 222 IdentifierInfo *parmName, SourceLocation parmLoc, 223 ParsedType typeArg, Syntax syntaxUsed) 224 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 225 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 226 EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), 227 UsedAsTypeAttr(false), IsAvailability(false), 228 IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) { 229 new (&getTypeBuffer()) ParsedType(typeArg); 230 AttrKind = getKind(getName(), getScopeName(), syntaxUsed); 231 } 232 233 friend class AttributePool; 234 friend class AttributeFactory; 235 236 public: 237 enum Kind { 238 #define PARSED_ATTR(NAME) AT_##NAME, 239 #include "clang/Sema/AttrParsedAttrList.inc" 240 #undef PARSED_ATTR 241 IgnoredAttribute, 242 UnknownAttribute 243 }; 244 245 IdentifierInfo *getName() const { return AttrName; } 246 SourceLocation getLoc() const { return AttrRange.getBegin(); } 247 SourceRange getRange() const { return AttrRange; } 248 249 bool hasScope() const { return ScopeName; } 250 IdentifierInfo *getScopeName() const { return ScopeName; } 251 SourceLocation getScopeLoc() const { return ScopeLoc; } 252 253 IdentifierInfo *getParameterName() const { return ParmName; } 254 SourceLocation getParameterLoc() const { return ParmLoc; } 255 256 bool isAlignasAttribute() const { 257 // FIXME: Use a better mechanism to determine this. 258 return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword; 259 } 260 261 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } 262 bool isCXX11Attribute() const { 263 return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); 264 } 265 bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; } 266 267 bool isInvalid() const { return Invalid; } 268 void setInvalid(bool b = true) const { Invalid = b; } 269 270 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } 271 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 272 273 bool isPackExpansion() const { return EllipsisLoc.isValid(); } 274 SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 275 276 Kind getKind() const { return Kind(AttrKind); } 277 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, 278 Syntax SyntaxUsed); 279 280 AttributeList *getNext() const { return NextInPosition; } 281 void setNext(AttributeList *N) { NextInPosition = N; } 282 283 /// getNumArgs - Return the number of actual arguments to this attribute. 284 unsigned getNumArgs() const { return NumArgs; } 285 286 /// hasParameterOrArguments - Return true if this attribute has a parameter, 287 /// or has a non empty argument expression list. 288 bool hasParameterOrArguments() const { return ParmName || NumArgs; } 289 290 /// getArg - Return the specified argument. 291 Expr *getArg(unsigned Arg) const { 292 assert(Arg < NumArgs && "Arg access out of range!"); 293 return getArgsBuffer()[Arg]; 294 } 295 296 class arg_iterator { 297 Expr * const *X; 298 unsigned Idx; 299 public: 300 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} 301 302 arg_iterator& operator++() { 303 ++Idx; 304 return *this; 305 } 306 307 bool operator==(const arg_iterator& I) const { 308 assert (X == I.X && 309 "compared arg_iterators are for different argument lists"); 310 return Idx == I.Idx; 311 } 312 313 bool operator!=(const arg_iterator& I) const { 314 return !operator==(I); 315 } 316 317 Expr* operator*() const { 318 return X[Idx]; 319 } 320 321 unsigned getArgNum() const { 322 return Idx+1; 323 } 324 }; 325 326 arg_iterator arg_begin() const { 327 return arg_iterator(getArgsBuffer(), 0); 328 } 329 330 arg_iterator arg_end() const { 331 return arg_iterator(getArgsBuffer(), NumArgs); 332 } 333 334 const AvailabilityChange &getAvailabilityIntroduced() const { 335 assert(getKind() == AT_Availability && "Not an availability attribute"); 336 return getAvailabilitySlot(IntroducedSlot); 337 } 338 339 const AvailabilityChange &getAvailabilityDeprecated() const { 340 assert(getKind() == AT_Availability && "Not an availability attribute"); 341 return getAvailabilitySlot(DeprecatedSlot); 342 } 343 344 const AvailabilityChange &getAvailabilityObsoleted() const { 345 assert(getKind() == AT_Availability && "Not an availability attribute"); 346 return getAvailabilitySlot(ObsoletedSlot); 347 } 348 349 SourceLocation getUnavailableLoc() const { 350 assert(getKind() == AT_Availability && "Not an availability attribute"); 351 return UnavailableLoc; 352 } 353 354 const Expr * getMessageExpr() const { 355 assert(getKind() == AT_Availability && "Not an availability attribute"); 356 return MessageExpr; 357 } 358 359 const ParsedType &getMatchingCType() const { 360 assert(getKind() == AT_TypeTagForDatatype && 361 "Not a type_tag_for_datatype attribute"); 362 return *getTypeTagForDatatypeDataSlot().MatchingCType; 363 } 364 365 bool getLayoutCompatible() const { 366 assert(getKind() == AT_TypeTagForDatatype && 367 "Not a type_tag_for_datatype attribute"); 368 return getTypeTagForDatatypeDataSlot().LayoutCompatible; 369 } 370 371 bool getMustBeNull() const { 372 assert(getKind() == AT_TypeTagForDatatype && 373 "Not a type_tag_for_datatype attribute"); 374 return getTypeTagForDatatypeDataSlot().MustBeNull; 375 } 376 377 const ParsedType &getTypeArg() const { 378 assert(getKind() == AT_VecTypeHint && "Not a type attribute"); 379 return getTypeBuffer(); 380 } 381 382 /// \brief Get an index into the attribute spelling list 383 /// defined in Attr.td. This index is used by an attribute 384 /// to pretty print itself. 385 unsigned getAttributeSpellingListIndex() const; 386 }; 387 388 /// A factory, from which one makes pools, from which one creates 389 /// individual attributes which are deallocated with the pool. 390 /// 391 /// Note that it's tolerably cheap to create and destroy one of 392 /// these as long as you don't actually allocate anything in it. 393 class AttributeFactory { 394 public: 395 enum { 396 /// The required allocation size of an availability attribute, 397 /// which we want to ensure is a multiple of sizeof(void*). 398 AvailabilityAllocSize = 399 sizeof(AttributeList) 400 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) 401 / sizeof(void*) * sizeof(void*)), 402 TypeTagForDatatypeAllocSize = 403 sizeof(AttributeList) 404 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1) 405 / sizeof(void*) * sizeof(void*) 406 }; 407 408 private: 409 enum { 410 /// The number of free lists we want to be sure to support 411 /// inline. This is just enough that availability attributes 412 /// don't surpass it. It's actually very unlikely we'll see an 413 /// attribute that needs more than that; on x86-64 you'd need 10 414 /// expression arguments, and on i386 you'd need 19. 415 InlineFreeListsCapacity = 416 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 417 }; 418 419 llvm::BumpPtrAllocator Alloc; 420 421 /// Free lists. The index is determined by the following formula: 422 /// (size - sizeof(AttributeList)) / sizeof(void*) 423 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 424 425 // The following are the private interface used by AttributePool. 426 friend class AttributePool; 427 428 /// Allocate an attribute of the given size. 429 void *allocate(size_t size); 430 431 /// Reclaim all the attributes in the given pool chain, which is 432 /// non-empty. Note that the current implementation is safe 433 /// against reclaiming things which were not actually allocated 434 /// with the allocator, although of course it's important to make 435 /// sure that their allocator lives at least as long as this one. 436 void reclaimPool(AttributeList *head); 437 438 public: 439 AttributeFactory(); 440 ~AttributeFactory(); 441 }; 442 443 class AttributePool { 444 AttributeFactory &Factory; 445 AttributeList *Head; 446 447 void *allocate(size_t size) { 448 return Factory.allocate(size); 449 } 450 451 AttributeList *add(AttributeList *attr) { 452 // We don't care about the order of the pool. 453 attr->NextInPool = Head; 454 Head = attr; 455 return attr; 456 } 457 458 void takePool(AttributeList *pool); 459 460 public: 461 /// Create a new pool for a factory. 462 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} 463 464 /// Move the given pool's allocations to this pool. 465 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 466 pool.Head = 0; 467 } 468 469 AttributeFactory &getFactory() const { return Factory; } 470 471 void clear() { 472 if (Head) { 473 Factory.reclaimPool(Head); 474 Head = 0; 475 } 476 } 477 478 /// Take the given pool's allocations and add them to this pool. 479 void takeAllFrom(AttributePool &pool) { 480 if (pool.Head) { 481 takePool(pool.Head); 482 pool.Head = 0; 483 } 484 } 485 486 ~AttributePool() { 487 if (Head) Factory.reclaimPool(Head); 488 } 489 490 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 491 IdentifierInfo *scopeName, SourceLocation scopeLoc, 492 IdentifierInfo *parmName, SourceLocation parmLoc, 493 Expr **args, unsigned numArgs, 494 AttributeList::Syntax syntax, 495 SourceLocation ellipsisLoc = SourceLocation()) { 496 void *memory = allocate(sizeof(AttributeList) 497 + numArgs * sizeof(Expr*)); 498 return add(new (memory) AttributeList(attrName, attrRange, 499 scopeName, scopeLoc, 500 parmName, parmLoc, 501 args, numArgs, syntax, 502 ellipsisLoc)); 503 } 504 505 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 506 IdentifierInfo *scopeName, SourceLocation scopeLoc, 507 IdentifierInfo *parmName, SourceLocation parmLoc, 508 const AvailabilityChange &introduced, 509 const AvailabilityChange &deprecated, 510 const AvailabilityChange &obsoleted, 511 SourceLocation unavailable, 512 const Expr *MessageExpr, 513 AttributeList::Syntax syntax) { 514 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 515 return add(new (memory) AttributeList(attrName, attrRange, 516 scopeName, scopeLoc, 517 parmName, parmLoc, 518 introduced, deprecated, obsoleted, 519 unavailable, MessageExpr, syntax)); 520 } 521 522 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 523 SourceLocation TokLoc, int Arg); 524 525 AttributeList *createTypeTagForDatatype( 526 IdentifierInfo *attrName, SourceRange attrRange, 527 IdentifierInfo *scopeName, SourceLocation scopeLoc, 528 IdentifierInfo *argumentKindName, 529 SourceLocation argumentKindLoc, 530 ParsedType matchingCType, bool layoutCompatible, 531 bool mustBeNull, AttributeList::Syntax syntax) { 532 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 533 return add(new (memory) AttributeList(attrName, attrRange, 534 scopeName, scopeLoc, 535 argumentKindName, argumentKindLoc, 536 matchingCType, layoutCompatible, 537 mustBeNull, syntax)); 538 } 539 540 AttributeList *createTypeAttribute( 541 IdentifierInfo *attrName, SourceRange attrRange, 542 IdentifierInfo *scopeName, SourceLocation scopeLoc, 543 IdentifierInfo *parmName, SourceLocation parmLoc, 544 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 545 void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); 546 return add(new (memory) AttributeList(attrName, attrRange, 547 scopeName, scopeLoc, 548 parmName, parmLoc, 549 typeArg, syntaxUsed)); 550 } 551 }; 552 553 /// addAttributeLists - Add two AttributeLists together 554 /// The right-hand list is appended to the left-hand list, if any 555 /// A pointer to the joined list is returned. 556 /// Note: the lists are not left unmodified. 557 inline AttributeList *addAttributeLists(AttributeList *Left, 558 AttributeList *Right) { 559 if (!Left) 560 return Right; 561 562 AttributeList *next = Left, *prev; 563 do { 564 prev = next; 565 next = next->getNext(); 566 } while (next); 567 prev->setNext(Right); 568 return Left; 569 } 570 571 /// CXX11AttributeList - A wrapper around a C++11 attribute list. 572 /// Stores, in addition to the list proper, whether or not an actual list was 573 /// (as opposed to an empty list, which may be ill-formed in some places) and 574 /// the source range of the list. 575 struct CXX11AttributeList { 576 AttributeList *AttrList; 577 SourceRange Range; 578 bool HasAttr; 579 CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) 580 : AttrList(attrList), Range(range), HasAttr (hasAttr) { 581 } 582 CXX11AttributeList () 583 : AttrList(0), Range(), HasAttr(false) { 584 } 585 }; 586 587 /// ParsedAttributes - A collection of parsed attributes. Currently 588 /// we don't differentiate between the various attribute syntaxes, 589 /// which is basically silly. 590 /// 591 /// Right now this is a very lightweight container, but the expectation 592 /// is that this will become significantly more serious. 593 class ParsedAttributes { 594 public: 595 ParsedAttributes(AttributeFactory &factory) 596 : pool(factory), list(0) { 597 } 598 599 ParsedAttributes(ParsedAttributes &attrs) 600 : pool(attrs.pool), list(attrs.list) { 601 attrs.list = 0; 602 } 603 604 AttributePool &getPool() const { return pool; } 605 606 bool empty() const { return list == 0; } 607 608 void add(AttributeList *newAttr) { 609 assert(newAttr); 610 assert(newAttr->getNext() == 0); 611 newAttr->setNext(list); 612 list = newAttr; 613 } 614 615 void addAll(AttributeList *newList) { 616 if (!newList) return; 617 618 AttributeList *lastInNewList = newList; 619 while (AttributeList *next = lastInNewList->getNext()) 620 lastInNewList = next; 621 622 lastInNewList->setNext(list); 623 list = newList; 624 } 625 626 void set(AttributeList *newList) { 627 list = newList; 628 } 629 630 void takeAllFrom(ParsedAttributes &attrs) { 631 addAll(attrs.list); 632 attrs.list = 0; 633 pool.takeAllFrom(attrs.pool); 634 } 635 636 void clear() { list = 0; pool.clear(); } 637 AttributeList *getList() const { return list; } 638 639 /// Returns a reference to the attribute list. Try not to introduce 640 /// dependencies on this method, it may not be long-lived. 641 AttributeList *&getListRef() { return list; } 642 643 /// Add attribute with expression arguments. 644 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 645 IdentifierInfo *scopeName, SourceLocation scopeLoc, 646 IdentifierInfo *parmName, SourceLocation parmLoc, 647 Expr **args, unsigned numArgs, 648 AttributeList::Syntax syntax, 649 SourceLocation ellipsisLoc = SourceLocation()) { 650 AttributeList *attr = 651 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 652 args, numArgs, syntax, ellipsisLoc); 653 add(attr); 654 return attr; 655 } 656 657 /// Add availability attribute. 658 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 659 IdentifierInfo *scopeName, SourceLocation scopeLoc, 660 IdentifierInfo *parmName, SourceLocation parmLoc, 661 const AvailabilityChange &introduced, 662 const AvailabilityChange &deprecated, 663 const AvailabilityChange &obsoleted, 664 SourceLocation unavailable, 665 const Expr *MessageExpr, 666 AttributeList::Syntax syntax) { 667 AttributeList *attr = 668 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 669 introduced, deprecated, obsoleted, unavailable, 670 MessageExpr, syntax); 671 add(attr); 672 return attr; 673 } 674 675 /// Add type_tag_for_datatype attribute. 676 AttributeList *addNewTypeTagForDatatype( 677 IdentifierInfo *attrName, SourceRange attrRange, 678 IdentifierInfo *scopeName, SourceLocation scopeLoc, 679 IdentifierInfo *argumentKindName, 680 SourceLocation argumentKindLoc, 681 ParsedType matchingCType, bool layoutCompatible, 682 bool mustBeNull, AttributeList::Syntax syntax) { 683 AttributeList *attr = 684 pool.createTypeTagForDatatype(attrName, attrRange, 685 scopeName, scopeLoc, 686 argumentKindName, argumentKindLoc, 687 matchingCType, layoutCompatible, 688 mustBeNull, syntax); 689 add(attr); 690 return attr; 691 } 692 693 /// Add an attribute with a single type argument. 694 AttributeList * 695 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 696 IdentifierInfo *scopeName, SourceLocation scopeLoc, 697 IdentifierInfo *parmName, SourceLocation parmLoc, 698 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 699 AttributeList *attr = 700 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, 701 parmName, parmLoc, typeArg, syntaxUsed); 702 add(attr); 703 return attr; 704 } 705 706 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, 707 SourceLocation loc, int arg) { 708 AttributeList *attr = 709 pool.createIntegerAttribute(C, name, loc, arg); 710 add(attr); 711 return attr; 712 } 713 714 715 private: 716 mutable AttributePool pool; 717 AttributeList *list; 718 }; 719 720 } // end namespace clang 721 722 #endif 723