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