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