AttributeList.h revision 51d8c52ad36129760eaa586f85176037e2cd0d0e
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
25namespace 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.
33struct 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///
55class AttributeList { // TODO: This should really be called ParsedAttribute
56public:
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  };
66private:
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
127public:
128  struct TypeTagForDatatypeData {
129    ParsedType *MatchingCType;
130    unsigned LayoutCompatible : 1;
131    unsigned MustBeNull : 1;
132  };
133
134private:
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
210public:
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 isCXX11Attribute() 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  /// \brief Get an index into the attribute spelling list
345  /// defined in Attr.td. This index is used by an attribute
346  /// to pretty print itself.
347  unsigned getAttributeSpellingListIndex() const;
348};
349
350/// A factory, from which one makes pools, from which one creates
351/// individual attributes which are deallocated with the pool.
352///
353/// Note that it's tolerably cheap to create and destroy one of
354/// these as long as you don't actually allocate anything in it.
355class AttributeFactory {
356public:
357  enum {
358    /// The required allocation size of an availability attribute,
359    /// which we want to ensure is a multiple of sizeof(void*).
360    AvailabilityAllocSize =
361      sizeof(AttributeList)
362      + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
363         / sizeof(void*) * sizeof(void*)),
364    TypeTagForDatatypeAllocSize =
365      sizeof(AttributeList)
366      + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
367        / sizeof(void*) * sizeof(void*)
368  };
369
370private:
371  enum {
372    /// The number of free lists we want to be sure to support
373    /// inline.  This is just enough that availability attributes
374    /// don't surpass it.  It's actually very unlikely we'll see an
375    /// attribute that needs more than that; on x86-64 you'd need 10
376    /// expression arguments, and on i386 you'd need 19.
377    InlineFreeListsCapacity =
378      1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
379  };
380
381  llvm::BumpPtrAllocator Alloc;
382
383  /// Free lists.  The index is determined by the following formula:
384  ///   (size - sizeof(AttributeList)) / sizeof(void*)
385  SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
386
387  // The following are the private interface used by AttributePool.
388  friend class AttributePool;
389
390  /// Allocate an attribute of the given size.
391  void *allocate(size_t size);
392
393  /// Reclaim all the attributes in the given pool chain, which is
394  /// non-empty.  Note that the current implementation is safe
395  /// against reclaiming things which were not actually allocated
396  /// with the allocator, although of course it's important to make
397  /// sure that their allocator lives at least as long as this one.
398  void reclaimPool(AttributeList *head);
399
400public:
401  AttributeFactory();
402  ~AttributeFactory();
403};
404
405class AttributePool {
406  AttributeFactory &Factory;
407  AttributeList *Head;
408
409  void *allocate(size_t size) {
410    return Factory.allocate(size);
411  }
412
413  AttributeList *add(AttributeList *attr) {
414    // We don't care about the order of the pool.
415    attr->NextInPool = Head;
416    Head = attr;
417    return attr;
418  }
419
420  void takePool(AttributeList *pool);
421
422public:
423  /// Create a new pool for a factory.
424  AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
425
426  /// Move the given pool's allocations to this pool.
427  AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
428    pool.Head = 0;
429  }
430
431  AttributeFactory &getFactory() const { return Factory; }
432
433  void clear() {
434    if (Head) {
435      Factory.reclaimPool(Head);
436      Head = 0;
437    }
438  }
439
440  /// Take the given pool's allocations and add them to this pool.
441  void takeAllFrom(AttributePool &pool) {
442    if (pool.Head) {
443      takePool(pool.Head);
444      pool.Head = 0;
445    }
446  }
447
448  ~AttributePool() {
449    if (Head) Factory.reclaimPool(Head);
450  }
451
452  AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
453                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
454                        IdentifierInfo *parmName, SourceLocation parmLoc,
455                        Expr **args, unsigned numArgs,
456                        AttributeList::Syntax syntax) {
457    void *memory = allocate(sizeof(AttributeList)
458                            + numArgs * sizeof(Expr*));
459    return add(new (memory) AttributeList(attrName, attrRange,
460                                          scopeName, scopeLoc,
461                                          parmName, parmLoc,
462                                          args, numArgs, syntax));
463  }
464
465  AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
466                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
467                        IdentifierInfo *parmName, SourceLocation parmLoc,
468                        const AvailabilityChange &introduced,
469                        const AvailabilityChange &deprecated,
470                        const AvailabilityChange &obsoleted,
471                        SourceLocation unavailable,
472                        const Expr *MessageExpr,
473                        AttributeList::Syntax syntax) {
474    void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
475    return add(new (memory) AttributeList(attrName, attrRange,
476                                          scopeName, scopeLoc,
477                                          parmName, parmLoc,
478                                          introduced, deprecated, obsoleted,
479                                          unavailable, MessageExpr, syntax));
480  }
481
482  AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
483                                        SourceLocation TokLoc, int Arg);
484
485  AttributeList *createTypeTagForDatatype(
486                    IdentifierInfo *attrName, SourceRange attrRange,
487                    IdentifierInfo *scopeName, SourceLocation scopeLoc,
488                    IdentifierInfo *argumentKindName,
489                    SourceLocation argumentKindLoc,
490                    ParsedType matchingCType, bool layoutCompatible,
491                    bool mustBeNull, AttributeList::Syntax syntax) {
492    void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
493    return add(new (memory) AttributeList(attrName, attrRange,
494                                          scopeName, scopeLoc,
495                                          argumentKindName, argumentKindLoc,
496                                          matchingCType, layoutCompatible,
497                                          mustBeNull, syntax));
498  }
499};
500
501/// addAttributeLists - Add two AttributeLists together
502/// The right-hand list is appended to the left-hand list, if any
503/// A pointer to the joined list is returned.
504/// Note: the lists are not left unmodified.
505inline AttributeList *addAttributeLists(AttributeList *Left,
506                                        AttributeList *Right) {
507  if (!Left)
508    return Right;
509
510  AttributeList *next = Left, *prev;
511  do {
512    prev = next;
513    next = next->getNext();
514  } while (next);
515  prev->setNext(Right);
516  return Left;
517}
518
519/// CXX11AttributeList - A wrapper around a C++11 attribute list.
520/// Stores, in addition to the list proper, whether or not an actual list was
521/// (as opposed to an empty list, which may be ill-formed in some places) and
522/// the source range of the list.
523struct CXX11AttributeList {
524  AttributeList *AttrList;
525  SourceRange Range;
526  bool HasAttr;
527  CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
528    : AttrList(attrList), Range(range), HasAttr (hasAttr) {
529  }
530  CXX11AttributeList ()
531    : AttrList(0), Range(), HasAttr(false) {
532  }
533};
534
535/// ParsedAttributes - A collection of parsed attributes.  Currently
536/// we don't differentiate between the various attribute syntaxes,
537/// which is basically silly.
538///
539/// Right now this is a very lightweight container, but the expectation
540/// is that this will become significantly more serious.
541class ParsedAttributes {
542public:
543  ParsedAttributes(AttributeFactory &factory)
544    : pool(factory), list(0) {
545  }
546
547  ParsedAttributes(ParsedAttributes &attrs)
548    : pool(attrs.pool), list(attrs.list) {
549    attrs.list = 0;
550  }
551
552  AttributePool &getPool() const { return pool; }
553
554  bool empty() const { return list == 0; }
555
556  void add(AttributeList *newAttr) {
557    assert(newAttr);
558    assert(newAttr->getNext() == 0);
559    newAttr->setNext(list);
560    list = newAttr;
561  }
562
563  void addAll(AttributeList *newList) {
564    if (!newList) return;
565
566    AttributeList *lastInNewList = newList;
567    while (AttributeList *next = lastInNewList->getNext())
568      lastInNewList = next;
569
570    lastInNewList->setNext(list);
571    list = newList;
572  }
573
574  void set(AttributeList *newList) {
575    list = newList;
576  }
577
578  void takeAllFrom(ParsedAttributes &attrs) {
579    addAll(attrs.list);
580    attrs.list = 0;
581    pool.takeAllFrom(attrs.pool);
582  }
583
584  void clear() { list = 0; pool.clear(); }
585  AttributeList *getList() const { return list; }
586
587  /// Returns a reference to the attribute list.  Try not to introduce
588  /// dependencies on this method, it may not be long-lived.
589  AttributeList *&getListRef() { return list; }
590
591  /// Add attribute with expression arguments.
592  AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
593                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
594                        IdentifierInfo *parmName, SourceLocation parmLoc,
595                        Expr **args, unsigned numArgs,
596                        AttributeList::Syntax syntax) {
597    AttributeList *attr =
598      pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
599                  args, numArgs, syntax);
600    add(attr);
601    return attr;
602  }
603
604  /// Add availability attribute.
605  AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
606                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
607                        IdentifierInfo *parmName, SourceLocation parmLoc,
608                        const AvailabilityChange &introduced,
609                        const AvailabilityChange &deprecated,
610                        const AvailabilityChange &obsoleted,
611                        SourceLocation unavailable,
612                        const Expr *MessageExpr,
613                        AttributeList::Syntax syntax) {
614    AttributeList *attr =
615      pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
616                  introduced, deprecated, obsoleted, unavailable,
617                  MessageExpr, syntax);
618    add(attr);
619    return attr;
620  }
621
622  /// Add type_tag_for_datatype attribute.
623  AttributeList *addNewTypeTagForDatatype(
624                        IdentifierInfo *attrName, SourceRange attrRange,
625                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
626                        IdentifierInfo *argumentKindName,
627                        SourceLocation argumentKindLoc,
628                        ParsedType matchingCType, bool layoutCompatible,
629                        bool mustBeNull, AttributeList::Syntax syntax) {
630    AttributeList *attr =
631      pool.createTypeTagForDatatype(attrName, attrRange,
632                                    scopeName, scopeLoc,
633                                    argumentKindName, argumentKindLoc,
634                                    matchingCType, layoutCompatible,
635                                    mustBeNull, syntax);
636    add(attr);
637    return attr;
638  }
639
640  AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
641                               SourceLocation loc, int arg) {
642    AttributeList *attr =
643      pool.createIntegerAttribute(C, name, loc, arg);
644    add(attr);
645    return attr;
646  }
647
648
649private:
650  mutable AttributePool pool;
651  AttributeList *list;
652};
653
654}  // end namespace clang
655
656#endif
657