• 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_ATTRLIST_H
16 #define LLVM_CLANG_SEMA_ATTRLIST_H
17 
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/VersionTuple.h"
20 #include "clang/Sema/Ownership.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Allocator.h"
23 #include <cassert>
24 
25 namespace clang {
26   class ASTContext;
27   class IdentifierInfo;
28   class Expr;
29 
30 /// \brief Represents information about a change in availability for
31 /// an entity, which is part of the encoding of the 'availability'
32 /// attribute.
33 struct AvailabilityChange {
34   /// \brief The location of the keyword indicating the kind of change.
35   SourceLocation KeywordLoc;
36 
37   /// \brief The version number at which the change occurred.
38   VersionTuple Version;
39 
40   /// \brief The source range covering the version number.
41   SourceRange VersionRange;
42 
43   /// \brief Determine whether this availability change is valid.
isValidAvailabilityChange44   bool isValid() const { return !Version.empty(); }
45 };
46 
47 /// AttributeList - Represents a syntactic attribute.
48 ///
49 /// For a GNU attribute, there are four forms of this construct:
50 ///
51 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
52 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
53 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
54 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
55 ///
56 class AttributeList { // TODO: This should really be called ParsedAttribute
57 public:
58   /// The style used to specify an attribute.
59   enum Syntax {
60     /// __attribute__((...))
61     AS_GNU,
62     /// [[...]]
63     AS_CXX11,
64     /// __declspec(...)
65     AS_Declspec,
66     /// __ptr16, alignas(...), etc.
67     AS_Keyword
68   };
69 private:
70   IdentifierInfo *AttrName;
71   IdentifierInfo *ScopeName;
72   IdentifierInfo *ParmName;
73   SourceRange AttrRange;
74   SourceLocation ScopeLoc;
75   SourceLocation ParmLoc;
76   SourceLocation EllipsisLoc;
77 
78   /// The number of expression arguments this attribute has.
79   /// The expressions themselves are stored after the object.
80   unsigned NumArgs : 16;
81 
82   /// Corresponds to the Syntax enum.
83   unsigned SyntaxUsed : 2;
84 
85   /// True if already diagnosed as invalid.
86   mutable unsigned Invalid : 1;
87 
88   /// True if this attribute was used as a type attribute.
89   mutable unsigned UsedAsTypeAttr : 1;
90 
91   /// True if this has the extra information associated with an
92   /// availability attribute.
93   unsigned IsAvailability : 1;
94 
95   /// True if this has extra information associated with a
96   /// type_tag_for_datatype attribute.
97   unsigned IsTypeTagForDatatype : 1;
98 
99   unsigned AttrKind : 8;
100 
101   /// \brief The location of the 'unavailable' keyword in an
102   /// availability attribute.
103   SourceLocation UnavailableLoc;
104 
105   const Expr *MessageExpr;
106 
107   /// The next attribute in the current position.
108   AttributeList *NextInPosition;
109 
110   /// The next attribute allocated in the current Pool.
111   AttributeList *NextInPool;
112 
getArgsBuffer()113   Expr **getArgsBuffer() {
114     return reinterpret_cast<Expr**>(this+1);
115   }
getArgsBuffer()116   Expr * const *getArgsBuffer() const {
117     return reinterpret_cast<Expr* const *>(this+1);
118   }
119 
120   enum AvailabilitySlot {
121     IntroducedSlot, DeprecatedSlot, ObsoletedSlot
122   };
123 
getAvailabilitySlot(AvailabilitySlot index)124   AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
125     return reinterpret_cast<AvailabilityChange*>(this+1)[index];
126   }
getAvailabilitySlot(AvailabilitySlot index)127   const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
128     return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
129   }
130 
131 public:
132   struct TypeTagForDatatypeData {
133     ParsedType *MatchingCType;
134     unsigned LayoutCompatible : 1;
135     unsigned MustBeNull : 1;
136   };
137 
138 private:
getTypeTagForDatatypeDataSlot()139   TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
140     return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
141   }
142 
getTypeTagForDatatypeDataSlot()143   const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
144     return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
145   }
146 
getTypeBuffer()147   ParsedType &getTypeBuffer() {
148     return *reinterpret_cast<ParsedType *>(this + 1);
149   }
150 
getTypeBuffer()151   const ParsedType &getTypeBuffer() const {
152     return *reinterpret_cast<const ParsedType *>(this + 1);
153   }
154 
155   AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
156   void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
157   void operator delete(void *) LLVM_DELETED_FUNCTION;
158   ~AttributeList() LLVM_DELETED_FUNCTION;
159 
160   size_t allocated_size() const;
161 
162   /// Constructor for attributes with expression arguments.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,Expr ** args,unsigned numArgs,Syntax syntaxUsed,SourceLocation ellipsisLoc)163   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
164                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
165                 IdentifierInfo *parmName, SourceLocation parmLoc,
166                 Expr **args, unsigned numArgs,
167                 Syntax syntaxUsed, SourceLocation ellipsisLoc)
168     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
169       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
170       EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed),
171       Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
172       IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
173     if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
174     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
175   }
176 
177   /// Constructor for availability attributes.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * messageExpr,Syntax syntaxUsed)178   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
179                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
180                 IdentifierInfo *parmName, SourceLocation parmLoc,
181                 const AvailabilityChange &introduced,
182                 const AvailabilityChange &deprecated,
183                 const AvailabilityChange &obsoleted,
184                 SourceLocation unavailable,
185                 const Expr *messageExpr,
186                 Syntax syntaxUsed)
187     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
188       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(),
189       NumArgs(0), SyntaxUsed(syntaxUsed),
190       Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
191       IsTypeTagForDatatype(false),
192       UnavailableLoc(unavailable), MessageExpr(messageExpr),
193       NextInPosition(0), NextInPool(0) {
194     new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
195     new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
196     new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
197     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
198   }
199 
200   /// Constructor for type_tag_for_datatype attribute.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,Syntax syntaxUsed)201   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
202                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
203                 IdentifierInfo *argumentKindName,
204                 SourceLocation argumentKindLoc,
205                 ParsedType matchingCType, bool layoutCompatible,
206                 bool mustBeNull, Syntax syntaxUsed)
207     : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName),
208       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
209       EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
210       Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
211       IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
212     TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
213     new (&ExtraData.MatchingCType) ParsedType(matchingCType);
214     ExtraData.LayoutCompatible = layoutCompatible;
215     ExtraData.MustBeNull = mustBeNull;
216     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
217   }
218 
219   /// Constructor for attributes with a single type argument.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,Syntax syntaxUsed)220   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
221                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
222                 IdentifierInfo *parmName, SourceLocation parmLoc,
223                 ParsedType typeArg, Syntax syntaxUsed)
224       : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
225         AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
226         EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
227         UsedAsTypeAttr(false), IsAvailability(false),
228         IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
229     new (&getTypeBuffer()) ParsedType(typeArg);
230     AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
231   }
232 
233   friend class AttributePool;
234   friend class AttributeFactory;
235 
236 public:
237   enum Kind {
238     #define PARSED_ATTR(NAME) AT_##NAME,
239     #include "clang/Sema/AttrParsedAttrList.inc"
240     #undef PARSED_ATTR
241     IgnoredAttribute,
242     UnknownAttribute
243   };
244 
getName()245   IdentifierInfo *getName() const { return AttrName; }
getLoc()246   SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()247   SourceRange getRange() const { return AttrRange; }
248 
hasScope()249   bool hasScope() const { return ScopeName; }
getScopeName()250   IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()251   SourceLocation getScopeLoc() const { return ScopeLoc; }
252 
getParameterName()253   IdentifierInfo *getParameterName() const { return ParmName; }
getParameterLoc()254   SourceLocation getParameterLoc() const { return ParmLoc; }
255 
isAlignasAttribute()256   bool isAlignasAttribute() const {
257     // FIXME: Use a better mechanism to determine this.
258     return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword;
259   }
260 
isDeclspecAttribute()261   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
isCXX11Attribute()262   bool isCXX11Attribute() const {
263     return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
264   }
isKeywordAttribute()265   bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; }
266 
isInvalid()267   bool isInvalid() const { return Invalid; }
268   void setInvalid(bool b = true) const { Invalid = b; }
269 
isUsedAsTypeAttr()270   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()271   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
272 
isPackExpansion()273   bool isPackExpansion() const { return EllipsisLoc.isValid(); }
getEllipsisLoc()274   SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
275 
getKind()276   Kind getKind() const { return Kind(AttrKind); }
277   static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
278                       Syntax SyntaxUsed);
279 
getNext()280   AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)281   void setNext(AttributeList *N) { NextInPosition = N; }
282 
283   /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()284   unsigned getNumArgs() const { return NumArgs; }
285 
286   /// hasParameterOrArguments - Return true if this attribute has a parameter,
287   /// or has a non empty argument expression list.
hasParameterOrArguments()288   bool hasParameterOrArguments() const { return ParmName || NumArgs; }
289 
290   /// getArg - Return the specified argument.
getArg(unsigned Arg)291   Expr *getArg(unsigned Arg) const {
292     assert(Arg < NumArgs && "Arg access out of range!");
293     return getArgsBuffer()[Arg];
294   }
295 
296   class arg_iterator {
297     Expr * const *X;
298     unsigned Idx;
299   public:
arg_iterator(Expr * const * x,unsigned idx)300     arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
301 
302     arg_iterator& operator++() {
303       ++Idx;
304       return *this;
305     }
306 
307     bool operator==(const arg_iterator& I) const {
308       assert (X == I.X &&
309               "compared arg_iterators are for different argument lists");
310       return Idx == I.Idx;
311     }
312 
313     bool operator!=(const arg_iterator& I) const {
314       return !operator==(I);
315     }
316 
317     Expr* operator*() const {
318       return X[Idx];
319     }
320 
getArgNum()321     unsigned getArgNum() const {
322       return Idx+1;
323     }
324   };
325 
arg_begin()326   arg_iterator arg_begin() const {
327     return arg_iterator(getArgsBuffer(), 0);
328   }
329 
arg_end()330   arg_iterator arg_end() const {
331     return arg_iterator(getArgsBuffer(), NumArgs);
332   }
333 
getAvailabilityIntroduced()334   const AvailabilityChange &getAvailabilityIntroduced() const {
335     assert(getKind() == AT_Availability && "Not an availability attribute");
336     return getAvailabilitySlot(IntroducedSlot);
337   }
338 
getAvailabilityDeprecated()339   const AvailabilityChange &getAvailabilityDeprecated() const {
340     assert(getKind() == AT_Availability && "Not an availability attribute");
341     return getAvailabilitySlot(DeprecatedSlot);
342   }
343 
getAvailabilityObsoleted()344   const AvailabilityChange &getAvailabilityObsoleted() const {
345     assert(getKind() == AT_Availability && "Not an availability attribute");
346     return getAvailabilitySlot(ObsoletedSlot);
347   }
348 
getUnavailableLoc()349   SourceLocation getUnavailableLoc() const {
350     assert(getKind() == AT_Availability && "Not an availability attribute");
351     return UnavailableLoc;
352   }
353 
getMessageExpr()354   const Expr * getMessageExpr() const {
355     assert(getKind() == AT_Availability && "Not an availability attribute");
356     return MessageExpr;
357   }
358 
getMatchingCType()359   const ParsedType &getMatchingCType() const {
360     assert(getKind() == AT_TypeTagForDatatype &&
361            "Not a type_tag_for_datatype attribute");
362     return *getTypeTagForDatatypeDataSlot().MatchingCType;
363   }
364 
getLayoutCompatible()365   bool getLayoutCompatible() const {
366     assert(getKind() == AT_TypeTagForDatatype &&
367            "Not a type_tag_for_datatype attribute");
368     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
369   }
370 
getMustBeNull()371   bool getMustBeNull() const {
372     assert(getKind() == AT_TypeTagForDatatype &&
373            "Not a type_tag_for_datatype attribute");
374     return getTypeTagForDatatypeDataSlot().MustBeNull;
375   }
376 
getTypeArg()377   const ParsedType &getTypeArg() const {
378     assert(getKind() == AT_VecTypeHint && "Not a type attribute");
379     return getTypeBuffer();
380   }
381 
382   /// \brief Get an index into the attribute spelling list
383   /// defined in Attr.td. This index is used by an attribute
384   /// to pretty print itself.
385   unsigned getAttributeSpellingListIndex() const;
386 };
387 
388 /// A factory, from which one makes pools, from which one creates
389 /// individual attributes which are deallocated with the pool.
390 ///
391 /// Note that it's tolerably cheap to create and destroy one of
392 /// these as long as you don't actually allocate anything in it.
393 class AttributeFactory {
394 public:
395   enum {
396     /// The required allocation size of an availability attribute,
397     /// which we want to ensure is a multiple of sizeof(void*).
398     AvailabilityAllocSize =
399       sizeof(AttributeList)
400       + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
401          / sizeof(void*) * sizeof(void*)),
402     TypeTagForDatatypeAllocSize =
403       sizeof(AttributeList)
404       + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
405         / sizeof(void*) * sizeof(void*)
406   };
407 
408 private:
409   enum {
410     /// The number of free lists we want to be sure to support
411     /// inline.  This is just enough that availability attributes
412     /// don't surpass it.  It's actually very unlikely we'll see an
413     /// attribute that needs more than that; on x86-64 you'd need 10
414     /// expression arguments, and on i386 you'd need 19.
415     InlineFreeListsCapacity =
416       1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
417   };
418 
419   llvm::BumpPtrAllocator Alloc;
420 
421   /// Free lists.  The index is determined by the following formula:
422   ///   (size - sizeof(AttributeList)) / sizeof(void*)
423   SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
424 
425   // The following are the private interface used by AttributePool.
426   friend class AttributePool;
427 
428   /// Allocate an attribute of the given size.
429   void *allocate(size_t size);
430 
431   /// Reclaim all the attributes in the given pool chain, which is
432   /// non-empty.  Note that the current implementation is safe
433   /// against reclaiming things which were not actually allocated
434   /// with the allocator, although of course it's important to make
435   /// sure that their allocator lives at least as long as this one.
436   void reclaimPool(AttributeList *head);
437 
438 public:
439   AttributeFactory();
440   ~AttributeFactory();
441 };
442 
443 class AttributePool {
444   AttributeFactory &Factory;
445   AttributeList *Head;
446 
allocate(size_t size)447   void *allocate(size_t size) {
448     return Factory.allocate(size);
449   }
450 
add(AttributeList * attr)451   AttributeList *add(AttributeList *attr) {
452     // We don't care about the order of the pool.
453     attr->NextInPool = Head;
454     Head = attr;
455     return attr;
456   }
457 
458   void takePool(AttributeList *pool);
459 
460 public:
461   /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)462   AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
463 
464   /// Move the given pool's allocations to this pool.
AttributePool(AttributePool & pool)465   AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
466     pool.Head = 0;
467   }
468 
getFactory()469   AttributeFactory &getFactory() const { return Factory; }
470 
clear()471   void clear() {
472     if (Head) {
473       Factory.reclaimPool(Head);
474       Head = 0;
475     }
476   }
477 
478   /// Take the given pool's allocations and add them to this pool.
takeAllFrom(AttributePool & pool)479   void takeAllFrom(AttributePool &pool) {
480     if (pool.Head) {
481       takePool(pool.Head);
482       pool.Head = 0;
483     }
484   }
485 
~AttributePool()486   ~AttributePool() {
487     if (Head) Factory.reclaimPool(Head);
488   }
489 
490   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
491                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
492                         IdentifierInfo *parmName, SourceLocation parmLoc,
493                         Expr **args, unsigned numArgs,
494                         AttributeList::Syntax syntax,
495                         SourceLocation ellipsisLoc = SourceLocation()) {
496     void *memory = allocate(sizeof(AttributeList)
497                             + numArgs * sizeof(Expr*));
498     return add(new (memory) AttributeList(attrName, attrRange,
499                                           scopeName, scopeLoc,
500                                           parmName, parmLoc,
501                                           args, numArgs, syntax,
502                                           ellipsisLoc));
503   }
504 
create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)505   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
506                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
507                         IdentifierInfo *parmName, SourceLocation parmLoc,
508                         const AvailabilityChange &introduced,
509                         const AvailabilityChange &deprecated,
510                         const AvailabilityChange &obsoleted,
511                         SourceLocation unavailable,
512                         const Expr *MessageExpr,
513                         AttributeList::Syntax syntax) {
514     void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
515     return add(new (memory) AttributeList(attrName, attrRange,
516                                           scopeName, scopeLoc,
517                                           parmName, parmLoc,
518                                           introduced, deprecated, obsoleted,
519                                           unavailable, MessageExpr, syntax));
520   }
521 
522   AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
523                                         SourceLocation TokLoc, int Arg);
524 
createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)525   AttributeList *createTypeTagForDatatype(
526                     IdentifierInfo *attrName, SourceRange attrRange,
527                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
528                     IdentifierInfo *argumentKindName,
529                     SourceLocation argumentKindLoc,
530                     ParsedType matchingCType, bool layoutCompatible,
531                     bool mustBeNull, AttributeList::Syntax syntax) {
532     void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
533     return add(new (memory) AttributeList(attrName, attrRange,
534                                           scopeName, scopeLoc,
535                                           argumentKindName, argumentKindLoc,
536                                           matchingCType, layoutCompatible,
537                                           mustBeNull, syntax));
538   }
539 
createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)540   AttributeList *createTypeAttribute(
541                     IdentifierInfo *attrName, SourceRange attrRange,
542                     IdentifierInfo *scopeName, SourceLocation scopeLoc,
543                     IdentifierInfo *parmName, SourceLocation parmLoc,
544                     ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
545     void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
546     return add(new (memory) AttributeList(attrName, attrRange,
547                                           scopeName, scopeLoc,
548                                           parmName, parmLoc,
549                                           typeArg, syntaxUsed));
550   }
551 };
552 
553 /// addAttributeLists - Add two AttributeLists together
554 /// The right-hand list is appended to the left-hand list, if any
555 /// A pointer to the joined list is returned.
556 /// Note: the lists are not left unmodified.
addAttributeLists(AttributeList * Left,AttributeList * Right)557 inline AttributeList *addAttributeLists(AttributeList *Left,
558                                         AttributeList *Right) {
559   if (!Left)
560     return Right;
561 
562   AttributeList *next = Left, *prev;
563   do {
564     prev = next;
565     next = next->getNext();
566   } while (next);
567   prev->setNext(Right);
568   return Left;
569 }
570 
571 /// CXX11AttributeList - A wrapper around a C++11 attribute list.
572 /// Stores, in addition to the list proper, whether or not an actual list was
573 /// (as opposed to an empty list, which may be ill-formed in some places) and
574 /// the source range of the list.
575 struct CXX11AttributeList {
576   AttributeList *AttrList;
577   SourceRange Range;
578   bool HasAttr;
CXX11AttributeListCXX11AttributeList579   CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
580     : AttrList(attrList), Range(range), HasAttr (hasAttr) {
581   }
CXX11AttributeListCXX11AttributeList582   CXX11AttributeList ()
583     : AttrList(0), Range(), HasAttr(false) {
584   }
585 };
586 
587 /// ParsedAttributes - A collection of parsed attributes.  Currently
588 /// we don't differentiate between the various attribute syntaxes,
589 /// which is basically silly.
590 ///
591 /// Right now this is a very lightweight container, but the expectation
592 /// is that this will become significantly more serious.
593 class ParsedAttributes {
594 public:
ParsedAttributes(AttributeFactory & factory)595   ParsedAttributes(AttributeFactory &factory)
596     : pool(factory), list(0) {
597   }
598 
ParsedAttributes(ParsedAttributes & attrs)599   ParsedAttributes(ParsedAttributes &attrs)
600     : pool(attrs.pool), list(attrs.list) {
601     attrs.list = 0;
602   }
603 
getPool()604   AttributePool &getPool() const { return pool; }
605 
empty()606   bool empty() const { return list == 0; }
607 
add(AttributeList * newAttr)608   void add(AttributeList *newAttr) {
609     assert(newAttr);
610     assert(newAttr->getNext() == 0);
611     newAttr->setNext(list);
612     list = newAttr;
613   }
614 
addAll(AttributeList * newList)615   void addAll(AttributeList *newList) {
616     if (!newList) return;
617 
618     AttributeList *lastInNewList = newList;
619     while (AttributeList *next = lastInNewList->getNext())
620       lastInNewList = next;
621 
622     lastInNewList->setNext(list);
623     list = newList;
624   }
625 
set(AttributeList * newList)626   void set(AttributeList *newList) {
627     list = newList;
628   }
629 
takeAllFrom(ParsedAttributes & attrs)630   void takeAllFrom(ParsedAttributes &attrs) {
631     addAll(attrs.list);
632     attrs.list = 0;
633     pool.takeAllFrom(attrs.pool);
634   }
635 
clear()636   void clear() { list = 0; pool.clear(); }
getList()637   AttributeList *getList() const { return list; }
638 
639   /// Returns a reference to the attribute list.  Try not to introduce
640   /// dependencies on this method, it may not be long-lived.
getListRef()641   AttributeList *&getListRef() { return list; }
642 
643   /// Add attribute with expression arguments.
644   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
645                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
646                         IdentifierInfo *parmName, SourceLocation parmLoc,
647                         Expr **args, unsigned numArgs,
648                         AttributeList::Syntax syntax,
649                         SourceLocation ellipsisLoc = SourceLocation()) {
650     AttributeList *attr =
651       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
652                   args, numArgs, syntax, ellipsisLoc);
653     add(attr);
654     return attr;
655   }
656 
657   /// Add availability attribute.
addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * MessageExpr,AttributeList::Syntax syntax)658   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
659                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
660                         IdentifierInfo *parmName, SourceLocation parmLoc,
661                         const AvailabilityChange &introduced,
662                         const AvailabilityChange &deprecated,
663                         const AvailabilityChange &obsoleted,
664                         SourceLocation unavailable,
665                         const Expr *MessageExpr,
666                         AttributeList::Syntax syntax) {
667     AttributeList *attr =
668       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
669                   introduced, deprecated, obsoleted, unavailable,
670                   MessageExpr, syntax);
671     add(attr);
672     return attr;
673   }
674 
675   /// Add type_tag_for_datatype attribute.
addNewTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)676   AttributeList *addNewTypeTagForDatatype(
677                         IdentifierInfo *attrName, SourceRange attrRange,
678                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
679                         IdentifierInfo *argumentKindName,
680                         SourceLocation argumentKindLoc,
681                         ParsedType matchingCType, bool layoutCompatible,
682                         bool mustBeNull, AttributeList::Syntax syntax) {
683     AttributeList *attr =
684       pool.createTypeTagForDatatype(attrName, attrRange,
685                                     scopeName, scopeLoc,
686                                     argumentKindName, argumentKindLoc,
687                                     matchingCType, layoutCompatible,
688                                     mustBeNull, syntax);
689     add(attr);
690     return attr;
691   }
692 
693   /// Add an attribute with a single type argument.
694   AttributeList *
addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)695   addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
696                  IdentifierInfo *scopeName, SourceLocation scopeLoc,
697                  IdentifierInfo *parmName, SourceLocation parmLoc,
698                  ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
699     AttributeList *attr =
700         pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
701                                  parmName, parmLoc, typeArg, syntaxUsed);
702     add(attr);
703     return attr;
704   }
705 
addNewInteger(ASTContext & C,IdentifierInfo * name,SourceLocation loc,int arg)706   AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
707                                SourceLocation loc, int arg) {
708     AttributeList *attr =
709       pool.createIntegerAttribute(C, name, loc, arg);
710     add(attr);
711     return attr;
712   }
713 
714 
715 private:
716   mutable AttributePool pool;
717   AttributeList *list;
718 };
719 
720 }  // end namespace clang
721 
722 #endif
723