blob: da1327be485a75bd2ef0ceb2d20c7e2e96e61117 [file] [log] [blame]
Chris Lattnera2f42b12008-04-11 07:06:57 +00001//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- 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//
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000010// This file defines the IdentifierResolver class, which is used for lexical
Chris Lattnera2f42b12008-04-11 07:06:57 +000011// scoped lookup, based on identifier.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
16#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
17
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +000018#include "clang/Basic/IdentifierTable.h"
19#include "clang/Parse/Scope.h"
20#include "clang/AST/Decl.h"
21
Chris Lattnera2f42b12008-04-11 07:06:57 +000022namespace clang {
Chris Lattnera2f42b12008-04-11 07:06:57 +000023
24/// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes.
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000025/// It manages the shadowing chains of identifiers and implements efficent decl
Chris Lattnera2f42b12008-04-11 07:06:57 +000026/// lookup based on an identifier.
27class IdentifierResolver {
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +000028
29 /// LookupContext - A wrapper for DeclContext. DeclContext is only part of
30 /// ScopedDecls, LookupContext can be used with all decls (assumes
31 /// translation unit context for non ScopedDecls).
32 class LookupContext {
33 DeclContext *Ctx;
34
35 /// TUCtx - Provides a common value for translation unit context for all
36 /// decls.
37 /// FIXME: When (if ?) all decls can point to their translation unit context
38 /// remove this hack.
39 static inline DeclContext *TUCtx() {
40 return reinterpret_cast<DeclContext*>(-1);
41 }
42
43 /// getContext - Returns translation unit context for non ScopedDecls and
44 /// for EnumConstantDecls returns the parent context of their EnumDecl.
45 static DeclContext *getContext(Decl *D) {
46 DeclContext *Ctx;
47
48 if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
49 Ctx = EnumD->getDeclContext()->getParent();
50 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
51 Ctx = SD->getDeclContext();
52 else
53 return TUCtx();
54
55 if (isa<TranslationUnitDecl>(Ctx))
56 return TUCtx();
57
58 return Ctx;
59 }
60
61 public:
62 LookupContext(Decl *D) {
63 Ctx = getContext(D);
64 }
65 LookupContext(DeclContext *DC) {
66 if (!DC || isa<TranslationUnitDecl>(DC))
67 Ctx = TUCtx();
68 else
69 Ctx = DC;
70 }
71
72 bool isTU() const {
73 return (Ctx == TUCtx());
74 }
75
76 /// getParent - Returns the parent context. This should not be called for
77 /// a translation unit context.
78 LookupContext getParent() const {
79 assert(!isTU() && "TU has no parent!");
80 return LookupContext(Ctx->getParent());
81 }
82
83 /// isEqOrContainedBy - Returns true of the given context is the same or a
84 /// parent of this one.
85 bool isEqOrContainedBy(const LookupContext &PC) const {
86 if (PC.isTU()) return true;
87
88 for (LookupContext Next = *this; !Next.isTU(); Next = Next.getParent())
89 if (Next.Ctx == PC.Ctx) return true;
90
91 return false;
92 }
93
94 bool operator==(const LookupContext &RHS) const {
95 return Ctx == RHS.Ctx;
96 }
97 bool operator!=(const LookupContext &RHS) const {
98 return Ctx != RHS.Ctx;
99 }
100 };
101
102 /// IdDeclInfo - Keeps track of information about decls associated to a
103 /// particular identifier. IdDeclInfos are lazily constructed and assigned
104 /// to an identifier the first time a decl with that identifier is shadowed
105 /// in some scope.
106 class IdDeclInfo {
107 public:
108 typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
109
110 inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
111 inline DeclsTy::iterator decls_end() { return Decls.end(); }
112
113 /// FindContext - Returns an iterator pointing just after the decl that is
114 /// in the given context or in a parent of it. The search is in reverse
115 /// order, from end to begin.
116 DeclsTy::iterator FindContext(const LookupContext &Ctx) {
117 return FindContext(Ctx, Decls.end());
118 }
119
120 /// FindContext - Returns an iterator pointing just after the decl that is
121 /// in the given context or in a parent of it. The search is in reverse
122 /// order, from end to begin.
123 DeclsTy::iterator FindContext(const LookupContext &Ctx,
124 const DeclsTy::iterator &Start) {
125 for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
126 if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
127 return I;
128 }
129
130 return Decls.begin();
131 }
132
133 /// iterator - Iterate over the decls by walking their parent contexts too.
134 class iterator {
135 public:
136 typedef DeclsTy::iterator BaseIter;
137
138 iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
139 const BaseIter &getBase() { return DI; }
140
141 NamedDecl *&operator*() const {
142 return *(DI-1);
143 }
144
145 bool operator==(const iterator &RHS) const {
146 return DI == RHS.DI;
147 }
148 bool operator!=(const iterator &RHS) const {
149 return DI != RHS.DI;
150 }
151
152 // Preincrement.
153 iterator& operator++() {
154 NamedDecl *D = **this;
155 void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
156 assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
157 DI = toIdDeclInfo(Ptr)->FindContext(LookupContext(D), DI-1);
158 return *this;
159 }
160
161 private:
162 BaseIter DI;
163 };
164
165 /// ctx_iterator - Iterator over the decls of a specific context only.
166 class ctx_iterator {
167 public:
168 typedef DeclsTy::iterator BaseIter;
169
170 ctx_iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
171 const BaseIter &getBase() { return DI; }
172
173 NamedDecl *&operator*() const {
174 return *(DI-1);
175 }
176
177 bool operator==(const ctx_iterator &RHS) const {
178 return DI == RHS.DI;
179 }
180 bool operator!=(const ctx_iterator &RHS) const {
181 return DI != RHS.DI;
182 }
183
184 // Preincrement.
185 ctx_iterator& operator++() {
186 NamedDecl *D = **this;
187 void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
188 assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
189 IdDeclInfo *Info = toIdDeclInfo(Ptr);
190
191 --DI;
192 if (DI != Info->Decls.begin() &&
193 LookupContext(D) != LookupContext(**this))
194 DI = Info->Decls.begin();
195 return *this;
196 }
197
198 private:
199 BaseIter DI;
200 };
201
202 void AddDecl(NamedDecl *D) {
203 Decls.insert(FindContext(LookupContext(D)), D);
204 }
205
206 /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
207 /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
208 /// be already added to the scope chain and must be in the same context as
209 /// the decl that we want to add.
210 void AddShadowed(NamedDecl *D, NamedDecl *Shadow) {
211 assert(LookupContext(D) == LookupContext(Shadow) &&
212 "Decl and Shadow not in same context!");
213
214 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
215 if (Shadow == *(I-1)) {
216 Decls.insert(I-1, D);
217 return;
218 }
219 }
220
221 assert(0 && "Shadow wasn't in scope chain!");
222 }
223
224 /// RemoveDecl - Remove the decl from the scope chain.
225 /// The decl must already be part of the decl chain.
226 void RemoveDecl(NamedDecl *D) {
227 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
228 if (D == *(I-1)) {
229 Decls.erase(I-1);
230 return;
231 }
232 }
233
234 assert(0 && "Didn't find this decl on its identifier's chain!");
235 }
236
237 private:
238 DeclsTy Decls;
239 };
240
241 /// SwizzledIterator - Can be instantiated either with a single NamedDecl*
242 /// (the common case where only one decl is associated with an identifier) or
243 /// with an 'Iter' iterator, when there are more than one decls to lookup.
244 template<typename Iter>
245 class SwizzledIterator {
246 uintptr_t Ptr;
247
248 SwizzledIterator() : Ptr(0) {}
249 SwizzledIterator(NamedDecl *D) {
250 Ptr = reinterpret_cast<uintptr_t>(D);
251 }
252 SwizzledIterator(Iter I) {
253 Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
254 }
255
256 bool isIterator() const { return (Ptr & 0x1); }
257
258 Iter getIterator() const {
259 assert(isIterator() && "Ptr not an iterator.");
260 return reinterpret_cast<typename Iter::BaseIter>(Ptr & ~0x1);
261 }
262
263 friend class IdentifierResolver;
264 public:
265 NamedDecl *operator*() const {
266 if (isIterator())
267 return *getIterator();
268 else
269 return reinterpret_cast<NamedDecl*>(Ptr);
270 }
271
272 bool operator==(const SwizzledIterator &RHS) const {
273 return Ptr == RHS.Ptr;
274 }
275 bool operator!=(const SwizzledIterator &RHS) const {
276 return Ptr != RHS.Ptr;
277 }
278
279 // Preincrement.
280 SwizzledIterator& operator++() {
281 if (isIterator()) {
282 Iter I = getIterator();
283 ++I;
284 Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
285 }
286 else // This is a single NamedDecl*.
287 Ptr = 0;
288
289 return *this;
290 }
291 };
292
Chris Lattnera2f42b12008-04-11 07:06:57 +0000293public:
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000294
295 typedef SwizzledIterator<IdDeclInfo::iterator> iterator;
296 typedef SwizzledIterator<IdDeclInfo::ctx_iterator> ctx_iterator;
297
298 /// begin - Returns an iterator for all decls, starting at the given
299 /// declaration context.
300 static iterator begin(const IdentifierInfo *II, DeclContext *Ctx);
301
302 static iterator end(const IdentifierInfo *II) {
303 void *Ptr = II->getFETokenInfo<void>();
304 if (!Ptr || isDeclPtr(Ptr))
305 return iterator();
306
307 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
308 return iterator(IDI->decls_begin());
309 }
310
311 /// ctx_begin - Returns an iterator for only decls that belong to the given
312 /// declaration context.
313 static ctx_iterator ctx_begin(const IdentifierInfo *II, DeclContext *Ctx);
314
315 static ctx_iterator ctx_end(const IdentifierInfo *II) {
316 void *Ptr = II->getFETokenInfo<void>();
317 if (!Ptr || isDeclPtr(Ptr))
318 return ctx_iterator();
319
320 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
321 return ctx_iterator(IDI->decls_begin());
322 }
323
324 /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
325 /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
326 /// true if 'D' belongs to the given declaration context.
327 static bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
328 if (Ctx->isFunctionOrMethod())
329 return S->isDeclScope(D);
330
331 return LookupContext(D) == LookupContext(Ctx);
332 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000333
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000334 /// AddDecl - Link the decl to its shadowed decl chain.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000335 void AddDecl(NamedDecl *D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000336
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000337 /// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
338 /// after the decl that the iterator points to, thus the 'CIT' decl will be
339 /// encountered before the 'D' decl.
340 void AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000341
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000342 /// RemoveDecl - Unlink the decl from its shadowed decl chain.
Chris Lattnera2f42b12008-04-11 07:06:57 +0000343 /// The decl must already be part of the decl chain.
344 void RemoveDecl(NamedDecl *D);
345
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000346 IdentifierResolver();
347 ~IdentifierResolver();
Chris Lattnera2f42b12008-04-11 07:06:57 +0000348
349private:
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000350 class IdDeclInfoMap;
351 IdDeclInfoMap *IdDeclInfos;
352
353 /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
354 static inline bool isDeclPtr(void *Ptr) {
355 return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
356 }
357
358 /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
359 static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
360 assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
361 && "Ptr not a IdDeclInfo* !");
362 return reinterpret_cast<IdDeclInfo*>(
363 reinterpret_cast<uintptr_t>(Ptr) & ~0x1
364 );
365 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000366};
367
368} // end namespace clang
369
370#endif