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