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