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