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/SourceLocation.h"
19 #include "clang/Basic/TargetInfo.h"
20 #include "clang/Basic/VersionTuple.h"
21 #include "clang/Sema/Ownership.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include "llvm/ADT/SmallVector.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.
isValidAvailabilityChange46   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     /// Context-sensitive version of a keyword attribute.
85     AS_ContextSensitiveKeyword,
86     /// #pragma ...
87     AS_Pragma
88   };
89 
90 private:
91   IdentifierInfo *AttrName;
92   IdentifierInfo *ScopeName;
93   SourceRange AttrRange;
94   SourceLocation ScopeLoc;
95   SourceLocation EllipsisLoc;
96 
97   /// The number of expression arguments this attribute has.
98   /// The expressions themselves are stored after the object.
99   unsigned NumArgs : 15;
100 
101   /// Corresponds to the Syntax enum.
102   unsigned SyntaxUsed : 3;
103 
104   /// True if already diagnosed as invalid.
105   mutable unsigned Invalid : 1;
106 
107   /// True if this attribute was used as a type attribute.
108   mutable unsigned UsedAsTypeAttr : 1;
109 
110   /// True if this has the extra information associated with an
111   /// availability attribute.
112   unsigned IsAvailability : 1;
113 
114   /// True if this has extra information associated with a
115   /// type_tag_for_datatype attribute.
116   unsigned IsTypeTagForDatatype : 1;
117 
118   /// True if this has extra information associated with a
119   /// Microsoft __delcspec(property) attribute.
120   unsigned IsProperty : 1;
121 
122   /// True if this has a ParsedType
123   unsigned HasParsedType : 1;
124 
125   unsigned AttrKind : 8;
126 
127   /// \brief The location of the 'unavailable' keyword in an
128   /// availability attribute.
129   SourceLocation UnavailableLoc;
130 
131   const Expr *MessageExpr;
132 
133   /// The next attribute in the current position.
134   AttributeList *NextInPosition;
135 
136   /// The next attribute allocated in the current Pool.
137   AttributeList *NextInPool;
138 
139   /// Arguments, if any, are stored immediately following the object.
getArgsBuffer()140   ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
getArgsBuffer()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.
getAvailabilitySlot(AvailabilitySlot index)151   AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
152     return reinterpret_cast<AvailabilityChange*>(getArgsBuffer()
153                                                  + NumArgs)[index];
154   }
getAvailabilitySlot(AvailabilitySlot index)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;
PropertyDataPropertyData168     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.
getTypeTagForDatatypeDataSlot()176   TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
177     return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
178   }
179 
getTypeTagForDatatypeDataSlot()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.
getTypeBuffer()187   ParsedType &getTypeBuffer() {
188     return *reinterpret_cast<ParsedType *>(this + 1);
189   }
190 
getTypeBuffer()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.
getPropertyDataBuffer()197   PropertyData &getPropertyDataBuffer() {
198     assert(IsProperty);
199     return *reinterpret_cast<PropertyData*>(this + 1);
200   }
201 
getPropertyDataBuffer()202   const PropertyData &getPropertyDataBuffer() const {
203     assert(IsProperty);
204     return *reinterpret_cast<const PropertyData*>(this + 1);
205   }
206 
207   AttributeList(const AttributeList &) = delete;
208   void operator=(const AttributeList &) = delete;
209   void operator delete(void *) = delete;
210   ~AttributeList() = delete;
211 
212   size_t allocated_size() const;
213 
214   /// Constructor for attributes with expression arguments.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ArgsUnion * args,unsigned numArgs,Syntax syntaxUsed,SourceLocation ellipsisLoc)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.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Parm,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * messageExpr,Syntax syntaxUsed)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.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Parm1,IdentifierLoc * Parm2,IdentifierLoc * Parm3,Syntax syntaxUsed)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.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * ArgKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,Syntax syntaxUsed)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.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,Syntax syntaxUsed)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.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,Syntax syntaxUsed)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 
getName()329   IdentifierInfo *getName() const { return AttrName; }
getLoc()330   SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()331   SourceRange getRange() const { return AttrRange; }
332 
hasScope()333   bool hasScope() const { return ScopeName; }
getScopeName()334   IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()335   SourceLocation getScopeLoc() const { return ScopeLoc; }
336 
hasParsedType()337   bool hasParsedType() const { return HasParsedType; }
338 
339   /// Is this the Microsoft __declspec(property) attribute?
isDeclspecPropertyAttribute()340   bool isDeclspecPropertyAttribute() const  {
341     return IsProperty;
342   }
343 
isAlignasAttribute()344   bool isAlignasAttribute() const {
345     // FIXME: Use a better mechanism to determine this.
346     return getKind() == AT_Aligned && isKeywordAttribute();
347   }
348 
isDeclspecAttribute()349   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
isCXX11Attribute()350   bool isCXX11Attribute() const {
351     return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
352   }
isKeywordAttribute()353   bool isKeywordAttribute() const {
354     return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
355   }
356 
isContextSensitiveKeywordAttribute()357   bool isContextSensitiveKeywordAttribute() const {
358     return SyntaxUsed == AS_ContextSensitiveKeyword;
359   }
360 
isInvalid()361   bool isInvalid() const { return Invalid; }
362   void setInvalid(bool b = true) const { Invalid = b; }
363 
isUsedAsTypeAttr()364   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()365   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
366 
isPackExpansion()367   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
getEllipsisLoc()368   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
369 
getKind()370   Kind getKind() const { return Kind(AttrKind); }
371   static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
372                       Syntax SyntaxUsed);
373 
getNext()374   AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)375   void setNext(AttributeList *N) { NextInPosition = N; }
376 
377   /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()378   unsigned getNumArgs() const { return NumArgs; }
379 
380   /// getArg - Return the specified argument.
getArg(unsigned Arg)381   ArgsUnion getArg(unsigned Arg) const {
382     assert(Arg < NumArgs && "Arg access out of range!");
383     return getArgsBuffer()[Arg];
384   }
385 
isArgExpr(unsigned Arg)386   bool isArgExpr(unsigned Arg) const {
387     return Arg < NumArgs && getArg(Arg).is<Expr*>();
388   }
getArgAsExpr(unsigned Arg)389   Expr *getArgAsExpr(unsigned Arg) const {
390     return getArg(Arg).get<Expr*>();
391   }
392 
isArgIdent(unsigned Arg)393   bool isArgIdent(unsigned Arg) const {
394     return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
395   }
getArgAsIdent(unsigned Arg)396   IdentifierLoc *getArgAsIdent(unsigned Arg) const {
397     return getArg(Arg).get<IdentifierLoc*>();
398   }
399 
getAvailabilityIntroduced()400   const AvailabilityChange &getAvailabilityIntroduced() const {
401     assert(getKind() == AT_Availability && "Not an availability attribute");
402     return getAvailabilitySlot(IntroducedSlot);
403   }
404 
getAvailabilityDeprecated()405   const AvailabilityChange &getAvailabilityDeprecated() const {
406     assert(getKind() == AT_Availability && "Not an availability attribute");
407     return getAvailabilitySlot(DeprecatedSlot);
408   }
409 
getAvailabilityObsoleted()410   const AvailabilityChange &getAvailabilityObsoleted() const {
411     assert(getKind() == AT_Availability && "Not an availability attribute");
412     return getAvailabilitySlot(ObsoletedSlot);
413   }
414 
getUnavailableLoc()415   SourceLocation getUnavailableLoc() const {
416     assert(getKind() == AT_Availability && "Not an availability attribute");
417     return UnavailableLoc;
418   }
419 
getMessageExpr()420   const Expr * getMessageExpr() const {
421     assert(getKind() == AT_Availability && "Not an availability attribute");
422     return MessageExpr;
423   }
424 
getMatchingCType()425   const ParsedType &getMatchingCType() const {
426     assert(getKind() == AT_TypeTagForDatatype &&
427            "Not a type_tag_for_datatype attribute");
428     return *getTypeTagForDatatypeDataSlot().MatchingCType;
429   }
430 
getLayoutCompatible()431   bool getLayoutCompatible() const {
432     assert(getKind() == AT_TypeTagForDatatype &&
433            "Not a type_tag_for_datatype attribute");
434     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
435   }
436 
getMustBeNull()437   bool getMustBeNull() const {
438     assert(getKind() == AT_TypeTagForDatatype &&
439            "Not a type_tag_for_datatype attribute");
440     return getTypeTagForDatatypeDataSlot().MustBeNull;
441   }
442 
getTypeArg()443   const ParsedType &getTypeArg() const {
444     assert(HasParsedType && "Not a type attribute");
445     return getTypeBuffer();
446   }
447 
getPropertyData()448   const PropertyData &getPropertyData() const {
449     assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
450     return getPropertyDataBuffer();
451   }
452 
453   /// \brief Get an index into the attribute spelling list
454   /// defined in Attr.td. This index is used by an attribute
455   /// to pretty print itself.
456   unsigned getAttributeSpellingListIndex() const;
457 
458   bool isTargetSpecificAttr() const;
459   bool isTypeAttr() const;
460 
461   bool hasCustomParsing() const;
462   unsigned getMinArgs() const;
463   unsigned getMaxArgs() const;
464   bool hasVariadicArg() const;
465   bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
466   bool diagnoseLangOpts(class Sema &S) const;
467   bool existsInTarget(const TargetInfo &Target) const;
468   bool isKnownToGCC() const;
469 
470   /// \brief If the parsed attribute has a semantic equivalent, and it would
471   /// have a semantic Spelling enumeration (due to having semantically-distinct
472   /// spelling variations), return the value of that semantic spelling. If the
473   /// parsed attribute does not have a semantic equivalent, or would not have
474   /// a Spelling enumeration, the value UINT_MAX is returned.
475   unsigned getSemanticSpelling() const;
476 };
477 
478 /// A factory, from which one makes pools, from which one creates
479 /// individual attributes which are deallocated with the pool.
480 ///
481 /// Note that it's tolerably cheap to create and destroy one of
482 /// these as long as you don't actually allocate anything in it.
483 class AttributeFactory {
484 public:
485   enum {
486     /// The required allocation size of an availability attribute,
487     /// which we want to ensure is a multiple of sizeof(void*).
488     AvailabilityAllocSize =
489       sizeof(AttributeList)
490       + ((3 * sizeof(AvailabilityChange) + sizeof(void*) +
491          sizeof(ArgsUnion) - 1)
492          / sizeof(void*) * sizeof(void*)),
493     TypeTagForDatatypeAllocSize =
494       sizeof(AttributeList)
495       + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
496          sizeof(ArgsUnion) - 1)
497         / sizeof(void*) * sizeof(void*),
498     PropertyAllocSize =
499       sizeof(AttributeList)
500       + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
501         / sizeof(void*) * sizeof(void*)
502   };
503 
504 private:
505   enum {
506     /// The number of free lists we want to be sure to support
507     /// inline.  This is just enough that availability attributes
508     /// don't surpass it.  It's actually very unlikely we'll see an
509     /// attribute that needs more than that; on x86-64 you'd need 10
510     /// expression arguments, and on i386 you'd need 19.
511     InlineFreeListsCapacity =
512       1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
513   };
514 
515   llvm::BumpPtrAllocator Alloc;
516 
517   /// Free lists.  The index is determined by the following formula:
518   ///   (size - sizeof(AttributeList)) / sizeof(void*)
519   SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
520 
521   // The following are the private interface used by AttributePool.
522   friend class AttributePool;
523 
524   /// Allocate an attribute of the given size.
525   void *allocate(size_t size);
526 
527   /// Reclaim all the attributes in the given pool chain, which is
528   /// non-empty.  Note that the current implementation is safe
529   /// against reclaiming things which were not actually allocated
530   /// with the allocator, although of course it's important to make
531   /// sure that their allocator lives at least as long as this one.
532   void reclaimPool(AttributeList *head);
533 
534 public:
535   AttributeFactory();
536   ~AttributeFactory();
537 };
538 
539 class AttributePool {
540   AttributeFactory &Factory;
541   AttributeList *Head;
542 
allocate(size_t size)543   void *allocate(size_t size) {
544     return Factory.allocate(size);
545   }
546 
add(AttributeList * attr)547   AttributeList *add(AttributeList *attr) {
548     // We don't care about the order of the pool.
549     attr->NextInPool = Head;
550     Head = attr;
551     return attr;
552   }
553 
554   void takePool(AttributeList *pool);
555 
556 public:
557   /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)558   AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
559 
560   AttributePool(const AttributePool &) = delete;
561 
562   /// Move the given pool's allocations to this pool.
AttributePool(AttributePool && pool)563   AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
564     pool.Head = nullptr;
565   }
566 
getFactory()567   AttributeFactory &getFactory() const { return Factory; }
568 
clear()569   void clear() {
570     if (Head) {
571       Factory.reclaimPool(Head);
572       Head = nullptr;
573     }
574   }
575 
576   /// Take the given pool's allocations and add them to this pool.
takeAllFrom(AttributePool & pool)577   void takeAllFrom(AttributePool &pool) {
578     if (pool.Head) {
579       takePool(pool.Head);
580       pool.Head = nullptr;
581     }
582   }
583 
~AttributePool()584   ~AttributePool() {
585     if (Head) Factory.reclaimPool(Head);
586   }
587 
588   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
589                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
590                         ArgsUnion *args, unsigned numArgs,
591                         AttributeList::Syntax syntax,
592                         SourceLocation ellipsisLoc = SourceLocation()) {
593     void *memory = allocate(sizeof(AttributeList)
594                             + numArgs * sizeof(ArgsUnion));
595     return add(new (memory) AttributeList(attrName, attrRange,
596                                           scopeName, scopeLoc,
597                                           args, numArgs, syntax,
598                                           ellipsisLoc));
599   }
600 
create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)601   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
602                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
603                         IdentifierLoc *Param,
604                         const AvailabilityChange &introduced,
605                         const AvailabilityChange &deprecated,
606                         const AvailabilityChange &obsoleted,
607                         SourceLocation unavailable,
608                         const Expr *MessageExpr,
609                         AttributeList::Syntax syntax) {
610     void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
611     return add(new (memory) AttributeList(attrName, attrRange,
612                                           scopeName, scopeLoc,
613                                           Param, introduced, deprecated,
614                                           obsoleted, unavailable, MessageExpr,
615                                           syntax));
616   }
617 
create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)618   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
619                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
620                         IdentifierLoc *Param1,
621                         IdentifierLoc *Param2,
622                         IdentifierLoc *Param3,
623                         AttributeList::Syntax syntax) {
624     size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
625     void *memory = allocate(size);
626     return add(new (memory) AttributeList(attrName, attrRange,
627                                           scopeName, scopeLoc,
628                                           Param1, Param2, Param3,
629                                           syntax));
630   }
631 
createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)632   AttributeList *createTypeTagForDatatype(
633                     IdentifierInfo *attrName, SourceRange attrRange,
634                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
635                     IdentifierLoc *argumentKind, ParsedType matchingCType,
636                     bool layoutCompatible, bool mustBeNull,
637                     AttributeList::Syntax syntax) {
638     void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
639     return add(new (memory) AttributeList(attrName, attrRange,
640                                           scopeName, scopeLoc,
641                                           argumentKind, matchingCType,
642                                           layoutCompatible, mustBeNull,
643                                           syntax));
644   }
645 
createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)646   AttributeList *createTypeAttribute(
647                     IdentifierInfo *attrName, SourceRange attrRange,
648                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
649                     ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
650     void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
651     return add(new (memory) AttributeList(attrName, attrRange,
652                                           scopeName, scopeLoc,
653                                           typeArg, syntaxUsed));
654   }
655 
createPropertyAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)656   AttributeList *createPropertyAttribute(
657                     IdentifierInfo *attrName, SourceRange attrRange,
658                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
659                     IdentifierInfo *getterId, IdentifierInfo *setterId,
660                     AttributeList::Syntax syntaxUsed) {
661     void *memory = allocate(AttributeFactory::PropertyAllocSize);
662     return add(new (memory) AttributeList(attrName, attrRange,
663                                           scopeName, scopeLoc,
664                                           getterId, setterId,
665                                           syntaxUsed));
666   }
667 };
668 
669 /// ParsedAttributes - A collection of parsed attributes.  Currently
670 /// we don't differentiate between the various attribute syntaxes,
671 /// which is basically silly.
672 ///
673 /// Right now this is a very lightweight container, but the expectation
674 /// is that this will become significantly more serious.
675 class ParsedAttributes {
676 public:
ParsedAttributes(AttributeFactory & factory)677   ParsedAttributes(AttributeFactory &factory)
678     : pool(factory), list(nullptr) {
679   }
680 
681   ParsedAttributes(const ParsedAttributes &) = delete;
682 
getPool()683   AttributePool &getPool() const { return pool; }
684 
empty()685   bool empty() const { return list == nullptr; }
686 
add(AttributeList * newAttr)687   void add(AttributeList *newAttr) {
688     assert(newAttr);
689     assert(newAttr->getNext() == nullptr);
690     newAttr->setNext(list);
691     list = newAttr;
692   }
693 
addAll(AttributeList * newList)694   void addAll(AttributeList *newList) {
695     if (!newList) return;
696 
697     AttributeList *lastInNewList = newList;
698     while (AttributeList *next = lastInNewList->getNext())
699       lastInNewList = next;
700 
701     lastInNewList->setNext(list);
702     list = newList;
703   }
704 
set(AttributeList * newList)705   void set(AttributeList *newList) {
706     list = newList;
707   }
708 
takeAllFrom(ParsedAttributes & attrs)709   void takeAllFrom(ParsedAttributes &attrs) {
710     addAll(attrs.list);
711     attrs.list = nullptr;
712     pool.takeAllFrom(attrs.pool);
713   }
714 
clear()715   void clear() { list = nullptr; pool.clear(); }
getList()716   AttributeList *getList() const { return list; }
717 
718   /// Returns a reference to the attribute list.  Try not to introduce
719   /// dependencies on this method, it may not be long-lived.
getListRef()720   AttributeList *&getListRef() { return list; }
721 
722   /// Add attribute with expression arguments.
723   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
724                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
725                         ArgsUnion *args, unsigned numArgs,
726                         AttributeList::Syntax syntax,
727                         SourceLocation ellipsisLoc = SourceLocation()) {
728     AttributeList *attr =
729       pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
730                   syntax, ellipsisLoc);
731     add(attr);
732     return attr;
733   }
734 
735   /// Add availability attribute.
addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)736   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
737                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
738                         IdentifierLoc *Param,
739                         const AvailabilityChange &introduced,
740                         const AvailabilityChange &deprecated,
741                         const AvailabilityChange &obsoleted,
742                         SourceLocation unavailable,
743                         const Expr *MessageExpr,
744                         AttributeList::Syntax syntax) {
745     AttributeList *attr =
746       pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
747                   deprecated, obsoleted, unavailable, MessageExpr, syntax);
748     add(attr);
749     return attr;
750   }
751 
752   /// Add objc_bridge_related attribute.
addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)753   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
754                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
755                         IdentifierLoc *Param1,
756                         IdentifierLoc *Param2,
757                         IdentifierLoc *Param3,
758                         AttributeList::Syntax syntax) {
759     AttributeList *attr =
760       pool.create(attrName, attrRange, scopeName, scopeLoc,
761                   Param1, Param2, Param3, syntax);
762     add(attr);
763     return attr;
764   }
765 
766   /// Add type_tag_for_datatype attribute.
addNewTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)767   AttributeList *addNewTypeTagForDatatype(
768                         IdentifierInfo *attrName, SourceRange attrRange,
769                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
770                         IdentifierLoc *argumentKind, ParsedType matchingCType,
771                         bool layoutCompatible, bool mustBeNull,
772                         AttributeList::Syntax syntax) {
773     AttributeList *attr =
774       pool.createTypeTagForDatatype(attrName, attrRange,
775                                     scopeName, scopeLoc,
776                                     argumentKind, matchingCType,
777                                     layoutCompatible, mustBeNull, syntax);
778     add(attr);
779     return attr;
780   }
781 
782   /// Add an attribute with a single type argument.
783   AttributeList *
addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)784   addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
785                  IdentifierInfo *scopeName, SourceLocation scopeLoc,
786                  ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
787     AttributeList *attr =
788         pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
789                                  typeArg, syntaxUsed);
790     add(attr);
791     return attr;
792   }
793 
794   /// Add microsoft __delspec(property) attribute.
795   AttributeList *
addNewPropertyAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)796   addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
797                  IdentifierInfo *scopeName, SourceLocation scopeLoc,
798                  IdentifierInfo *getterId, IdentifierInfo *setterId,
799                  AttributeList::Syntax syntaxUsed) {
800     AttributeList *attr =
801         pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
802                                      getterId, setterId, syntaxUsed);
803     add(attr);
804     return attr;
805   }
806 
807 private:
808   mutable AttributePool pool;
809   AttributeList *list;
810 };
811 
812 /// These constants match the enumerated choices of
813 /// err_attribute_argument_n_type and err_attribute_argument_type.
814 enum AttributeArgumentNType {
815   AANT_ArgumentIntOrBool,
816   AANT_ArgumentIntegerConstant,
817   AANT_ArgumentString,
818   AANT_ArgumentIdentifier
819 };
820 
821 /// These constants match the enumerated choices of
822 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
823 enum AttributeDeclKind {
824   ExpectedFunction,
825   ExpectedUnion,
826   ExpectedVariableOrFunction,
827   ExpectedFunctionOrMethod,
828   ExpectedParameter,
829   ExpectedFunctionMethodOrBlock,
830   ExpectedFunctionMethodOrClass,
831   ExpectedFunctionMethodOrParameter,
832   ExpectedClass,
833   ExpectedEnum,
834   ExpectedVariable,
835   ExpectedMethod,
836   ExpectedVariableFunctionOrLabel,
837   ExpectedFieldOrGlobalVar,
838   ExpectedStruct,
839   ExpectedVariableOrTypedef,
840   ExpectedTLSVar,
841   ExpectedVariableOrField,
842   ExpectedVariableFieldOrTag,
843   ExpectedTypeOrNamespace,
844   ExpectedObjectiveCInterface,
845   ExpectedMethodOrProperty,
846   ExpectedStructOrUnion,
847   ExpectedStructOrUnionOrClass,
848   ExpectedType,
849   ExpectedObjCInstanceMethod,
850   ExpectedObjCInterfaceDeclInitMethod,
851   ExpectedFunctionVariableOrClass,
852   ExpectedObjectiveCProtocol,
853   ExpectedFunctionGlobalVarMethodOrProperty,
854   ExpectedStructOrUnionOrTypedef,
855   ExpectedStructOrTypedef,
856   ExpectedObjectiveCInterfaceOrProtocol,
857   ExpectedKernelFunction,
858   ExpectedFunctionWithProtoType
859 };
860 
861 }  // end namespace clang
862 
863 #endif
864