AttributeList.h revision 76da55d3a49e1805f51b1ced7c5da5bcd7f759d8
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 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///
56class AttributeList { // TODO: This should really be called ParsedAttribute
57public:
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  };
69private:
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
135public:
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
147private:
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
274public:
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.
441class AttributeFactory {
442public:
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
460private:
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
490public:
491  AttributeFactory();
492  ~AttributeFactory();
493};
494
495class 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
512public:
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.
623inline 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.
641struct 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.
659class ParsedAttributes {
660public:
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
796private:
797  mutable AttributePool pool;
798  AttributeList *list;
799};
800
801}  // end namespace clang
802
803#endif
804