blob: 79432954e5e5c3a6b45c0546b3b4af09a7fe2c6a [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 Kyrtzidis7bc198f2008-04-14 00:09:21 +0000137IdentifierResolver::IdentifierResolver() : IdDeclInfos(new IdDeclInfoMap) {}
138IdentifierResolver::~IdentifierResolver() {
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000139 delete IdDeclInfos;
Argyrios Kyrtzidis7bc198f2008-04-14 00:09:21 +0000140}
Chris Lattnera2f42b12008-04-11 07:06:57 +0000141
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +0000142/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
143/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
144/// true if 'D' belongs to the given declaration context.
145bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S) {
146 if (Ctx->isFunctionOrMethod())
147 return S->isDeclScope(D);
148
149 return LookupContext(D) == LookupContext(Ctx);
150}
151
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000152/// AddDecl - Link the decl to its shadowed decl chain.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000153void IdentifierResolver::AddDecl(NamedDecl *D) {
Chris Lattnera2f42b12008-04-11 07:06:57 +0000154 IdentifierInfo *II = D->getIdentifier();
155 void *Ptr = II->getFETokenInfo<void>();
156
157 if (!Ptr) {
158 II->setFETokenInfo(D);
159 return;
160 }
161
162 IdDeclInfo *IDI;
163
164 if (isDeclPtr(Ptr)) {
165 II->setFETokenInfo(NULL);
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000166 IDI = &(*IdDeclInfos)[II];
167 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
168 IDI->AddDecl(PrevD);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000169 } else
170 IDI = toIdDeclInfo(Ptr);
171
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000172 IDI->AddDecl(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000173}
174
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000175/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
Argyrios Kyrtzidis3d0d83a2008-05-15 17:26:35 +0000176/// after the decl that the iterator points to, thus the 'Shadow' decl will be
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000177/// encountered before the 'D' decl.
178void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
179 assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
180 assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
181
Chris Lattnera2f42b12008-04-11 07:06:57 +0000182 IdentifierInfo *II = D->getIdentifier();
183 void *Ptr = II->getFETokenInfo<void>();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000184 assert(Ptr && "No decl from Ptr ?");
Chris Lattnera2f42b12008-04-11 07:06:57 +0000185
186 IdDeclInfo *IDI;
187
188 if (isDeclPtr(Ptr)) {
189 II->setFETokenInfo(NULL);
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000190 IDI = &(*IdDeclInfos)[II];
191 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
192 assert(PrevD == Shadow && "Invalid shadow decl ?");
193 IDI->AddDecl(D);
194 IDI->AddDecl(PrevD);
195 return;
196 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000197
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000198 IDI = toIdDeclInfo(Ptr);
199 IDI->AddShadowed(D, Shadow);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000200}
201
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000202/// RemoveDecl - Unlink the decl from its shadowed decl chain.
Chris Lattnera2f42b12008-04-11 07:06:57 +0000203/// The decl must already be part of the decl chain.
204void IdentifierResolver::RemoveDecl(NamedDecl *D) {
205 assert(D && "null param passed");
206 IdentifierInfo *II = D->getIdentifier();
207 void *Ptr = II->getFETokenInfo<void>();
208
209 assert(Ptr && "Didn't find this decl on its identifier's chain!");
210
211 if (isDeclPtr(Ptr)) {
212 assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
213 II->setFETokenInfo(NULL);
214 return;
215 }
216
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000217 return toIdDeclInfo(Ptr)->RemoveDecl(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000218}
219
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000220/// begin - Returns an iterator for decls of identifier 'II', starting at
221/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
222/// decls of parent declaration contexts too.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000223IdentifierResolver::iterator
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000224IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx,
225 bool LookInParentCtx) {
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000226 assert(Ctx && "null param passed");
Chris Lattnera2f42b12008-04-11 07:06:57 +0000227
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000228 void *Ptr = II->getFETokenInfo<void>();
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000229 if (!Ptr) return end();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000230
231 LookupContext LC(Ctx);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000232
233 if (isDeclPtr(Ptr)) {
234 NamedDecl *D = static_cast<NamedDecl*>(Ptr);
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000235 LookupContext DC(D);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000236
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000237 if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
238 (!LookInParentCtx && LC == DC))
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000239 return iterator(D);
240 else
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000241 return end();
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000242 }
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000243
Chris Lattnera2f42b12008-04-11 07:06:57 +0000244 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000245
246 IdDeclInfo::DeclsTy::iterator I;
247 if (LookInParentCtx)
248 I = IDI->FindContext(LC);
249 else {
250 for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
251 if (LookupContext(*(I-1)) == LC)
252 break;
253 }
254
255 if (I != IDI->decls_begin())
256 return iterator(I-1, LookInParentCtx);
257 else // No decls found.
258 return end();
Chris Lattnera2f42b12008-04-11 07:06:57 +0000259}
260
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000261/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
262void IdentifierResolver::iterator::PreIncIter() {
263 NamedDecl *D = **this;
264 LookupContext Ctx(D);
265 void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
266 assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
267 IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000268
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000269 BaseIter I = getIterator();
270 if (LookInParentCtx())
271 I = Info->FindContext(Ctx, I);
272 else {
273 if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
274 // The next decl is in different declaration context.
275 // Skip remaining decls and set the iterator to the end.
276 I = Info->decls_begin();
277 }
Chris Lattnera2f42b12008-04-11 07:06:57 +0000278 }
279
Argyrios Kyrtzidis90eb5392008-07-17 17:49:50 +0000280 if (I != Info->decls_begin())
281 *this = iterator(I-1, LookInParentCtx());
282 else // No more decls.
283 *this = end();
Chris Lattnera2f42b12008-04-11 07:06:57 +0000284}
285
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000286
Argyrios Kyrtzidis81bebb12008-09-09 19:28:27 +0000287//===----------------------------------------------------------------------===//
288// IdDeclInfoMap Implementation
289//===----------------------------------------------------------------------===//
290
Chris Lattnera2f42b12008-04-11 07:06:57 +0000291/// Returns the IdDeclInfo associated to the IdentifierInfo.
292/// It creates a new IdDeclInfo if one was not created before for this id.
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000293IdentifierResolver::IdDeclInfo &
294IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
Chris Lattnera2f42b12008-04-11 07:06:57 +0000295 assert (II && "null IdentifierInfo passed");
296 void *Ptr = II->getFETokenInfo<void>();
297
Argyrios Kyrtzidis00bc6452008-05-09 23:39:43 +0000298 if (Ptr) return *toIdDeclInfo(Ptr);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000299
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000300 if (CurIndex == VECTOR_SIZE) {
301 // Add a IdDeclInfo vector 'pool'
Argyrios Kyrtzidis72e62b02008-04-12 12:38:58 +0000302 IDIVecs.push_back(std::vector<IdDeclInfo>());
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000303 // Fill the vector
304 IDIVecs.back().resize(VECTOR_SIZE);
Chris Lattnera2f42b12008-04-11 07:06:57 +0000305 CurIndex = 0;
306 }
Argyrios Kyrtzidis321f2782008-04-12 01:50:47 +0000307 IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
Chris Lattnera2f42b12008-04-11 07:06:57 +0000308 II->setFETokenInfo(reinterpret_cast<void*>(
309 reinterpret_cast<uintptr_t>(IDI) | 0x1)
310 );
311 ++CurIndex;
312 return *IDI;
313}