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