blob: eae64384cdd58733743a1c82d7de508887988e6f [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//
10// This file implements the IdentifierResolver class,which is used for lexical
11// scoped lookup, based on identifier.
12//
13//===----------------------------------------------------------------------===//
14
15#include "IdentifierResolver.h"
16#include "clang/Basic/IdentifierTable.h"
17#include "clang/AST/Decl.h"
18#include <list>
19
20using namespace clang;
21
22class IdDeclInfo;
23
24/// FETokenInfo of an identifier contains a Decl pointer if lower bit == 0
25static inline bool isDeclPtr(void *Ptr) {
26 return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
27}
28
29/// FETokenInfo of an identifier contains a IdDeclInfo pointer if lower bit == 1
30static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
31 return reinterpret_cast<IdDeclInfo*>(
32 reinterpret_cast<uintptr_t>(Ptr) & ~0x1
33 );
34}
35
36
37/// IdDeclInfo - Keeps track of information about decls associated to a particular
38/// identifier. IdDeclInfos are lazily constructed and assigned to an identifier
39/// the first time a decl with that identifier is shadowed in some scope.
40class IdDeclInfo {
41 typedef llvm::SmallVector<NamedDecl *, 2> ShadowedTy;
42 ShadowedTy ShadowedDecls;
43
44public:
45 typedef ShadowedTy::iterator ShadowedIter;
46
47 inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); }
48 inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); }
49
50 /// Add a decl in the scope chain
51 void PushShadowed(NamedDecl *D) {
52 assert(D && "Decl null");
53 ShadowedDecls.push_back(D);
54 }
55
56 /// Add the decl at the top of scope chain
57 void PushGlobalShadowed(NamedDecl *D) {
58 assert(D && "Decl null");
59 ShadowedDecls.insert(ShadowedDecls.begin(), D);
60 }
61
62 /// RemoveShadowed - Remove the decl from the scope chain.
63 /// The decl must already be part of the decl chain.
64 void RemoveShadowed(NamedDecl *D);
65};
66
67
68/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
69/// Allocates 'pools' (arrays of IdDeclInfos) to avoid allocating each
70/// individual IdDeclInfo to heap.
71class IdentifierResolver::IdDeclInfoMap {
72 static const unsigned int ARRAY_SIZE = 512;
73 // Holds pointers to arrays of IdDeclInfos that serve as 'pools'.
74 // Used only to iterate and destroy them at destructor.
75 std::list<IdDeclInfo*> IDIArrPtrs;
76 IdDeclInfo *CurArr;
77 unsigned int CurIndex;
78
79public:
80 IdDeclInfoMap() : CurIndex(ARRAY_SIZE) {}
81 ~IdDeclInfoMap() {
82 for (std::list<IdDeclInfo*>::iterator it = IDIArrPtrs.begin();
83 it != IDIArrPtrs.end(); ++it)
84 delete[] *it;
85 }
86
87 /// Returns the IdDeclInfo associated to the IdentifierInfo.
88 /// It creates a new IdDeclInfo if one was not created before for this id.
89 IdDeclInfo &operator[](IdentifierInfo *II);
90};
91
92
93IdentifierResolver::IdentifierResolver() : IdDeclInfos(*new IdDeclInfoMap) {}
94IdentifierResolver::~IdentifierResolver() { delete &IdDeclInfos; }
95
96/// AddDecl - Link the decl to its shadowed decl chain
97void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
98 assert(D && S && "null param passed");
99 IdentifierInfo *II = D->getIdentifier();
100 void *Ptr = II->getFETokenInfo<void>();
101
102 if (!Ptr) {
103 II->setFETokenInfo(D);
104 return;
105 }
106
107 IdDeclInfo *IDI;
108
109 if (isDeclPtr(Ptr)) {
110 II->setFETokenInfo(NULL);
111 IDI = &IdDeclInfos[II];
112 IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
113 } else
114 IDI = toIdDeclInfo(Ptr);
115
116 IDI->PushShadowed(D);
117}
118
119/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain
120void IdentifierResolver::AddGlobalDecl(NamedDecl *D) {
121 assert(D && "null param passed");
122 IdentifierInfo *II = D->getIdentifier();
123 void *Ptr = II->getFETokenInfo<void>();
124
125 if (!Ptr) {
126 II->setFETokenInfo(D);
127 return;
128 }
129
130 IdDeclInfo *IDI;
131
132 if (isDeclPtr(Ptr)) {
133 II->setFETokenInfo(NULL);
134 IDI = &IdDeclInfos[II];
135 IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
136 } else
137 IDI = toIdDeclInfo(Ptr);
138
139 IDI->PushGlobalShadowed(D);
140}
141
142/// RemoveDecl - Unlink the decl from its shadowed decl chain
143/// The decl must already be part of the decl chain.
144void IdentifierResolver::RemoveDecl(NamedDecl *D) {
145 assert(D && "null param passed");
146 IdentifierInfo *II = D->getIdentifier();
147 void *Ptr = II->getFETokenInfo<void>();
148
149 assert(Ptr && "Didn't find this decl on its identifier's chain!");
150
151 if (isDeclPtr(Ptr)) {
152 assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
153 II->setFETokenInfo(NULL);
154 return;
155 }
156
157 return toIdDeclInfo(Ptr)->RemoveShadowed(D);
158}
159
160/// Lookup - Find the non-shadowed decl that belongs to a particular
161/// Decl::IdentifierNamespace.
162NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NSI) {
163 assert(II && "null param passed");
164 Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
165 void *Ptr = II->getFETokenInfo<void>();
166
167 if (!Ptr) return NULL;
168
169 if (isDeclPtr(Ptr)) {
170 NamedDecl *D = static_cast<NamedDecl*>(Ptr);
171 return (D->getIdentifierNamespace() == NS) ? D : NULL;
172 }
173
174 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
175
176 // ShadowedDecls are ordered from most shadowed to less shadowed.
177 // So we do a reverse iteration from end to begin.
178 for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
179 SI != IDI->shadowed_begin(); --SI) {
180 NamedDecl *D = *(SI-1);
181 if (D->getIdentifierNamespace() == NS)
182 return D;
183 }
184
185 // we didn't find the decl.
186 return NULL;
187}
188
189/// RemoveShadowed - Remove the decl from the scope chain.
190/// The decl must already be part of the decl chain.
191void IdDeclInfo::RemoveShadowed(NamedDecl *D) {
192 assert(D && "null decl passed");
193 assert(ShadowedDecls.size() > 0 &&
194 "Didn't find this decl on its identifier's chain!");
195
196 // common case
197 if (D == ShadowedDecls.back()) {
198 ShadowedDecls.pop_back();
199 return;
200 }
201
202 for (ShadowedIter SI = ShadowedDecls.end()-1;
203 SI != ShadowedDecls.begin(); --SI) {
204 if (*(SI-1) == D) {
205 ShadowedDecls.erase(SI-1);
206 return;
207 }
208 }
209
210 assert(false && "Didn't find this decl on its identifier's chain!");
211}
212
213/// Returns the IdDeclInfo associated to the IdentifierInfo.
214/// It creates a new IdDeclInfo if one was not created before for this id.
215IdDeclInfo &IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
216 assert (II && "null IdentifierInfo passed");
217 void *Ptr = II->getFETokenInfo<void>();
218
219 if (Ptr) {
220 assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken");
221 return *toIdDeclInfo(Ptr);
222 }
223
224 if (CurIndex == ARRAY_SIZE) {
225 CurArr = new IdDeclInfo[ARRAY_SIZE];
226 IDIArrPtrs.push_back(CurArr);
227 CurIndex = 0;
228 }
229 IdDeclInfo *IDI = CurArr + CurIndex;
230 II->setFETokenInfo(reinterpret_cast<void*>(
231 reinterpret_cast<uintptr_t>(IDI) | 0x1)
232 );
233 ++CurIndex;
234 return *IDI;
235}