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