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