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