]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
MFC r244628:
[FreeBSD/stable/9.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 "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.
44   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
109   Expr **getArgsBuffer() {
110     return reinterpret_cast<Expr**>(this+1);
111   }
112   Expr * const *getArgsBuffer() const {
113     return reinterpret_cast<Expr* const *>(this+1);
114   }
115
116   enum AvailabilitySlot {
117     IntroducedSlot, DeprecatedSlot, ObsoletedSlot
118   };
119
120   AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
121     return reinterpret_cast<AvailabilityChange*>(this+1)[index];
122   }
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:
135   TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
136     return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
137   }
138
139   const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
140     return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
141   }
142
143   AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
144   void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
145   void operator delete(void *) LLVM_DELETED_FUNCTION;
146   ~AttributeList() LLVM_DELETED_FUNCTION;
147
148   size_t allocated_size() const;
149
150   /// Constructor for attributes with expression arguments.
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.
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.
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
219   IdentifierInfo *getName() const { return AttrName; }
220   SourceLocation getLoc() const { return AttrRange.getBegin(); }
221   SourceRange getRange() const { return AttrRange; }
222   
223   bool hasScope() const { return ScopeName; }
224   IdentifierInfo *getScopeName() const { return ScopeName; }
225   SourceLocation getScopeLoc() const { return ScopeLoc; }
226   
227   IdentifierInfo *getParameterName() const { return ParmName; }
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).
232   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec ||
233                                             SyntaxUsed == AS_MSTypespec; }
234   bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; }
235   bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; }
236
237   bool isInvalid() const { return Invalid; }
238   void setInvalid(bool b = true) const { Invalid = b; }
239
240   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
241   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
242
243   Kind getKind() const { return Kind(AttrKind); }
244   static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
245                       Syntax SyntaxUsed);
246
247   AttributeList *getNext() const { return NextInPosition; }
248   void setNext(AttributeList *N) { NextInPosition = N; }
249
250   /// getNumArgs - Return the number of actual arguments to this attribute.
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.
255   bool hasParameterOrArguments() const { return ParmName || NumArgs; }
256
257   /// getArg - Return the specified argument.
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:
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
288     unsigned getArgNum() const {
289       return Idx+1;
290     }
291   };
292
293   arg_iterator arg_begin() const {
294     return arg_iterator(getArgsBuffer(), 0);
295   }
296
297   arg_iterator arg_end() const {
298     return arg_iterator(getArgsBuffer(), NumArgs);
299   }
300
301   const AvailabilityChange &getAvailabilityIntroduced() const {
302     assert(getKind() == AT_Availability && "Not an availability attribute");
303     return getAvailabilitySlot(IntroducedSlot);
304   }
305
306   const AvailabilityChange &getAvailabilityDeprecated() const {
307     assert(getKind() == AT_Availability && "Not an availability attribute");
308     return getAvailabilitySlot(DeprecatedSlot);
309   }
310
311   const AvailabilityChange &getAvailabilityObsoleted() const {
312     assert(getKind() == AT_Availability && "Not an availability attribute");
313     return getAvailabilitySlot(ObsoletedSlot);
314   }
315
316   SourceLocation getUnavailableLoc() const {
317     assert(getKind() == AT_Availability && "Not an availability attribute");
318     return UnavailableLoc;
319   }
320   
321   const Expr * getMessageExpr() const {
322     assert(getKind() == AT_Availability && "Not an availability attribute");
323     return MessageExpr;
324   }
325
326   const ParsedType &getMatchingCType() const {
327     assert(getKind() == AT_TypeTagForDatatype &&
328            "Not a type_tag_for_datatype attribute");
329     return *getTypeTagForDatatypeDataSlot().MatchingCType;
330   }
331
332   bool getLayoutCompatible() const {
333     assert(getKind() == AT_TypeTagForDatatype &&
334            "Not a type_tag_for_datatype attribute");
335     return getTypeTagForDatatypeDataSlot().LayoutCompatible;
336   }
337
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
404   void *allocate(size_t size) {
405     return Factory.allocate(size);
406   }
407
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.
419   AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
420
421   /// Move the given pool's allocations to this pool.
422   AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
423     pool.Head = 0;
424   }
425
426   AttributeFactory &getFactory() const { return Factory; }
427
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.
436   void takeAllFrom(AttributePool &pool) {
437     if (pool.Head) {
438       takePool(pool.Head);
439       pool.Head = 0;
440     }
441   }
442
443   ~AttributePool() {
444     if (Head) Factory.reclaimPool(Head);
445   }
446
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
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
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.
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;
522   CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
523     : AttrList(attrList), Range(range), HasAttr (hasAttr) {
524   }
525   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:
538   ParsedAttributes(AttributeFactory &factory)
539     : pool(factory), list(0) {
540   }
541
542   ParsedAttributes(ParsedAttributes &attrs)
543     : pool(attrs.pool), list(attrs.list) {
544     attrs.list = 0;
545   }
546
547   AttributePool &getPool() const { return pool; }
548
549   bool empty() const { return list == 0; }
550
551   void add(AttributeList *newAttr) {
552     assert(newAttr);
553     assert(newAttr->getNext() == 0);
554     newAttr->setNext(list);
555     list = newAttr;
556   }
557
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
569   void set(AttributeList *newList) {
570     list = newList;
571   }
572
573   void takeAllFrom(ParsedAttributes &attrs) {
574     addAll(attrs.list);
575     attrs.list = 0;
576     pool.takeAllFrom(attrs.pool);
577   }
578
579   void clear() { list = 0; pool.clear(); }
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.
584   AttributeList *&getListRef() { return list; }
585
586   /// Add attribute with expression arguments.
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.
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.
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
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