blob: 8c0c4d693268660c1f9b6f1527da3ae23de1b632 [file] [log] [blame]
Chris Lattnera2f42b12008-04-11 07:06:57 +00001//===- IdentifierResolver.cpp - 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 implements 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#include "IdentifierResolver.h"
Chris Lattnera2f42b12008-04-11 07:06:57 +000016#include <list>
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000017#include <vector>
Chris Lattnera2f42b12008-04-11 07:06:57 +000018
19using namespace clang;
20
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +000021//===----------------------------------------------------------------------===//
22// IdDeclInfoMap class
23//===----------------------------------------------------------------------===//
Chris Lattnera2f42b12008-04-11 07:06:57 +000024
25/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000026/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
Chris Lattnera2f42b12008-04-11 07:06:57 +000027/// individual IdDeclInfo to heap.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +000028class IdentifierResolver::IdDeclInfoMap {
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000029 static const unsigned int VECTOR_SIZE = 512;
30 // Holds vectors of IdDeclInfos that serve as 'pools'.
31 // New vectors are added when the current one is full.
32 std::list< std::vector<IdDeclInfo> > IDIVecs;
Chris Lattnera2f42b12008-04-11 07:06:57 +000033 unsigned int CurIndex;
34
35public:
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +000036 IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
Chris Lattnera2f42b12008-04-11 07:06:57 +000037
38 /// Returns the IdDeclInfo associated to the IdentifierInfo.
39 /// It creates a new IdDeclInfo if one was not created before for this id.
40 IdDeclInfo &operator[](IdentifierInfo *II);
41};
42
Argyrios Kyrtzidis7bc198f2008-04-14 00:09:21 +000043
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +000044//===----------------------------------------------------------------------===//
45// LookupContext Implementation
46//===----------------------------------------------------------------------===//
47
48/// getContext - Returns translation unit context for non ScopedDecls and
49/// for EnumConstantDecls returns the parent context of their EnumDecl.
50DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
51 DeclContext *Ctx;
52
53 if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D))
54 return FD->getParent();
55
56 if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
57 Ctx = EnumD->getDeclContext()->getParent();
58 } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
59 Ctx = SD->getDeclContext();
60 else
61 return TUCtx();
62
63 if (isa<TranslationUnitDecl>(Ctx))
64 return TUCtx();
65
66 return Ctx;
67}
68
69/// isEqOrContainedBy - Returns true of the given context is the same or a
70/// parent of this one.
71bool IdentifierResolver::LookupContext::isEqOrContainedBy(
72 const LookupContext &PC) const {
73 if (PC.isTU()) return true;
74
75 for (LookupContext Next = *this; !Next.isTU(); Next = Next.getParent())
76 if (Next.Ctx == PC.Ctx) return true;
77
78 return false;
79}
80
81
82//===----------------------------------------------------------------------===//
83// IdDeclInfo Implementation
84//===----------------------------------------------------------------------===//
85
86/// FindContext - Returns an iterator pointing just after the decl that is
87/// in the given context or in a parent of it. The search is in reverse
88/// order, from end to begin.
89IdentifierResolver::IdDeclInfo::DeclsTy::iterator
90IdentifierResolver::IdDeclInfo::FindContext(const LookupContext &Ctx,
91 const DeclsTy::iterator &Start) {
92 for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
93 if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
94 return I;
95 }
96
97 return Decls.begin();
98}
99
100/// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
101/// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
102/// be already added to the scope chain and must be in the same context as
103/// the decl that we want to add.
104void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D,
105 NamedDecl *Shadow) {
106 assert(LookupContext(D) == LookupContext(Shadow) &&
107 "Decl and Shadow not in same context!");
108
109 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
110 if (Shadow == *(I-1)) {
111 Decls.insert(I-1, D);
112 return;
113 }
114 }
115
116 assert(0 && "Shadow wasn't in scope chain!");
117}
118
119/// RemoveDecl - Remove the decl from the scope chain.
120/// The decl must already be part of the decl chain.
121void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
122 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
123 if (D == *(I-1)) {
124 Decls.erase(I-1);
125 return;
126 }
127 }
128
129 assert(0 && "Didn't find this decl on its identifier's chain!");
130}
131
132
133//===----------------------------------------------------------------------===//
134// IdentifierResolver Implementation
135//===----------------------------------------------------------------------===//
136
Argyrios Kyrtzidiseb7c3882008-09-09 21:32:02 +0000137IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
138 : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
139}
Argyrios Kyrtzidis7bc198f2008-04-14 00:09:21 +0000140IdentifierResolver::~IdentifierResolver() {
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000141 delete IdDeclInfos;
Argyrios Kyrtzidis7bc198f2008-04-14 00:09:21 +0000142}
Chris Lattnera2f42b12008-04-11 07:06:57 +0000143
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +0000144/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
145/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
146/// true if 'D' belongs to the given declaration context.
147bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S) {
148 if (Ctx->isFunctionOrMethod())
149 return S->isDeclScope(D);
150
151 return LookupContext(D) == LookupContext(Ctx);
152}
153
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000154/// AddDecl - Link the decl to its shadowed decl chain.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000155void IdentifierResolver::AddDecl(NamedDecl *D) {
Chris Lattnera2f42b12008-04-11 07:06:57 +0000156 IdentifierInfo *II = D->getIdentifier();
157 void *Ptr = II->getFETokenInfo<void>();
158
159 if (!Ptr) {
160 II->setFETokenInfo(D);
161 return;
162 }
163
164 IdDeclInfo *IDI;
165
166 if (isDeclPtr(Ptr)) {
167 II->setFETokenInfo(NULL);
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000168 IDI = &(*IdDeclInfos)[II];
169 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
170 IDI->AddDecl(PrevD);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000171 } else
172 IDI = toIdDeclInfo(Ptr);
173
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000174 IDI->AddDecl(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000175}
176
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000177/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
Argyrios Kyrtzidis3d0d83a2008-05-15 17:26:35 +0000178/// after the decl that the iterator points to, thus the 'Shadow' decl will be
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000179/// encountered before the 'D' decl.
180void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
181 assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
182 assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
183
Chris Lattnera2f42b12008-04-11 07:06:57 +0000184 IdentifierInfo *II = D->getIdentifier();
185 void *Ptr = II->getFETokenInfo<void>();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000186 assert(Ptr && "No decl from Ptr ?");
Chris Lattnera2f42b12008-04-11 07:06:57 +0000187
188 IdDeclInfo *IDI;
189
190 if (isDeclPtr(Ptr)) {
191 II->setFETokenInfo(NULL);
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000192 IDI = &(*IdDeclInfos)[II];
193 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
194 assert(PrevD == Shadow && "Invalid shadow decl ?");
195 IDI->AddDecl(D);
196 IDI->AddDecl(PrevD);
197 return;
198 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000199
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000200 IDI = toIdDeclInfo(Ptr);
201 IDI->AddShadowed(D, Shadow);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000202}
203
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000204/// RemoveDecl - Unlink the decl from its shadowed decl chain.
Chris Lattnera2f42b12008-04-11 07:06:57 +0000205/// The decl must already be part of the decl chain.
206void IdentifierResolver::RemoveDecl(NamedDecl *D) {
207 assert(D && "null param passed");
208 IdentifierInfo *II = D->getIdentifier();
209 void *Ptr = II->getFETokenInfo<void>();
210
211 assert(Ptr && "Didn't find this decl on its identifier's chain!");
212
213 if (isDeclPtr(Ptr)) {
214 assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
215 II->setFETokenInfo(NULL);
216 return;
217 }
218
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000219 return toIdDeclInfo(Ptr)->RemoveDecl(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000220}
221
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000222/// begin - Returns an iterator for decls of identifier 'II', starting at
223/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
224/// decls of parent declaration contexts too.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000225IdentifierResolver::iterator
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000226IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx,
227 bool LookInParentCtx) {
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000228 assert(Ctx && "null param passed");
Chris Lattnera2f42b12008-04-11 07:06:57 +0000229
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000230 void *Ptr = II->getFETokenInfo<void>();
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000231 if (!Ptr) return end();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000232
233 LookupContext LC(Ctx);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000234
235 if (isDeclPtr(Ptr)) {
236 NamedDecl *D = static_cast<NamedDecl*>(Ptr);
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000237 LookupContext DC(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000238
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000239 if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
240 (!LookInParentCtx && LC == DC))
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000241 return iterator(D);
242 else
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000243 return end();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000244 }
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000245
Chris Lattnera2f42b12008-04-11 07:06:57 +0000246 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000247
248 IdDeclInfo::DeclsTy::iterator I;
249 if (LookInParentCtx)
250 I = IDI->FindContext(LC);
251 else {
252 for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
253 if (LookupContext(*(I-1)) == LC)
254 break;
255 }
256
257 if (I != IDI->decls_begin())
258 return iterator(I-1, LookInParentCtx);
259 else // No decls found.
260 return end();
Chris Lattnera2f42b12008-04-11 07:06:57 +0000261}
262
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000263/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
264void IdentifierResolver::iterator::PreIncIter() {
265 NamedDecl *D = **this;
266 LookupContext Ctx(D);
267 void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
268 assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
269 IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000270
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000271 BaseIter I = getIterator();
272 if (LookInParentCtx())
273 I = Info->FindContext(Ctx, I);
274 else {
275 if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
276 // The next decl is in different declaration context.
277 // Skip remaining decls and set the iterator to the end.
278 I = Info->decls_begin();
279 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000280 }
281
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000282 if (I != Info->decls_begin())
283 *this = iterator(I-1, LookInParentCtx());
284 else // No more decls.
285 *this = end();
Chris Lattnera2f42b12008-04-11 07:06:57 +0000286}
287
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000288
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +0000289//===----------------------------------------------------------------------===//
290// IdDeclInfoMap Implementation
291//===----------------------------------------------------------------------===//
292
Chris Lattnera2f42b12008-04-11 07:06:57 +0000293/// Returns the IdDeclInfo associated to the IdentifierInfo.
294/// It creates a new IdDeclInfo if one was not created before for this id.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000295IdentifierResolver::IdDeclInfo &
296IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
Chris Lattnera2f42b12008-04-11 07:06:57 +0000297 assert (II && "null IdentifierInfo passed");
298 void *Ptr = II->getFETokenInfo<void>();
299
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000300 if (Ptr) return *toIdDeclInfo(Ptr);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000301
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000302 if (CurIndex == VECTOR_SIZE) {
303 // Add a IdDeclInfo vector 'pool'
Argyrios Kyrtzidis72e62b02008-04-12 12:38:58 +0000304 IDIVecs.push_back(std::vector<IdDeclInfo>());
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000305 // Fill the vector
306 IDIVecs.back().resize(VECTOR_SIZE);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000307 CurIndex = 0;
308 }
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000309 IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
Chris Lattnera2f42b12008-04-11 07:06:57 +0000310 II->setFETokenInfo(reinterpret_cast<void*>(
311 reinterpret_cast<uintptr_t>(IDI) | 0x1)
312 );
313 ++CurIndex;
314 return *IDI;
315}