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