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