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