Line data Source code
1 : //===-- Redeclarable.h - Base for Decls that can be redeclared -*- 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 Redeclarable interface.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #ifndef LLVM_CLANG_AST_REDECLARABLE_H
15 : #define LLVM_CLANG_AST_REDECLARABLE_H
16 :
17 : #include "clang/AST/ExternalASTSource.h"
18 : #include "llvm/ADT/PointerIntPair.h"
19 : #include "llvm/Support/Casting.h"
20 : #include <iterator>
21 :
22 : namespace clang {
23 :
24 : /// \brief Provides common interface for the Decls that can be redeclared.
25 : template<typename decl_type>
26 : class Redeclarable {
27 : protected:
28 : class DeclLink {
29 : /// A pointer to a known latest declaration, either statically known or
30 : /// generationally updated as decls are added by an external source.
31 : typedef LazyGenerationalUpdatePtr<const Decl*, Decl*,
32 : &ExternalASTSource::CompleteRedeclChain>
33 : KnownLatest;
34 :
35 : typedef const ASTContext *UninitializedLatest;
36 : typedef Decl *Previous;
37 :
38 : /// A pointer to either an uninitialized latest declaration (where either
39 : /// we've not yet set the previous decl or there isn't one), or to a known
40 : /// previous declaration.
41 : typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest;
42 :
43 : mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next;
44 :
45 : public:
46 : enum PreviousTag { PreviousLink };
47 : enum LatestTag { LatestLink };
48 :
49 : DeclLink(LatestTag, const ASTContext &Ctx)
50 : : Next(NotKnownLatest(&Ctx)) {}
51 : DeclLink(PreviousTag, decl_type *D)
52 : : Next(NotKnownLatest(Previous(D))) {}
53 :
54 : bool NextIsPrevious() const {
55 0 : return Next.is<NotKnownLatest>() &&
56 : // FIXME: 'template' is required on the next line due to an
57 : // apparent clang bug.
58 0 : Next.get<NotKnownLatest>().template is<Previous>();
59 : }
60 :
61 0 : bool NextIsLatest() const { return !NextIsPrevious(); }
62 :
63 : decl_type *getNext(const decl_type *D) const {
64 0 : if (Next.is<NotKnownLatest>()) {
65 0 : NotKnownLatest NKL = Next.get<NotKnownLatest>();
66 0 : if (NKL.is<Previous>())
67 0 : return static_cast<decl_type*>(NKL.get<Previous>());
68 :
69 : // Allocate the generational 'most recent' cache now, if needed.
70 0 : Next = KnownLatest(*NKL.get<UninitializedLatest>(),
71 0 : const_cast<decl_type *>(D));
72 0 : }
73 :
74 0 : return static_cast<decl_type*>(Next.get<KnownLatest>().get(D));
75 0 : }
76 :
77 : void setPrevious(decl_type *D) {
78 : assert(NextIsPrevious() && "decl became non-canonical unexpectedly");
79 : Next = Previous(D);
80 : }
81 :
82 : void setLatest(decl_type *D) {
83 : assert(NextIsLatest() && "decl became canonical unexpectedly");
84 : if (Next.is<NotKnownLatest>()) {
85 : NotKnownLatest NKL = Next.get<NotKnownLatest>();
86 : Next = KnownLatest(*NKL.get<UninitializedLatest>(), D);
87 : } else {
88 : auto Latest = Next.get<KnownLatest>();
89 : Latest.set(D);
90 : Next = Latest;
91 : }
92 : }
93 :
94 : void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); }
95 :
96 : Decl *getLatestNotUpdated() const {
97 : assert(NextIsLatest() && "expected a canonical decl");
98 : if (Next.is<NotKnownLatest>())
99 : return nullptr;
100 : return Next.get<KnownLatest>().getNotUpdated();
101 : }
102 : };
103 :
104 : static DeclLink PreviousDeclLink(decl_type *D) {
105 : return DeclLink(DeclLink::PreviousLink, D);
106 : }
107 :
108 : static DeclLink LatestDeclLink(const ASTContext &Ctx) {
109 : return DeclLink(DeclLink::LatestLink, Ctx);
110 : }
111 :
112 : /// \brief Points to the next redeclaration in the chain.
113 : ///
114 : /// If NextIsPrevious() is true, this is a link to the previous declaration
115 : /// of this same Decl. If NextIsLatest() is true, this is the first
116 : /// declaration and Link points to the latest declaration. For example:
117 : ///
118 : /// #1 int f(int x, int y = 1); // <pointer to #3, true>
119 : /// #2 int f(int x = 0, int y); // <pointer to #1, false>
120 : /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
121 : ///
122 : /// If there is only one declaration, it is <pointer to self, true>
123 : DeclLink RedeclLink;
124 : decl_type *First;
125 :
126 : decl_type *getNextRedeclaration() const {
127 0 : return RedeclLink.getNext(static_cast<const decl_type *>(this));
128 : }
129 :
130 : public:
131 : Redeclarable(const ASTContext &Ctx)
132 : : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {}
133 :
134 : /// \brief Return the previous declaration of this declaration or NULL if this
135 : /// is the first declaration.
136 : decl_type *getPreviousDecl() {
137 0 : if (RedeclLink.NextIsPrevious())
138 0 : return getNextRedeclaration();
139 0 : return nullptr;
140 0 : }
141 : const decl_type *getPreviousDecl() const {
142 : return const_cast<decl_type *>(
143 : static_cast<const decl_type*>(this))->getPreviousDecl();
144 : }
145 :
146 : /// \brief Return the first declaration of this declaration or itself if this
147 : /// is the only declaration.
148 0 : decl_type *getFirstDecl() { return First; }
149 :
150 : /// \brief Return the first declaration of this declaration or itself if this
151 : /// is the only declaration.
152 : const decl_type *getFirstDecl() const { return First; }
153 :
154 : /// \brief True if this is the first declaration in its redeclaration chain.
155 0 : bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }
156 :
157 : /// \brief Returns the most recent (re)declaration of this declaration.
158 : decl_type *getMostRecentDecl() {
159 0 : return getFirstDecl()->getNextRedeclaration();
160 : }
161 :
162 : /// \brief Returns the most recent (re)declaration of this declaration.
163 : const decl_type *getMostRecentDecl() const {
164 : return getFirstDecl()->getNextRedeclaration();
165 : }
166 :
167 : /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
168 : /// first and only declaration.
169 : void setPreviousDecl(decl_type *PrevDecl);
170 :
171 : /// \brief Iterates through all the redeclarations of the same decl.
172 : class redecl_iterator {
173 : /// Current - The current declaration.
174 : decl_type *Current;
175 : decl_type *Starter;
176 : bool PassedFirst;
177 :
178 : public:
179 : typedef decl_type* value_type;
180 : typedef decl_type* reference;
181 : typedef decl_type* pointer;
182 : typedef std::forward_iterator_tag iterator_category;
183 : typedef std::ptrdiff_t difference_type;
184 :
185 0 : redecl_iterator() : Current(nullptr) { }
186 : explicit redecl_iterator(decl_type *C)
187 0 : : Current(C), Starter(C), PassedFirst(false) { }
188 :
189 0 : reference operator*() const { return Current; }
190 : pointer operator->() const { return Current; }
191 :
192 : redecl_iterator& operator++() {
193 0 : assert(Current && "Advancing while iterator has reached end");
194 : // Sanity check to avoid infinite loop on invalid redecl chain.
195 0 : if (Current->isFirstDecl()) {
196 0 : if (PassedFirst) {
197 0 : assert(0 && "Passed first decl twice, invalid redecl chain!");
198 : Current = nullptr;
199 : return *this;
200 : }
201 0 : PassedFirst = true;
202 0 : }
203 :
204 : // Get either previous decl or latest decl.
205 0 : decl_type *Next = Current->getNextRedeclaration();
206 0 : Current = (Next != Starter) ? Next : nullptr;
207 0 : return *this;
208 : }
209 :
210 : redecl_iterator operator++(int) {
211 : redecl_iterator tmp(*this);
212 : ++(*this);
213 : return tmp;
214 : }
215 :
216 : friend bool operator==(redecl_iterator x, redecl_iterator y) {
217 : return x.Current == y.Current;
218 : }
219 : friend bool operator!=(redecl_iterator x, redecl_iterator y) {
220 0 : return x.Current != y.Current;
221 : }
222 : };
223 :
224 : typedef llvm::iterator_range<redecl_iterator> redecl_range;
225 :
226 : /// \brief Returns an iterator range for all the redeclarations of the same
227 : /// decl. It will iterate at least once (when this decl is the only one).
228 : redecl_range redecls() const {
229 0 : return redecl_range(redecl_iterator(const_cast<decl_type *>(
230 0 : static_cast<const decl_type *>(this))),
231 0 : redecl_iterator());
232 : }
233 :
234 : redecl_iterator redecls_begin() const { return redecls().begin(); }
235 : redecl_iterator redecls_end() const { return redecls().end(); }
236 :
237 : friend class ASTDeclReader;
238 : friend class ASTDeclWriter;
239 : };
240 :
241 : /// \brief Get the primary declaration for a declaration from an AST file. That
242 : /// will be the first-loaded declaration.
243 : Decl *getPrimaryMergedDecl(Decl *D);
244 :
245 : /// \brief Provides common interface for the Decls that cannot be redeclared,
246 : /// but can be merged if the same declaration is brought in from multiple
247 : /// modules.
248 : template<typename decl_type>
249 : class Mergeable {
250 : public:
251 : Mergeable() {}
252 :
253 : /// \brief Return the first declaration of this declaration or itself if this
254 : /// is the only declaration.
255 : decl_type *getFirstDecl() {
256 : decl_type *D = static_cast<decl_type*>(this);
257 : if (!D->isFromASTFile())
258 : return D;
259 : return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
260 : }
261 :
262 : /// \brief Return the first declaration of this declaration or itself if this
263 : /// is the only declaration.
264 : const decl_type *getFirstDecl() const {
265 : const decl_type *D = static_cast<const decl_type*>(this);
266 : if (!D->isFromASTFile())
267 : return D;
268 : return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
269 : }
270 :
271 : /// \brief Returns true if this is the first declaration.
272 : bool isFirstDecl() const { return getFirstDecl() == this; }
273 : };
274 :
275 : }
276 :
277 : #endif
|