AttributeList.h revision 0b7e678a11ece4288dc01aebb5b17e5eef8f8d2d
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 "llvm/ADT/SmallVector.h"
20#include "clang/Basic/SourceLocation.h"
21#include "clang/Basic/VersionTuple.h"
22#include <cassert>
23
24namespace clang {
25  class ASTContext;
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 { // TODO: This should really be called ParsedAttribute
55private:
56  IdentifierInfo *AttrName;
57  IdentifierInfo *ScopeName;
58  IdentifierInfo *ParmName;
59  SourceLocation AttrLoc;
60  SourceLocation ScopeLoc;
61  SourceLocation ParmLoc;
62
63  /// The number of expression arguments this attribute has.
64  /// The expressions themselves are stored after the object.
65  unsigned NumArgs;
66
67  /// True if Microsoft style: declspec(foo).
68  bool DeclspecAttribute;
69
70  /// True if C++0x-style: [[foo]].
71  bool CXX0XAttribute;
72
73  /// True if already diagnosed as invalid.
74  mutable bool Invalid;
75
76  /// True if this has the extra information associated with an
77  /// availability attribute.
78  bool IsAvailability;
79
80  /// The next attribute in the current position.
81  AttributeList *NextInPosition;
82
83  /// The next attribute allocated in the current Pool.
84  AttributeList *NextInPool;
85
86  Expr **getArgsBuffer() {
87    return reinterpret_cast<Expr**>(this+1);
88  }
89  Expr * const *getArgsBuffer() const {
90    return reinterpret_cast<Expr* const *>(this+1);
91  }
92
93  enum AvailabilitySlot {
94    IntroducedSlot, DeprecatedSlot, ObsoletedSlot
95  };
96
97  AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
98    return reinterpret_cast<AvailabilityChange*>(this+1)[index];
99  }
100  const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
101    return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
102  }
103
104  AttributeList(const AttributeList &); // DO NOT IMPLEMENT
105  void operator=(const AttributeList &); // DO NOT IMPLEMENT
106  void operator delete(void *); // DO NOT IMPLEMENT
107  ~AttributeList(); // DO NOT IMPLEMENT
108
109  size_t allocated_size() const;
110
111  AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc,
112                IdentifierInfo *scopeName, SourceLocation scopeLoc,
113                IdentifierInfo *parmName, SourceLocation parmLoc,
114                Expr **args, unsigned numArgs,
115                bool declspec, bool cxx0x)
116    : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
117      AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
118      NumArgs(numArgs),
119      DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false),
120      IsAvailability(false), NextInPosition(0), NextInPool(0) {
121    if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
122  }
123
124  AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc,
125                IdentifierInfo *scopeName, SourceLocation scopeLoc,
126                IdentifierInfo *parmName, SourceLocation parmLoc,
127                const AvailabilityChange &introduced,
128                const AvailabilityChange &deprecated,
129                const AvailabilityChange &obsoleted,
130                bool declspec, bool cxx0x)
131    : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
132      AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
133      NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
134      Invalid(false), IsAvailability(true), NextInPosition(0), NextInPool(0) {
135    new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
136    new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
137    new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
138  }
139
140  friend class AttributePool;
141  friend class AttributeFactory;
142
143public:
144  enum Kind {             // Please keep this list alphabetized.
145    AT_IBAction,          // Clang-specific.
146    AT_IBOutlet,          // Clang-specific.
147    AT_IBOutletCollection, // Clang-specific.
148    AT_address_space,
149    AT_alias,
150    AT_aligned,
151    AT_always_inline,
152    AT_analyzer_noreturn,
153    AT_annotate,
154    AT_availability,      // Clang-specific
155    AT_base_check,
156    AT_blocks,
157    AT_carries_dependency,
158    AT_cdecl,
159    AT_cleanup,
160    AT_common,
161    AT_const,
162    AT_constant,
163    AT_constructor,
164    AT_deprecated,
165    AT_destructor,
166    AT_device,
167    AT_dllexport,
168    AT_dllimport,
169    AT_ext_vector_type,
170    AT_fastcall,
171    AT_format,
172    AT_format_arg,
173    AT_global,
174    AT_gnu_inline,
175    AT_host,
176    AT_launch_bounds,
177    AT_malloc,
178    AT_may_alias,
179    AT_mode,
180    AT_neon_polyvector_type,    // Clang-specific.
181    AT_neon_vector_type,        // Clang-specific.
182    AT_naked,
183    AT_nodebug,
184    AT_noinline,
185    AT_no_instrument_function,
186    AT_nocommon,
187    AT_nonnull,
188    AT_noreturn,
189    AT_nothrow,
190    AT_nsobject,
191    AT_objc_exception,
192    AT_objc_method_family,
193    AT_cf_returns_not_retained, // Clang-specific.
194    AT_cf_returns_retained,     // Clang-specific.
195    AT_ns_returns_not_retained, // Clang-specific.
196    AT_ns_returns_retained,     // Clang-specific.
197    AT_ns_returns_autoreleased, // Clang-specific.
198    AT_cf_consumed,             // Clang-specific.
199    AT_ns_consumed,             // Clang-specific.
200    AT_ns_consumes_self,        // Clang-specific.
201    AT_objc_gc,
202    AT_opencl_image_access,     // OpenCL-specific.
203    AT_opencl_kernel_function,  // OpenCL-specific.
204    AT_overloadable,       // Clang-specific.
205    AT_ownership_holds,    // Clang-specific.
206    AT_ownership_returns,  // Clang-specific.
207    AT_ownership_takes,    // Clang-specific.
208    AT_packed,
209    AT_pascal,
210    AT_pure,
211    AT_regparm,
212    AT_section,
213    AT_sentinel,
214    AT_shared,
215    AT_stdcall,
216    AT_thiscall,
217    AT_transparent_union,
218    AT_unavailable,
219    AT_unused,
220    AT_used,
221    AT_uuid,
222    AT_vecreturn,     // PS3 PPU-specific.
223    AT_vector_size,
224    AT_visibility,
225    AT_warn_unused_result,
226    AT_weak,
227    AT_weakref,
228    AT_weak_import,
229    AT_reqd_wg_size,
230    AT_init_priority,
231    IgnoredAttribute,
232    UnknownAttribute
233  };
234
235  IdentifierInfo *getName() const { return AttrName; }
236  SourceLocation getLoc() const { return AttrLoc; }
237
238  bool hasScope() const { return ScopeName; }
239  IdentifierInfo *getScopeName() const { return ScopeName; }
240  SourceLocation getScopeLoc() const { return ScopeLoc; }
241
242  IdentifierInfo *getParameterName() const { return ParmName; }
243  SourceLocation getParameterLoc() const { return ParmLoc; }
244
245  bool isDeclspecAttribute() const { return DeclspecAttribute; }
246  bool isCXX0XAttribute() const { return CXX0XAttribute; }
247
248  bool isInvalid() const { return Invalid; }
249  void setInvalid(bool b = true) const { Invalid = b; }
250
251  Kind getKind() const { return getKind(getName()); }
252  static Kind getKind(const IdentifierInfo *Name);
253
254  AttributeList *getNext() const { return NextInPosition; }
255  void setNext(AttributeList *N) { NextInPosition = N; }
256
257  /// getNumArgs - Return the number of actual arguments to this attribute.
258  unsigned getNumArgs() const { return NumArgs; }
259
260  /// getArg - Return the specified argument.
261  Expr *getArg(unsigned Arg) const {
262    assert(Arg < NumArgs && "Arg access out of range!");
263    return getArgsBuffer()[Arg];
264  }
265
266  class arg_iterator {
267    Expr * const *X;
268    unsigned Idx;
269  public:
270    arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
271
272    arg_iterator& operator++() {
273      ++Idx;
274      return *this;
275    }
276
277    bool operator==(const arg_iterator& I) const {
278      assert (X == I.X &&
279              "compared arg_iterators are for different argument lists");
280      return Idx == I.Idx;
281    }
282
283    bool operator!=(const arg_iterator& I) const {
284      return !operator==(I);
285    }
286
287    Expr* operator*() const {
288      return X[Idx];
289    }
290
291    unsigned getArgNum() const {
292      return Idx+1;
293    }
294  };
295
296  arg_iterator arg_begin() const {
297    return arg_iterator(getArgsBuffer(), 0);
298  }
299
300  arg_iterator arg_end() const {
301    return arg_iterator(getArgsBuffer(), NumArgs);
302  }
303
304  const AvailabilityChange &getAvailabilityIntroduced() const {
305    assert(getKind() == AT_availability && "Not an availability attribute");
306    return getAvailabilitySlot(IntroducedSlot);
307  }
308
309  const AvailabilityChange &getAvailabilityDeprecated() const {
310    assert(getKind() == AT_availability && "Not an availability attribute");
311    return getAvailabilitySlot(DeprecatedSlot);
312  }
313
314  const AvailabilityChange &getAvailabilityObsoleted() const {
315    assert(getKind() == AT_availability && "Not an availability attribute");
316    return getAvailabilitySlot(ObsoletedSlot);
317  }
318};
319
320/// A factory, from which one makes pools, from which one creates
321/// individual attributes which are deallocated with the pool.
322///
323/// Note that it's tolerably cheap to create and destroy one of
324/// these as long as you don't actually allocate anything in it.
325class AttributeFactory {
326public:
327  enum {
328    /// The required allocation size of an availability attribute,
329    /// which we want to ensure is a multiple of sizeof(void*).
330    AvailabilityAllocSize =
331      sizeof(AttributeList)
332      + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
333         / sizeof(void*) * sizeof(void*))
334  };
335
336private:
337  enum {
338    /// The number of free lists we want to be sure to support
339    /// inline.  This is just enough that availability attributes
340    /// don't surpass it.  It's actually very unlikely we'll see an
341    /// attribute that needs more than that; on x86-64 you'd need 10
342    /// expression arguments, and on i386 you'd need 19.
343    InlineFreeListsCapacity =
344      1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
345  };
346
347  llvm::BumpPtrAllocator Alloc;
348
349  /// Free lists.  The index is determined by the following formula:
350  ///   (size - sizeof(AttributeList)) / sizeof(void*)
351  llvm::SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
352
353  // The following are the private interface used by AttributePool.
354  friend class AttributePool;
355
356  /// Allocate an attribute of the given size.
357  void *allocate(size_t size);
358
359  /// Reclaim all the attributes in the given pool chain, which is
360  /// non-empty.  Note that the current implementation is safe
361  /// against reclaiming things which were not actually allocated
362  /// with the allocator, although of course it's important to make
363  /// sure that their allocator lives at least as long as this one.
364  void reclaimPool(AttributeList *head);
365
366public:
367  AttributeFactory();
368  ~AttributeFactory();
369};
370
371class AttributePool {
372  AttributeFactory &Factory;
373  AttributeList *Head;
374
375  void *allocate(size_t size) {
376    return Factory.allocate(size);
377  }
378
379  AttributeList *add(AttributeList *attr) {
380    // We don't care about the order of the pool.
381    attr->NextInPool = Head;
382    Head = attr;
383    return attr;
384  }
385
386  void takePool(AttributeList *pool);
387
388public:
389  /// Create a new pool for a factory.
390  AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
391
392  /// Move the given pool's allocations to this pool.
393  AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
394    pool.Head = 0;
395  }
396
397  AttributeFactory &getFactory() const { return Factory; }
398
399  void clear() {
400    if (Head) {
401      Factory.reclaimPool(Head);
402      Head = 0;
403    }
404  }
405
406  /// Take the given pool's allocations and add them to this pool.
407  void takeAllFrom(AttributePool &pool) {
408    if (pool.Head) {
409      takePool(pool.Head);
410      pool.Head = 0;
411    }
412  }
413
414  ~AttributePool() {
415    if (Head) Factory.reclaimPool(Head);
416  }
417
418  AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc,
419                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
420                        IdentifierInfo *parmName, SourceLocation parmLoc,
421                        Expr **args, unsigned numArgs,
422                        bool declspec = false, bool cxx0x = false) {
423    void *memory = allocate(sizeof(AttributeList)
424                            + numArgs * sizeof(Expr*));
425    return add(new (memory) AttributeList(attrName, attrLoc,
426                                          scopeName, scopeLoc,
427                                          parmName, parmLoc,
428                                          args, numArgs,
429                                          declspec, cxx0x));
430  }
431
432  AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc,
433                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
434                        IdentifierInfo *parmName, SourceLocation parmLoc,
435                        const AvailabilityChange &introduced,
436                        const AvailabilityChange &deprecated,
437                        const AvailabilityChange &obsoleted,
438                        bool declspec = false, bool cxx0x = false) {
439    void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
440    return add(new (memory) AttributeList(attrName, attrLoc,
441                                          scopeName, scopeLoc,
442                                          parmName, parmLoc,
443                                          introduced, deprecated, obsoleted,
444                                          declspec, cxx0x));
445  }
446
447  AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
448                                        SourceLocation TokLoc, int Arg);
449};
450
451/// addAttributeLists - Add two AttributeLists together
452/// The right-hand list is appended to the left-hand list, if any
453/// A pointer to the joined list is returned.
454/// Note: the lists are not left unmodified.
455inline AttributeList *addAttributeLists(AttributeList *Left,
456                                        AttributeList *Right) {
457  if (!Left)
458    return Right;
459
460  AttributeList *next = Left, *prev;
461  do {
462    prev = next;
463    next = next->getNext();
464  } while (next);
465  prev->setNext(Right);
466  return Left;
467}
468
469/// CXX0XAttributeList - A wrapper around a C++0x attribute list.
470/// Stores, in addition to the list proper, whether or not an actual list was
471/// (as opposed to an empty list, which may be ill-formed in some places) and
472/// the source range of the list.
473struct CXX0XAttributeList {
474  AttributeList *AttrList;
475  SourceRange Range;
476  bool HasAttr;
477  CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
478    : AttrList(attrList), Range(range), HasAttr (hasAttr) {
479  }
480  CXX0XAttributeList ()
481    : AttrList(0), Range(), HasAttr(false) {
482  }
483};
484
485/// ParsedAttributes - A collection of parsed attributes.  Currently
486/// we don't differentiate between the various attribute syntaxes,
487/// which is basically silly.
488///
489/// Right now this is a very lightweight container, but the expectation
490/// is that this will become significantly more serious.
491class ParsedAttributes {
492public:
493  ParsedAttributes(AttributeFactory &factory)
494    : pool(factory), list(0) {
495  }
496
497  ParsedAttributes(ParsedAttributes &attrs)
498    : pool(attrs.pool), list(attrs.list) {
499    attrs.list = 0;
500  }
501
502  AttributePool &getPool() const { return pool; }
503
504  bool empty() const { return list == 0; }
505
506  void add(AttributeList *newAttr) {
507    assert(newAttr);
508    assert(newAttr->getNext() == 0);
509    newAttr->setNext(list);
510    list = newAttr;
511  }
512
513  void addAll(AttributeList *newList) {
514    if (!newList) return;
515
516    AttributeList *lastInNewList = newList;
517    while (AttributeList *next = lastInNewList->getNext())
518      lastInNewList = next;
519
520    lastInNewList->setNext(list);
521    list = newList;
522  }
523
524  void set(AttributeList *newList) {
525    list = newList;
526  }
527
528  void takeAllFrom(ParsedAttributes &attrs) {
529    addAll(attrs.list);
530    attrs.list = 0;
531    pool.takeAllFrom(attrs.pool);
532  }
533
534  void clear() { list = 0; pool.clear(); }
535  AttributeList *getList() const { return list; }
536
537  /// Returns a reference to the attribute list.  Try not to introduce
538  /// dependencies on this method, it may not be long-lived.
539  AttributeList *&getListRef() { return list; }
540
541
542  AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc,
543                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
544                        IdentifierInfo *parmName, SourceLocation parmLoc,
545                        Expr **args, unsigned numArgs,
546                        bool declspec = false, bool cxx0x = false) {
547    AttributeList *attr =
548      pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc,
549                  args, numArgs, declspec, cxx0x);
550    add(attr);
551    return attr;
552  }
553
554  AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc,
555                        IdentifierInfo *scopeName, SourceLocation scopeLoc,
556                        IdentifierInfo *parmName, SourceLocation parmLoc,
557                        const AvailabilityChange &introduced,
558                        const AvailabilityChange &deprecated,
559                        const AvailabilityChange &obsoleted,
560                        bool declspec = false, bool cxx0x = false) {
561    AttributeList *attr =
562      pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc,
563                  introduced, deprecated, obsoleted, declspec, cxx0x);
564    add(attr);
565    return attr;
566  }
567
568  AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
569                               SourceLocation loc, int arg) {
570    AttributeList *attr =
571      pool.createIntegerAttribute(C, name, loc, arg);
572    add(attr);
573    return attr;
574  }
575
576
577private:
578  mutable AttributePool pool;
579  AttributeList *list;
580};
581
582}  // end namespace clang
583
584#endif
585