UnresolvedSet.h revision 205408
1//===-- UnresolvedSet.h - Unresolved sets of declarations  ------*- 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 UnresolvedSet class, which is used to store
11//  collections of declarations in the AST.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_UNRESOLVEDSET_H
16#define LLVM_CLANG_AST_UNRESOLVEDSET_H
17
18#include <iterator>
19#include "llvm/ADT/SmallVector.h"
20#include "clang/Basic/Specifiers.h"
21
22namespace clang {
23
24class NamedDecl;
25
26/// A POD class for pairing a NamedDecl* with an access specifier.
27/// Can be put into unions.
28class DeclAccessPair {
29  NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
30
31  enum { Mask = 0x3 };
32
33public:
34  static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
35    DeclAccessPair p;
36    p.set(D, AS);
37    return p;
38  }
39
40  NamedDecl *getDecl() const {
41    return (NamedDecl*) (~Mask & (uintptr_t) Ptr);
42  }
43  AccessSpecifier getAccess() const {
44    return AccessSpecifier(Mask & (uintptr_t) Ptr);
45  }
46
47  void setDecl(NamedDecl *D) {
48    set(D, getAccess());
49  }
50  void setAccess(AccessSpecifier AS) {
51    set(getDecl(), AS);
52  }
53  void set(NamedDecl *D, AccessSpecifier AS) {
54    Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) |
55                                       reinterpret_cast<uintptr_t>(D));
56  }
57
58  operator NamedDecl*() const { return getDecl(); }
59  NamedDecl *operator->() const { return getDecl(); }
60};
61}
62
63// Take a moment to tell SmallVector that this is POD.
64namespace llvm {
65template<typename> struct isPodLike;
66template<> struct isPodLike<clang::DeclAccessPair> {
67   static const bool value = true;
68};
69}
70
71namespace clang {
72
73/// The iterator over UnresolvedSets.  Serves as both the const and
74/// non-const iterator.
75class UnresolvedSetIterator {
76private:
77  typedef llvm::SmallVectorImpl<DeclAccessPair> DeclsTy;
78  typedef DeclsTy::iterator IteratorTy;
79
80  IteratorTy ir;
81
82  friend class UnresolvedSetImpl;
83  explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
84  explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
85    ir(const_cast<DeclsTy::iterator>(ir)) {}
86public:
87  UnresolvedSetIterator() {}
88
89  typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
90  typedef NamedDecl *value_type;
91  typedef NamedDecl **pointer;
92  typedef NamedDecl *reference;
93  typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
94
95  NamedDecl *getDecl() const { return ir->getDecl(); }
96  AccessSpecifier getAccess() const { return ir->getAccess(); }
97  DeclAccessPair getPair() const { return *ir; }
98
99  NamedDecl *operator*() const { return getDecl(); }
100
101  UnresolvedSetIterator &operator++() { ++ir; return *this; }
102  UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
103  UnresolvedSetIterator &operator--() { --ir; return *this; }
104  UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
105
106  UnresolvedSetIterator &operator+=(difference_type d) {
107    ir += d; return *this;
108  }
109  UnresolvedSetIterator operator+(difference_type d) const {
110    return UnresolvedSetIterator(ir + d);
111  }
112  UnresolvedSetIterator &operator-=(difference_type d) {
113    ir -= d; return *this;
114  }
115  UnresolvedSetIterator operator-(difference_type d) const {
116    return UnresolvedSetIterator(ir - d);
117  }
118  value_type operator[](difference_type d) const { return *(*this + d); }
119
120  difference_type operator-(const UnresolvedSetIterator &o) const {
121    return ir - o.ir;
122  }
123
124  bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
125  bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
126  bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
127  bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
128  bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
129  bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
130};
131
132/// UnresolvedSet - A set of unresolved declarations.  This is needed
133/// in a lot of places, but isn't really worth breaking into its own
134/// header right now.
135class UnresolvedSetImpl {
136  typedef UnresolvedSetIterator::DeclsTy DeclsTy;
137
138  // Don't allow direct construction, and only permit subclassing by
139  // UnresolvedSet.
140private:
141  template <unsigned N> friend class UnresolvedSet;
142  UnresolvedSetImpl() {}
143  UnresolvedSetImpl(const UnresolvedSetImpl &) {}
144
145public:
146  // We don't currently support assignment through this iterator, so we might
147  // as well use the same implementation twice.
148  typedef UnresolvedSetIterator iterator;
149  typedef UnresolvedSetIterator const_iterator;
150
151  iterator begin() { return iterator(decls().begin()); }
152  iterator end() { return iterator(decls().end()); }
153
154  const_iterator begin() const { return const_iterator(decls().begin()); }
155  const_iterator end() const { return const_iterator(decls().end()); }
156
157  void addDecl(NamedDecl *D) {
158    addDecl(D, AS_none);
159  }
160
161  void addDecl(NamedDecl *D, AccessSpecifier AS) {
162    decls().push_back(DeclAccessPair::make(D, AS));
163  }
164
165  /// Replaces the given declaration with the new one, once.
166  ///
167  /// \return true if the set changed
168  bool replace(const NamedDecl* Old, NamedDecl *New) {
169    for (DeclsTy::iterator I = decls().begin(), E = decls().end(); I != E; ++I)
170      if (I->getDecl() == Old)
171        return (I->setDecl(New), true);
172    return false;
173  }
174
175  /// Replaces the declaration at the given iterator with the new one,
176  /// preserving the original access bits.
177  void replace(iterator I, NamedDecl *New) {
178    I.ir->setDecl(New);
179  }
180
181  void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
182    I.ir->set(New, AS);
183  }
184
185  void erase(unsigned I) {
186    decls()[I] = decls().back();
187    decls().pop_back();
188  }
189
190  void erase(iterator I) {
191    *I.ir = decls().back();
192    decls().pop_back();
193  }
194
195  void setAccess(iterator I, AccessSpecifier AS) {
196    I.ir->setAccess(AS);
197  }
198
199  void clear() { decls().clear(); }
200  void set_size(unsigned N) { decls().set_size(N); }
201
202  bool empty() const { return decls().empty(); }
203  unsigned size() const { return decls().size(); }
204
205  void append(iterator I, iterator E) {
206    decls().append(I.ir, E.ir);
207  }
208
209  DeclAccessPair &operator[](unsigned I) { return decls()[I]; }
210  const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; }
211
212private:
213  // These work because the only permitted subclass is UnresolvedSetImpl
214
215  DeclsTy &decls() {
216    return *reinterpret_cast<DeclsTy*>(this);
217  }
218  const DeclsTy &decls() const {
219    return *reinterpret_cast<const DeclsTy*>(this);
220  }
221};
222
223/// A set of unresolved declarations
224template <unsigned InlineCapacity> class UnresolvedSet :
225    public UnresolvedSetImpl {
226  llvm::SmallVector<DeclAccessPair, InlineCapacity> Decls;
227};
228
229
230} // namespace clang
231
232#endif
233