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/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.
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     /// #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 : 15;
98 
99   /// Corresponds to the Syntax enum.
100   unsigned SyntaxUsed : 3;
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.
getArgsBuffer()138   ArgsUnion *getArgsBuffer() {
139     return reinterpret_cast<ArgsUnion*>(this+1);
140   }
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 &) 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.
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 && SyntaxUsed == AS_Keyword;
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 { return SyntaxUsed == AS_Keyword; }
354 
isInvalid()355   bool isInvalid() const { return Invalid; }
356   void setInvalid(bool b = true) const { Invalid = b; }
357 
isUsedAsTypeAttr()358   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()359   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
360 
isPackExpansion()361   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
getEllipsisLoc()362   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
363 
getKind()364   Kind getKind() const { return Kind(AttrKind); }
365   static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
366                       Syntax SyntaxUsed);
367 
getNext()368   AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)369   void setNext(AttributeList *N) { NextInPosition = N; }
370 
371   /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()372   unsigned getNumArgs() const { return NumArgs; }
373 
374   /// getArg - Return the specified argument.
getArg(unsigned Arg)375   ArgsUnion getArg(unsigned Arg) const {
376     assert(Arg < NumArgs && "Arg access out of range!");
377     return getArgsBuffer()[Arg];
378   }
379 
isArgExpr(unsigned Arg)380   bool isArgExpr(unsigned Arg) const {
381     return Arg < NumArgs && getArg(Arg).is<Expr*>();
382   }
getArgAsExpr(unsigned Arg)383   Expr *getArgAsExpr(unsigned Arg) const {
384     return getArg(Arg).get<Expr*>();
385   }
386 
isArgIdent(unsigned Arg)387   bool isArgIdent(unsigned Arg) const {
388     return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
389   }
getArgAsIdent(unsigned Arg)390   IdentifierLoc *getArgAsIdent(unsigned Arg) const {
391     return getArg(Arg).get<IdentifierLoc*>();
392   }
393 
getAvailabilityIntroduced()394   const AvailabilityChange &getAvailabilityIntroduced() const {
395     assert(getKind() == AT_Availability && "Not an availability attribute");
396     return getAvailabilitySlot(IntroducedSlot);
397   }
398 
getAvailabilityDeprecated()399   const AvailabilityChange &getAvailabilityDeprecated() const {
400     assert(getKind() == AT_Availability && "Not an availability attribute");
401     return getAvailabilitySlot(DeprecatedSlot);
402   }
403 
getAvailabilityObsoleted()404   const AvailabilityChange &getAvailabilityObsoleted() const {
405     assert(getKind() == AT_Availability && "Not an availability attribute");
406     return getAvailabilitySlot(ObsoletedSlot);
407   }
408 
getUnavailableLoc()409   SourceLocation getUnavailableLoc() const {
410     assert(getKind() == AT_Availability && "Not an availability attribute");
411     return UnavailableLoc;
412   }
413 
getMessageExpr()414   const Expr * getMessageExpr() const {
415     assert(getKind() == AT_Availability && "Not an availability attribute");
416     return MessageExpr;
417   }
418 
getMatchingCType()419   const ParsedType &getMatchingCType() const {
420     assert(getKind() == AT_TypeTagForDatatype &&
421            "Not a type_tag_for_datatype attribute");
422     return *getTypeTagForDatatypeDataSlot().MatchingCType;
423   }
424 
getLayoutCompatible()425   bool getLayoutCompatible() const {
426     assert(getKind() == AT_TypeTagForDatatype &&
427            "Not a type_tag_for_datatype attribute");
428     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
429   }
430 
getMustBeNull()431   bool getMustBeNull() const {
432     assert(getKind() == AT_TypeTagForDatatype &&
433            "Not a type_tag_for_datatype attribute");
434     return getTypeTagForDatatypeDataSlot().MustBeNull;
435   }
436 
getTypeArg()437   const ParsedType &getTypeArg() const {
438     assert(HasParsedType && "Not a type attribute");
439     return getTypeBuffer();
440   }
441 
getPropertyData()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 hasVariadicArg() const;
459   bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
460   bool diagnoseLangOpts(class Sema &S) const;
461   bool existsInTarget(const llvm::Triple &T) const;
462   bool isKnownToGCC() const;
463 
464   /// \brief If the parsed attribute has a semantic equivalent, and it would
465   /// have a semantic Spelling enumeration (due to having semantically-distinct
466   /// spelling variations), return the value of that semantic spelling. If the
467   /// parsed attribute does not have a semantic equivalent, or would not have
468   /// a Spelling enumeration, the value UINT_MAX is returned.
469   unsigned getSemanticSpelling() const;
470 };
471 
472 /// A factory, from which one makes pools, from which one creates
473 /// individual attributes which are deallocated with the pool.
474 ///
475 /// Note that it's tolerably cheap to create and destroy one of
476 /// these as long as you don't actually allocate anything in it.
477 class AttributeFactory {
478 public:
479   enum {
480     /// The required allocation size of an availability attribute,
481     /// which we want to ensure is a multiple of sizeof(void*).
482     AvailabilityAllocSize =
483       sizeof(AttributeList)
484       + ((3 * sizeof(AvailabilityChange) + sizeof(void*) +
485          sizeof(ArgsUnion) - 1)
486          / sizeof(void*) * sizeof(void*)),
487     TypeTagForDatatypeAllocSize =
488       sizeof(AttributeList)
489       + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
490          sizeof(ArgsUnion) - 1)
491         / sizeof(void*) * sizeof(void*),
492     PropertyAllocSize =
493       sizeof(AttributeList)
494       + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
495         / sizeof(void*) * sizeof(void*)
496   };
497 
498 private:
499   enum {
500     /// The number of free lists we want to be sure to support
501     /// inline.  This is just enough that availability attributes
502     /// don't surpass it.  It's actually very unlikely we'll see an
503     /// attribute that needs more than that; on x86-64 you'd need 10
504     /// expression arguments, and on i386 you'd need 19.
505     InlineFreeListsCapacity =
506       1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
507   };
508 
509   llvm::BumpPtrAllocator Alloc;
510 
511   /// Free lists.  The index is determined by the following formula:
512   ///   (size - sizeof(AttributeList)) / sizeof(void*)
513   SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
514 
515   // The following are the private interface used by AttributePool.
516   friend class AttributePool;
517 
518   /// Allocate an attribute of the given size.
519   void *allocate(size_t size);
520 
521   /// Reclaim all the attributes in the given pool chain, which is
522   /// non-empty.  Note that the current implementation is safe
523   /// against reclaiming things which were not actually allocated
524   /// with the allocator, although of course it's important to make
525   /// sure that their allocator lives at least as long as this one.
526   void reclaimPool(AttributeList *head);
527 
528 public:
529   AttributeFactory();
530   ~AttributeFactory();
531 };
532 
533 class AttributePool {
534   AttributeFactory &Factory;
535   AttributeList *Head;
536 
allocate(size_t size)537   void *allocate(size_t size) {
538     return Factory.allocate(size);
539   }
540 
add(AttributeList * attr)541   AttributeList *add(AttributeList *attr) {
542     // We don't care about the order of the pool.
543     attr->NextInPool = Head;
544     Head = attr;
545     return attr;
546   }
547 
548   void takePool(AttributeList *pool);
549 
550 public:
551   /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)552   AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
553 
554   /// Move the given pool's allocations to this pool.
AttributePool(AttributePool & pool)555   AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
556     pool.Head = nullptr;
557   }
558 
getFactory()559   AttributeFactory &getFactory() const { return Factory; }
560 
clear()561   void clear() {
562     if (Head) {
563       Factory.reclaimPool(Head);
564       Head = nullptr;
565     }
566   }
567 
568   /// Take the given pool's allocations and add them to this pool.
takeAllFrom(AttributePool & pool)569   void takeAllFrom(AttributePool &pool) {
570     if (pool.Head) {
571       takePool(pool.Head);
572       pool.Head = nullptr;
573     }
574   }
575 
~AttributePool()576   ~AttributePool() {
577     if (Head) Factory.reclaimPool(Head);
578   }
579 
580   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
581                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
582                         ArgsUnion *args, unsigned numArgs,
583                         AttributeList::Syntax syntax,
584                         SourceLocation ellipsisLoc = SourceLocation()) {
585     void *memory = allocate(sizeof(AttributeList)
586                             + numArgs * sizeof(ArgsUnion));
587     return add(new (memory) AttributeList(attrName, attrRange,
588                                           scopeName, scopeLoc,
589                                           args, numArgs, syntax,
590                                           ellipsisLoc));
591   }
592 
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)593   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
594                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
595                         IdentifierLoc *Param,
596                         const AvailabilityChange &introduced,
597                         const AvailabilityChange &deprecated,
598                         const AvailabilityChange &obsoleted,
599                         SourceLocation unavailable,
600                         const Expr *MessageExpr,
601                         AttributeList::Syntax syntax) {
602     void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
603     return add(new (memory) AttributeList(attrName, attrRange,
604                                           scopeName, scopeLoc,
605                                           Param, introduced, deprecated,
606                                           obsoleted, unavailable, MessageExpr,
607                                           syntax));
608   }
609 
create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)610   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
611                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
612                         IdentifierLoc *Param1,
613                         IdentifierLoc *Param2,
614                         IdentifierLoc *Param3,
615                         AttributeList::Syntax syntax) {
616     size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
617     void *memory = allocate(size);
618     return add(new (memory) AttributeList(attrName, attrRange,
619                                           scopeName, scopeLoc,
620                                           Param1, Param2, Param3,
621                                           syntax));
622   }
623 
createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * argumentKind,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)624   AttributeList *createTypeTagForDatatype(
625                     IdentifierInfo *attrName, SourceRange attrRange,
626                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
627                     IdentifierLoc *argumentKind, ParsedType matchingCType,
628                     bool layoutCompatible, bool mustBeNull,
629                     AttributeList::Syntax syntax) {
630     void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
631     return add(new (memory) AttributeList(attrName, attrRange,
632                                           scopeName, scopeLoc,
633                                           argumentKind, matchingCType,
634                                           layoutCompatible, mustBeNull,
635                                           syntax));
636   }
637 
createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)638   AttributeList *createTypeAttribute(
639                     IdentifierInfo *attrName, SourceRange attrRange,
640                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
641                     ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
642     void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
643     return add(new (memory) AttributeList(attrName, attrRange,
644                                           scopeName, scopeLoc,
645                                           typeArg, syntaxUsed));
646   }
647 
createPropertyAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)648   AttributeList *createPropertyAttribute(
649                     IdentifierInfo *attrName, SourceRange attrRange,
650                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
651                     IdentifierInfo *getterId, IdentifierInfo *setterId,
652                     AttributeList::Syntax syntaxUsed) {
653     void *memory = allocate(AttributeFactory::PropertyAllocSize);
654     return add(new (memory) AttributeList(attrName, attrRange,
655                                           scopeName, scopeLoc,
656                                           getterId, setterId,
657                                           syntaxUsed));
658   }
659 };
660 
661 /// ParsedAttributes - A collection of parsed attributes.  Currently
662 /// we don't differentiate between the various attribute syntaxes,
663 /// which is basically silly.
664 ///
665 /// Right now this is a very lightweight container, but the expectation
666 /// is that this will become significantly more serious.
667 class ParsedAttributes {
668 public:
ParsedAttributes(AttributeFactory & factory)669   ParsedAttributes(AttributeFactory &factory)
670     : pool(factory), list(nullptr) {
671   }
672 
673   ParsedAttributes(const ParsedAttributes &) LLVM_DELETED_FUNCTION;
674 
getPool()675   AttributePool &getPool() const { return pool; }
676 
empty()677   bool empty() const { return list == nullptr; }
678 
add(AttributeList * newAttr)679   void add(AttributeList *newAttr) {
680     assert(newAttr);
681     assert(newAttr->getNext() == nullptr);
682     newAttr->setNext(list);
683     list = newAttr;
684   }
685 
addAll(AttributeList * newList)686   void addAll(AttributeList *newList) {
687     if (!newList) return;
688 
689     AttributeList *lastInNewList = newList;
690     while (AttributeList *next = lastInNewList->getNext())
691       lastInNewList = next;
692 
693     lastInNewList->setNext(list);
694     list = newList;
695   }
696 
set(AttributeList * newList)697   void set(AttributeList *newList) {
698     list = newList;
699   }
700 
takeAllFrom(ParsedAttributes & attrs)701   void takeAllFrom(ParsedAttributes &attrs) {
702     addAll(attrs.list);
703     attrs.list = nullptr;
704     pool.takeAllFrom(attrs.pool);
705   }
706 
clear()707   void clear() { list = nullptr; pool.clear(); }
getList()708   AttributeList *getList() const { return list; }
709 
710   /// Returns a reference to the attribute list.  Try not to introduce
711   /// dependencies on this method, it may not be long-lived.
getListRef()712   AttributeList *&getListRef() { return list; }
713 
714   /// Add attribute with expression arguments.
715   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
716                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
717                         ArgsUnion *args, unsigned numArgs,
718                         AttributeList::Syntax syntax,
719                         SourceLocation ellipsisLoc = SourceLocation()) {
720     AttributeList *attr =
721       pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
722                   syntax, ellipsisLoc);
723     add(attr);
724     return attr;
725   }
726 
727   /// 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)728   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
729                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
730                         IdentifierLoc *Param,
731                         const AvailabilityChange &introduced,
732                         const AvailabilityChange &deprecated,
733                         const AvailabilityChange &obsoleted,
734                         SourceLocation unavailable,
735                         const Expr *MessageExpr,
736                         AttributeList::Syntax syntax) {
737     AttributeList *attr =
738       pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
739                   deprecated, obsoleted, unavailable, MessageExpr, syntax);
740     add(attr);
741     return attr;
742   }
743 
744   /// Add objc_bridge_related attribute.
addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierLoc * Param1,IdentifierLoc * Param2,IdentifierLoc * Param3,AttributeList::Syntax syntax)745   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
746                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
747                         IdentifierLoc *Param1,
748                         IdentifierLoc *Param2,
749                         IdentifierLoc *Param3,
750                         AttributeList::Syntax syntax) {
751     AttributeList *attr =
752       pool.create(attrName, attrRange, scopeName, scopeLoc,
753                   Param1, Param2, Param3, syntax);
754     add(attr);
755     return attr;
756   }
757 
758   /// 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)759   AttributeList *addNewTypeTagForDatatype(
760                         IdentifierInfo *attrName, SourceRange attrRange,
761                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
762                         IdentifierLoc *argumentKind, ParsedType matchingCType,
763                         bool layoutCompatible, bool mustBeNull,
764                         AttributeList::Syntax syntax) {
765     AttributeList *attr =
766       pool.createTypeTagForDatatype(attrName, attrRange,
767                                     scopeName, scopeLoc,
768                                     argumentKind, matchingCType,
769                                     layoutCompatible, mustBeNull, syntax);
770     add(attr);
771     return attr;
772   }
773 
774   /// Add an attribute with a single type argument.
775   AttributeList *
addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)776   addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
777                  IdentifierInfo *scopeName, SourceLocation scopeLoc,
778                  ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
779     AttributeList *attr =
780         pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
781                                  typeArg, syntaxUsed);
782     add(attr);
783     return attr;
784   }
785 
786   /// Add microsoft __delspec(property) attribute.
787   AttributeList *
addNewPropertyAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * getterId,IdentifierInfo * setterId,AttributeList::Syntax syntaxUsed)788   addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
789                  IdentifierInfo *scopeName, SourceLocation scopeLoc,
790                  IdentifierInfo *getterId, IdentifierInfo *setterId,
791                  AttributeList::Syntax syntaxUsed) {
792     AttributeList *attr =
793         pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
794                                      getterId, setterId, syntaxUsed);
795     add(attr);
796     return attr;
797   }
798 
799 private:
800   mutable AttributePool pool;
801   AttributeList *list;
802 };
803 
804 /// These constants match the enumerated choices of
805 /// err_attribute_argument_n_type and err_attribute_argument_type.
806 enum AttributeArgumentNType {
807   AANT_ArgumentIntOrBool,
808   AANT_ArgumentIntegerConstant,
809   AANT_ArgumentString,
810   AANT_ArgumentIdentifier
811 };
812 
813 /// These constants match the enumerated choices of
814 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
815 enum AttributeDeclKind {
816   ExpectedFunction,
817   ExpectedUnion,
818   ExpectedVariableOrFunction,
819   ExpectedFunctionOrMethod,
820   ExpectedParameter,
821   ExpectedFunctionMethodOrBlock,
822   ExpectedFunctionMethodOrClass,
823   ExpectedFunctionMethodOrParameter,
824   ExpectedClass,
825   ExpectedVariable,
826   ExpectedMethod,
827   ExpectedVariableFunctionOrLabel,
828   ExpectedFieldOrGlobalVar,
829   ExpectedStruct,
830   ExpectedVariableOrTypedef,
831   ExpectedTLSVar,
832   ExpectedVariableOrField,
833   ExpectedVariableFieldOrTag,
834   ExpectedTypeOrNamespace,
835   ExpectedObjectiveCInterface,
836   ExpectedMethodOrProperty,
837   ExpectedStructOrUnion,
838   ExpectedStructOrUnionOrClass,
839   ExpectedType,
840   ExpectedObjCInstanceMethod,
841   ExpectedObjCInterfaceDeclInitMethod,
842   ExpectedFunctionVariableOrClass,
843   ExpectedObjectiveCProtocol,
844   ExpectedFunctionGlobalVarMethodOrProperty,
845   ExpectedStructOrTypedef,
846   ExpectedObjectiveCInterfaceOrProtocol,
847   ExpectedKernelFunction
848 };
849 
850 }  // end namespace clang
851 
852 #endif
853