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