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(HasParsedType && "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 bool hasCustomParsing() const; 468 unsigned getMinArgs() const; 469 unsigned getMaxArgs() const; 470}; 471 472/// A factory, from which one makes pools, from which one creates 473/// individual attributes which are deallocated with the pool. 474/// 475/// Note that it's tolerably cheap to create and destroy one of 476/// these as long as you don't actually allocate anything in it. 477class AttributeFactory { 478public: 479 enum { 480 /// The required allocation size of an availability attribute, 481 /// which we want to ensure is a multiple of sizeof(void*). 482 AvailabilityAllocSize = 483 sizeof(AttributeList) 484 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) + 485 sizeof(ArgsUnion) - 1) 486 / sizeof(void*) * sizeof(void*)), 487 TypeTagForDatatypeAllocSize = 488 sizeof(AttributeList) 489 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + 490 sizeof(ArgsUnion) - 1) 491 / sizeof(void*) * sizeof(void*), 492 PropertyAllocSize = 493 sizeof(AttributeList) 494 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) 495 / sizeof(void*) * sizeof(void*) 496 }; 497 498private: 499 enum { 500 /// The number of free lists we want to be sure to support 501 /// inline. This is just enough that availability attributes 502 /// don't surpass it. It's actually very unlikely we'll see an 503 /// attribute that needs more than that; on x86-64 you'd need 10 504 /// expression arguments, and on i386 you'd need 19. 505 InlineFreeListsCapacity = 506 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 507 }; 508 509 llvm::BumpPtrAllocator Alloc; 510 511 /// Free lists. The index is determined by the following formula: 512 /// (size - sizeof(AttributeList)) / sizeof(void*) 513 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 514 515 // The following are the private interface used by AttributePool. 516 friend class AttributePool; 517 518 /// Allocate an attribute of the given size. 519 void *allocate(size_t size); 520 521 /// Reclaim all the attributes in the given pool chain, which is 522 /// non-empty. Note that the current implementation is safe 523 /// against reclaiming things which were not actually allocated 524 /// with the allocator, although of course it's important to make 525 /// sure that their allocator lives at least as long as this one. 526 void reclaimPool(AttributeList *head); 527 528public: 529 AttributeFactory(); 530 ~AttributeFactory(); 531}; 532 533class AttributePool { 534 AttributeFactory &Factory; 535 AttributeList *Head; 536 537 void *allocate(size_t size) { 538 return Factory.allocate(size); 539 } 540 541 AttributeList *add(AttributeList *attr) { 542 // We don't care about the order of the pool. 543 attr->NextInPool = Head; 544 Head = attr; 545 return attr; 546 } 547 548 void takePool(AttributeList *pool); 549 550public: 551 /// Create a new pool for a factory. 552 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} 553 554 /// Move the given pool's allocations to this pool. 555 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 556 pool.Head = 0; 557 } 558 559 AttributeFactory &getFactory() const { return Factory; } 560 561 void clear() { 562 if (Head) { 563 Factory.reclaimPool(Head); 564 Head = 0; 565 } 566 } 567 568 /// Take the given pool's allocations and add them to this pool. 569 void takeAllFrom(AttributePool &pool) { 570 if (pool.Head) { 571 takePool(pool.Head); 572 pool.Head = 0; 573 } 574 } 575 576 ~AttributePool() { 577 if (Head) Factory.reclaimPool(Head); 578 } 579 580 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 581 IdentifierInfo *scopeName, SourceLocation scopeLoc, 582 ArgsUnion *args, unsigned numArgs, 583 AttributeList::Syntax syntax, 584 SourceLocation ellipsisLoc = SourceLocation()) { 585 void *memory = allocate(sizeof(AttributeList) 586 + numArgs * sizeof(ArgsUnion)); 587 return add(new (memory) AttributeList(attrName, attrRange, 588 scopeName, scopeLoc, 589 args, numArgs, syntax, 590 ellipsisLoc)); 591 } 592 593 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 594 IdentifierInfo *scopeName, SourceLocation scopeLoc, 595 IdentifierLoc *Param, 596 const AvailabilityChange &introduced, 597 const AvailabilityChange &deprecated, 598 const AvailabilityChange &obsoleted, 599 SourceLocation unavailable, 600 const Expr *MessageExpr, 601 AttributeList::Syntax syntax) { 602 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 603 return add(new (memory) AttributeList(attrName, attrRange, 604 scopeName, scopeLoc, 605 Param, introduced, deprecated, 606 obsoleted, unavailable, MessageExpr, 607 syntax)); 608 } 609 610 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 611 SourceLocation TokLoc, int Arg); 612 613 AttributeList *createTypeTagForDatatype( 614 IdentifierInfo *attrName, SourceRange attrRange, 615 IdentifierInfo *scopeName, SourceLocation scopeLoc, 616 IdentifierLoc *argumentKind, ParsedType matchingCType, 617 bool layoutCompatible, bool mustBeNull, 618 AttributeList::Syntax syntax) { 619 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 620 return add(new (memory) AttributeList(attrName, attrRange, 621 scopeName, scopeLoc, 622 argumentKind, matchingCType, 623 layoutCompatible, mustBeNull, 624 syntax)); 625 } 626 627 AttributeList *createTypeAttribute( 628 IdentifierInfo *attrName, SourceRange attrRange, 629 IdentifierInfo *scopeName, SourceLocation scopeLoc, 630 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 631 void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); 632 return add(new (memory) AttributeList(attrName, attrRange, 633 scopeName, scopeLoc, 634 typeArg, syntaxUsed)); 635 } 636 637 AttributeList *createPropertyAttribute( 638 IdentifierInfo *attrName, SourceRange attrRange, 639 IdentifierInfo *scopeName, SourceLocation scopeLoc, 640 IdentifierInfo *getterId, IdentifierInfo *setterId, 641 AttributeList::Syntax syntaxUsed) { 642 void *memory = allocate(AttributeFactory::PropertyAllocSize); 643 return add(new (memory) AttributeList(attrName, attrRange, 644 scopeName, scopeLoc, 645 getterId, setterId, 646 syntaxUsed)); 647 } 648}; 649 650/// addAttributeLists - Add two AttributeLists together 651/// The right-hand list is appended to the left-hand list, if any 652/// A pointer to the joined list is returned. 653/// Note: the lists are not left unmodified. 654inline AttributeList *addAttributeLists(AttributeList *Left, 655 AttributeList *Right) { 656 if (!Left) 657 return Right; 658 659 AttributeList *next = Left, *prev; 660 do { 661 prev = next; 662 next = next->getNext(); 663 } while (next); 664 prev->setNext(Right); 665 return Left; 666} 667 668/// CXX11AttributeList - A wrapper around a C++11 attribute list. 669/// Stores, in addition to the list proper, whether or not an actual list was 670/// (as opposed to an empty list, which may be ill-formed in some places) and 671/// the source range of the list. 672struct CXX11AttributeList { 673 AttributeList *AttrList; 674 SourceRange Range; 675 bool HasAttr; 676 CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) 677 : AttrList(attrList), Range(range), HasAttr (hasAttr) { 678 } 679 CXX11AttributeList () 680 : AttrList(0), Range(), HasAttr(false) { 681 } 682}; 683 684/// ParsedAttributes - A collection of parsed attributes. Currently 685/// we don't differentiate between the various attribute syntaxes, 686/// which is basically silly. 687/// 688/// Right now this is a very lightweight container, but the expectation 689/// is that this will become significantly more serious. 690class ParsedAttributes { 691public: 692 ParsedAttributes(AttributeFactory &factory) 693 : pool(factory), list(0) { 694 } 695 696 ParsedAttributes(ParsedAttributes &attrs) 697 : pool(attrs.pool), list(attrs.list) { 698 attrs.list = 0; 699 } 700 701 AttributePool &getPool() const { return pool; } 702 703 bool empty() const { return list == 0; } 704 705 void add(AttributeList *newAttr) { 706 assert(newAttr); 707 assert(newAttr->getNext() == 0); 708 newAttr->setNext(list); 709 list = newAttr; 710 } 711 712 void addAll(AttributeList *newList) { 713 if (!newList) return; 714 715 AttributeList *lastInNewList = newList; 716 while (AttributeList *next = lastInNewList->getNext()) 717 lastInNewList = next; 718 719 lastInNewList->setNext(list); 720 list = newList; 721 } 722 723 void set(AttributeList *newList) { 724 list = newList; 725 } 726 727 void takeAllFrom(ParsedAttributes &attrs) { 728 addAll(attrs.list); 729 attrs.list = 0; 730 pool.takeAllFrom(attrs.pool); 731 } 732 733 void clear() { list = 0; pool.clear(); } 734 AttributeList *getList() const { return list; } 735 736 /// Returns a reference to the attribute list. Try not to introduce 737 /// dependencies on this method, it may not be long-lived. 738 AttributeList *&getListRef() { return list; } 739 740 /// Add attribute with expression arguments. 741 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 742 IdentifierInfo *scopeName, SourceLocation scopeLoc, 743 ArgsUnion *args, unsigned numArgs, 744 AttributeList::Syntax syntax, 745 SourceLocation ellipsisLoc = SourceLocation()) { 746 AttributeList *attr = 747 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, 748 syntax, ellipsisLoc); 749 add(attr); 750 return attr; 751 } 752 753 /// Add availability attribute. 754 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 755 IdentifierInfo *scopeName, SourceLocation scopeLoc, 756 IdentifierLoc *Param, 757 const AvailabilityChange &introduced, 758 const AvailabilityChange &deprecated, 759 const AvailabilityChange &obsoleted, 760 SourceLocation unavailable, 761 const Expr *MessageExpr, 762 AttributeList::Syntax syntax) { 763 AttributeList *attr = 764 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, 765 deprecated, obsoleted, unavailable, MessageExpr, syntax); 766 add(attr); 767 return attr; 768 } 769 770 /// Add type_tag_for_datatype attribute. 771 AttributeList *addNewTypeTagForDatatype( 772 IdentifierInfo *attrName, SourceRange attrRange, 773 IdentifierInfo *scopeName, SourceLocation scopeLoc, 774 IdentifierLoc *argumentKind, ParsedType matchingCType, 775 bool layoutCompatible, bool mustBeNull, 776 AttributeList::Syntax syntax) { 777 AttributeList *attr = 778 pool.createTypeTagForDatatype(attrName, attrRange, 779 scopeName, scopeLoc, 780 argumentKind, matchingCType, 781 layoutCompatible, mustBeNull, syntax); 782 add(attr); 783 return attr; 784 } 785 786 /// Add an attribute with a single type argument. 787 AttributeList * 788 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 789 IdentifierInfo *scopeName, SourceLocation scopeLoc, 790 ParsedType typeArg, AttributeList::Syntax syntaxUsed) { 791 AttributeList *attr = 792 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, 793 typeArg, syntaxUsed); 794 add(attr); 795 return attr; 796 } 797 798 /// Add microsoft __delspec(property) attribute. 799 AttributeList * 800 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 801 IdentifierInfo *scopeName, SourceLocation scopeLoc, 802 IdentifierInfo *getterId, IdentifierInfo *setterId, 803 AttributeList::Syntax syntaxUsed) { 804 AttributeList *attr = 805 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 806 getterId, setterId, syntaxUsed); 807 add(attr); 808 return attr; 809 } 810 811 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, 812 SourceLocation loc, int arg) { 813 AttributeList *attr = 814 pool.createIntegerAttribute(C, name, loc, arg); 815 add(attr); 816 return attr; 817 } 818 819 820private: 821 mutable AttributePool pool; 822 AttributeList *list; 823}; 824 825/// These constants match the enumerated choices of 826/// err_attribute_argument_n_type and err_attribute_argument_type. 827enum AttributeArgumentNType { 828 AANT_ArgumentIntOrBool, 829 AANT_ArgumentIntegerConstant, 830 AANT_ArgumentString, 831 AANT_ArgumentIdentifier 832}; 833 834} // end namespace clang 835 836#endif 837