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