AttributeList.h revision 0a0d2b179085a52c10402feebeb6db8b4d96a140
1//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the AttributeList class, which is used to collect
11// parsed attributes.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SEMA_ATTRLIST_H
16#define LLVM_CLANG_SEMA_ATTRLIST_H
17
18#include "llvm/Support/Allocator.h"
19#include "clang/Sema/Ownership.h"
20#include "clang/Basic/SourceLocation.h"
21#include "clang/Basic/VersionTuple.h"
22#include "clang/AST/Expr.h"
23#include <cassert>
24
25namespace clang {
26  class IdentifierInfo;
27  class Expr;
28
29/// \brief Represents information about a change in availability for
30/// an entity, which is part of the encoding of the 'availability'
31/// attribute.
32struct AvailabilityChange {
33  /// \brief The location of the keyword indicating the kind of change.
34  SourceLocation KeywordLoc;
35
36  /// \brief The version number at which the change occurred.
37  VersionTuple Version;
38
39  /// \brief The source range covering the version number.
40  SourceRange VersionRange;
41
42  /// \brief Determine whether this availability change is valid.
43  bool isValid() const { return !Version.empty(); }
44};
45
46/// AttributeList - Represents GCC's __attribute__ declaration. There are
47/// 4 forms of this construct...they are:
48///
49/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
50/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
51/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
52/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
53///
54class AttributeList {
55public:
56  class Factory;
57private:
58  IdentifierInfo *AttrName;
59  SourceLocation AttrLoc;
60  IdentifierInfo *ScopeName;
61  SourceLocation ScopeLoc;
62  IdentifierInfo *ParmName;
63  SourceLocation ParmLoc;
64  Expr **Args;
65  unsigned NumArgs;
66  AttributeList *Next;
67  bool DeclspecAttribute, CXX0XAttribute;
68
69  // For the 'availability' attribute.
70  AvailabilityChange AvailabilityIntroduced;
71  AvailabilityChange AvailabilityDeprecated;
72  AvailabilityChange AvailabilityObsoleted;
73
74  /// True if already diagnosed as invalid.
75  mutable bool Invalid;
76
77  AttributeList(const AttributeList &); // DO NOT IMPLEMENT
78  void operator=(const AttributeList &); // DO NOT IMPLEMENT
79  void operator delete(void *); // DO NOT IMPLEMENT
80  ~AttributeList(); // DO NOT IMPLEMENT
81  AttributeList(llvm::BumpPtrAllocator &Alloc,
82                IdentifierInfo *AttrName, SourceLocation AttrLoc,
83                IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
84                IdentifierInfo *ParmName, SourceLocation ParmLoc,
85                Expr **args, unsigned numargs,
86                bool declspec, bool cxx0x);
87
88  AttributeList(llvm::BumpPtrAllocator &Alloc,
89                IdentifierInfo *AttrName, SourceLocation AttrLoc,
90                IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
91                IdentifierInfo *ParmName, SourceLocation ParmLoc,
92                const AvailabilityChange &Introduced,
93                const AvailabilityChange &Deprecated,
94                const AvailabilityChange &Obsoleted,
95                bool declspec, bool cxx0x);
96public:
97  class Factory {
98    llvm::BumpPtrAllocator Alloc;
99  public:
100    Factory() {}
101    ~Factory() {}
102    AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
103      IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
104      IdentifierInfo *ParmName, SourceLocation ParmLoc,
105      Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) {
106        AttributeList *Mem = Alloc.Allocate<AttributeList>();
107        new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
108                                ParmName, ParmLoc, args, numargs,
109                                declspec, cxx0x);
110        return Mem;
111      }
112
113    AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc,
114      IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
115      IdentifierInfo *ParmName, SourceLocation ParmLoc,
116      const AvailabilityChange &Introduced,
117      const AvailabilityChange &Deprecated,
118      const AvailabilityChange &Obsoleted,
119      bool declspec = false, bool cxx0x = false) {
120        AttributeList *Mem = Alloc.Allocate<AttributeList>();
121        new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc,
122                                ParmName, ParmLoc, Introduced, Deprecated,
123                                Obsoleted, declspec, cxx0x);
124        return Mem;
125      }
126
127    AttributeList* CreateIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
128                                          SourceLocation TokLoc, int Arg) {
129      Expr* IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t)Arg),
130                                          C.IntTy, TokLoc);
131      return Create( Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0);
132    }
133  };
134
135  enum Kind {             // Please keep this list alphabetized.
136    AT_IBAction,          // Clang-specific.
137    AT_IBOutlet,          // Clang-specific.
138    AT_IBOutletCollection, // Clang-specific.
139    AT_address_space,
140    AT_alias,
141    AT_aligned,
142    AT_always_inline,
143    AT_analyzer_noreturn,
144    AT_annotate,
145    AT_availability,      // Clang-specific
146    AT_base_check,
147    AT_blocks,
148    AT_carries_dependency,
149    AT_cdecl,
150    AT_cleanup,
151    AT_common,
152    AT_const,
153    AT_constant,
154    AT_constructor,
155    AT_deprecated,
156    AT_destructor,
157    AT_device,
158    AT_dllexport,
159    AT_dllimport,
160    AT_ext_vector_type,
161    AT_fastcall,
162    AT_format,
163    AT_format_arg,
164    AT_global,
165    AT_gnu_inline,
166    AT_host,
167    AT_launch_bounds,
168    AT_malloc,
169    AT_may_alias,
170    AT_mode,
171    AT_neon_polyvector_type,    // Clang-specific.
172    AT_neon_vector_type,        // Clang-specific.
173    AT_naked,
174    AT_nodebug,
175    AT_noinline,
176    AT_no_instrument_function,
177    AT_nocommon,
178    AT_nonnull,
179    AT_noreturn,
180    AT_nothrow,
181    AT_nsobject,
182    AT_objc_exception,
183    AT_objc_method_family,
184    AT_cf_returns_not_retained, // Clang-specific.
185    AT_cf_returns_retained,     // Clang-specific.
186    AT_ns_returns_not_retained, // Clang-specific.
187    AT_ns_returns_retained,     // Clang-specific.
188    AT_ns_returns_autoreleased, // Clang-specific.
189    AT_cf_consumed,             // Clang-specific.
190    AT_ns_consumed,             // Clang-specific.
191    AT_ns_consumes_self,        // Clang-specific.
192    AT_objc_gc,
193    AT_opencl_image_access,     // OpenCL-specific.
194    AT_opencl_kernel_function,  // OpenCL-specific.
195    AT_overloadable,       // Clang-specific.
196    AT_ownership_holds,    // Clang-specific.
197    AT_ownership_returns,  // Clang-specific.
198    AT_ownership_takes,    // Clang-specific.
199    AT_packed,
200    AT_pascal,
201    AT_pure,
202    AT_regparm,
203    AT_section,
204    AT_sentinel,
205    AT_shared,
206    AT_stdcall,
207    AT_thiscall,
208    AT_transparent_union,
209    AT_unavailable,
210    AT_unused,
211    AT_used,
212    AT_uuid,
213    AT_vecreturn,     // PS3 PPU-specific.
214    AT_vector_size,
215    AT_visibility,
216    AT_warn_unused_result,
217    AT_weak,
218    AT_weakref,
219    AT_weak_import,
220    AT_reqd_wg_size,
221    AT_init_priority,
222    IgnoredAttribute,
223    UnknownAttribute
224  };
225
226  IdentifierInfo *getName() const { return AttrName; }
227  SourceLocation getLoc() const { return AttrLoc; }
228
229  bool hasScope() const { return ScopeName; }
230  IdentifierInfo *getScopeName() const { return ScopeName; }
231  SourceLocation getScopeLoc() const { return ScopeLoc; }
232
233  IdentifierInfo *getParameterName() const { return ParmName; }
234  SourceLocation getParameterLoc() const { return ParmLoc; }
235
236  bool isDeclspecAttribute() const { return DeclspecAttribute; }
237  bool isCXX0XAttribute() const { return CXX0XAttribute; }
238
239  bool isInvalid() const { return Invalid; }
240  void setInvalid(bool b = true) const { Invalid = b; }
241
242  Kind getKind() const { return getKind(getName()); }
243  static Kind getKind(const IdentifierInfo *Name);
244
245  AttributeList *getNext() const { return Next; }
246  void setNext(AttributeList *N) { Next = N; }
247
248  /// getNumArgs - Return the number of actual arguments to this attribute.
249  unsigned getNumArgs() const { return NumArgs; }
250
251  /// getArg - Return the specified argument.
252  Expr *getArg(unsigned Arg) const {
253    assert(Arg < NumArgs && "Arg access out of range!");
254    return Args[Arg];
255  }
256
257  class arg_iterator {
258    Expr** X;
259    unsigned Idx;
260  public:
261    arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {}
262
263    arg_iterator& operator++() {
264      ++Idx;
265      return *this;
266    }
267
268    bool operator==(const arg_iterator& I) const {
269      assert (X == I.X &&
270              "compared arg_iterators are for different argument lists");
271      return Idx == I.Idx;
272    }
273
274    bool operator!=(const arg_iterator& I) const {
275      return !operator==(I);
276    }
277
278    Expr* operator*() const {
279      return X[Idx];
280    }
281
282    unsigned getArgNum() const {
283      return Idx+1;
284    }
285  };
286
287  arg_iterator arg_begin() const {
288    return arg_iterator(Args, 0);
289  }
290
291  arg_iterator arg_end() const {
292    return arg_iterator(Args, NumArgs);
293  }
294
295  const AvailabilityChange &getAvailabilityIntroduced() const {
296    assert(getKind() == AT_availability && "Not an availability attribute");
297    return AvailabilityIntroduced;
298  }
299
300  const AvailabilityChange &getAvailabilityDeprecated() const {
301    assert(getKind() == AT_availability && "Not an availability attribute");
302    return AvailabilityDeprecated;
303  }
304
305  const AvailabilityChange &getAvailabilityObsoleted() const {
306    assert(getKind() == AT_availability && "Not an availability attribute");
307    return AvailabilityObsoleted;
308  }
309};
310
311/// addAttributeLists - Add two AttributeLists together
312/// The right-hand list is appended to the left-hand list, if any
313/// A pointer to the joined list is returned.
314/// Note: the lists are not left unmodified.
315inline AttributeList *addAttributeLists(AttributeList *Left,
316                                        AttributeList *Right) {
317  if (!Left)
318    return Right;
319
320  AttributeList *next = Left, *prev;
321  do {
322    prev = next;
323    next = next->getNext();
324  } while (next);
325  prev->setNext(Right);
326  return Left;
327}
328
329/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
330/// Stores, in addition to the list proper, whether or not an actual list was
331/// (as opposed to an empty list, which may be ill-formed in some places) and
332/// the source range of the list.
333struct CXX0XAttributeList {
334  AttributeList *AttrList;
335  SourceRange Range;
336  bool HasAttr;
337  CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
338    : AttrList(attrList), Range(range), HasAttr (hasAttr) {
339  }
340  CXX0XAttributeList ()
341    : AttrList(0), Range(), HasAttr(false) {
342  }
343};
344
345/// ParsedAttributes - A collection of parsed attributes.  Currently
346/// we don't differentiate between the various attribute syntaxes,
347/// which is basically silly.
348///
349/// Right now this is a very lightweight container, but the expectation
350/// is that this will become significantly more serious.
351class ParsedAttributes {
352public:
353  ParsedAttributes() : list(0) {}
354
355  bool empty() const { return list == 0; }
356
357  void add(AttributeList *newAttr) {
358    assert(newAttr);
359    assert(newAttr->getNext() == 0);
360    newAttr->setNext(list);
361    list = newAttr;
362  }
363
364  void append(AttributeList *newList) {
365    if (!newList) return;
366
367    AttributeList *lastInNewList = newList;
368    while (AttributeList *next = lastInNewList->getNext())
369      lastInNewList = next;
370
371    lastInNewList->setNext(list);
372    list = newList;
373  }
374
375  void set(AttributeList *newList) {
376    list = newList;
377  }
378
379  void clear() { list = 0; }
380  AttributeList *getList() const { return list; }
381
382  /// Returns a reference to the attribute list.  Try not to introduce
383  /// dependencies on this method, it may not be long-lived.
384  AttributeList *&getListRef() { return list; }
385
386private:
387  AttributeList *list;
388};
389
390}  // end namespace clang
391
392#endif
393