Attr.h revision 212904
1//===--- Attr.h - Classes for representing expressions ----------*- 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 Attr interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_ATTR_H
15#define LLVM_CLANG_AST_ATTR_H
16
17#include "llvm/Support/Casting.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/StringRef.h"
20#include "clang/Basic/AttrKinds.h"
21#include "clang/AST/Type.h"
22#include "clang/Basic/SourceLocation.h"
23#include <cassert>
24#include <cstring>
25#include <algorithm>
26using llvm::dyn_cast;
27
28namespace clang {
29  class ASTContext;
30  class IdentifierInfo;
31  class ObjCInterfaceDecl;
32  class Expr;
33  class QualType;
34  class FunctionDecl;
35  class TypeSourceInfo;
36}
37
38// Defined in ASTContext.h
39void *operator new(size_t Bytes, clang::ASTContext &C,
40                   size_t Alignment = 16) throw ();
41// FIXME: Being forced to not have a default argument here due to redeclaration
42//        rules on default arguments sucks
43void *operator new[](size_t Bytes, clang::ASTContext &C,
44                     size_t Alignment) throw ();
45
46// It is good practice to pair new/delete operators.  Also, MSVC gives many
47// warnings if a matching delete overload is not declared, even though the
48// throw() spec guarantees it will not be implicitly called.
49void operator delete(void *Ptr, clang::ASTContext &C, size_t)
50              throw ();
51void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
52              throw ();
53
54namespace clang {
55
56/// Attr - This represents one attribute.
57class Attr {
58private:
59  SourceLocation Loc;
60  unsigned AttrKind : 16;
61  bool Inherited : 1;
62
63protected:
64  virtual ~Attr();
65
66  void* operator new(size_t bytes) throw() {
67    assert(0 && "Attrs cannot be allocated with regular 'new'.");
68    return 0;
69  }
70  void operator delete(void* data) throw() {
71    assert(0 && "Attrs cannot be released with regular 'delete'.");
72  }
73
74public:
75  // Forward so that the regular new and delete do not hide global ones.
76  void* operator new(size_t Bytes, ASTContext &C,
77                     size_t Alignment = 16) throw() {
78    return ::operator new(Bytes, C, Alignment);
79  }
80  void operator delete(void *Ptr, ASTContext &C,
81                       size_t Alignment) throw() {
82    return ::operator delete(Ptr, C, Alignment);
83  }
84
85protected:
86  Attr(attr::Kind AK, SourceLocation L)
87    : Loc(L), AttrKind(AK), Inherited(false) {}
88
89public:
90
91  /// \brief Whether this attribute should be merged to new
92  /// declarations.
93  virtual bool isMerged() const { return true; }
94
95  attr::Kind getKind() const {
96    return static_cast<attr::Kind>(AttrKind);
97  }
98
99  SourceLocation getLocation() const { return Loc; }
100  void setLocation(SourceLocation L) { Loc = L; }
101
102  bool isInherited() const { return Inherited; }
103  void setInherited(bool I) { Inherited = I; }
104
105  // Clone this attribute.
106  virtual Attr* clone(ASTContext &C) const = 0;
107
108  // Implement isa/cast/dyncast/etc.
109  static bool classof(const Attr *) { return true; }
110};
111
112#include "clang/AST/Attrs.inc"
113
114/// AttrVec - A vector of Attr, which is how they are stored on the AST.
115typedef llvm::SmallVector<Attr*, 2> AttrVec;
116typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
117
118/// DestroyAttrs - Destroy the contents of an AttrVec.
119inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
120}
121
122/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
123/// providing attributes that are of a specifc type.
124template <typename SpecificAttr>
125class specific_attr_iterator {
126  /// Current - The current, underlying iterator.
127  /// In order to ensure we don't dereference an invalid iterator unless
128  /// specifically requested, we don't necessarily advance this all the
129  /// way. Instead, we advance it when an operation is requested; if the
130  /// operation is acting on what should be a past-the-end iterator,
131  /// then we offer no guarantees, but this way we do not dererence a
132  /// past-the-end iterator when we move to a past-the-end position.
133  mutable AttrVec::const_iterator Current;
134
135  void AdvanceToNext() const {
136    while (!llvm::isa<SpecificAttr>(*Current))
137      ++Current;
138  }
139
140  void AdvanceToNext(AttrVec::const_iterator I) const {
141    while (Current != I && !llvm::isa<SpecificAttr>(*Current))
142      ++Current;
143  }
144
145public:
146  typedef SpecificAttr*             value_type;
147  typedef SpecificAttr*             reference;
148  typedef SpecificAttr*             pointer;
149  typedef std::forward_iterator_tag iterator_category;
150  typedef std::ptrdiff_t            difference_type;
151
152  specific_attr_iterator() : Current() { }
153  explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
154
155  reference operator*() const {
156    AdvanceToNext();
157    return llvm::cast<SpecificAttr>(*Current);
158  }
159  pointer operator->() const {
160    AdvanceToNext();
161    return llvm::cast<SpecificAttr>(*Current);
162  }
163
164  specific_attr_iterator& operator++() {
165    ++Current;
166    return *this;
167  }
168  specific_attr_iterator operator++(int) {
169    specific_attr_iterator Tmp(*this);
170    ++(*this);
171    return Tmp;
172  }
173
174  friend bool operator==(specific_attr_iterator Left,
175                         specific_attr_iterator Right) {
176    if (Left.Current < Right.Current)
177      Left.AdvanceToNext(Right.Current);
178    else
179      Right.AdvanceToNext(Left.Current);
180    return Left.Current == Right.Current;
181  }
182  friend bool operator!=(specific_attr_iterator Left,
183                         specific_attr_iterator Right) {
184    return !(Left == Right);
185  }
186};
187
188template <typename T>
189inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
190  return specific_attr_iterator<T>(vec.begin());
191}
192template <typename T>
193inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
194  return specific_attr_iterator<T>(vec.end());
195}
196
197template <typename T>
198inline bool hasSpecificAttr(const AttrVec& vec) {
199  return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
200}
201template <typename T>
202inline T *getSpecificAttr(const AttrVec& vec) {
203  specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
204  if (i != specific_attr_end<T>(vec))
205    return *i;
206  else
207    return 0;
208}
209
210/// getMaxAlignment - Returns the highest alignment value found among
211/// AlignedAttrs in an AttrVec, or 0 if there are none.
212inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
213  unsigned Align = 0;
214  specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
215  for(; i != e; ++i)
216    Align = std::max(Align, i->getAlignment(Ctx));
217  return Align;
218}
219
220}  // end namespace clang
221
222#endif
223