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