1 //===- 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 declaration names. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Sema/IdentifierResolver.h" 16 #include "clang/Sema/Scope.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/Basic/LangOptions.h" 19 20 using namespace clang; 21 22 //===----------------------------------------------------------------------===// 23 // IdDeclInfoMap class 24 //===----------------------------------------------------------------------===// 25 26 /// IdDeclInfoMap - Associates IdDeclInfos with declaration names. 27 /// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each 28 /// individual IdDeclInfo to heap. 29 class IdentifierResolver::IdDeclInfoMap { 30 static const unsigned int POOL_SIZE = 512; 31 32 /// We use our own linked-list implementation because it is sadly 33 /// impossible to add something to a pre-C++0x STL container without 34 /// a completely unnecessary copy. 35 struct IdDeclInfoPool { 36 IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {} 37 38 IdDeclInfoPool *Next; 39 IdDeclInfo Pool[POOL_SIZE]; 40 }; 41 42 IdDeclInfoPool *CurPool; 43 unsigned int CurIndex; 44 45 public: 46 IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {} 47 48 ~IdDeclInfoMap() { 49 IdDeclInfoPool *Cur = CurPool; 50 while (IdDeclInfoPool *P = Cur) { 51 Cur = Cur->Next; 52 delete P; 53 } 54 } 55 56 /// Returns the IdDeclInfo associated to the DeclarationName. 57 /// It creates a new IdDeclInfo if one was not created before for this id. 58 IdDeclInfo &operator[](DeclarationName Name); 59 }; 60 61 62 //===----------------------------------------------------------------------===// 63 // IdDeclInfo Implementation 64 //===----------------------------------------------------------------------===// 65 66 /// RemoveDecl - Remove the decl from the scope chain. 67 /// The decl must already be part of the decl chain. 68 void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) { 69 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { 70 if (D == *(I-1)) { 71 Decls.erase(I-1); 72 return; 73 } 74 } 75 76 assert(0 && "Didn't find this decl on its identifier's chain!"); 77 } 78 79 bool 80 IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { 81 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { 82 if (Old == *(I-1)) { 83 *(I - 1) = New; 84 return true; 85 } 86 } 87 88 return false; 89 } 90 91 92 //===----------------------------------------------------------------------===// 93 // IdentifierResolver Implementation 94 //===----------------------------------------------------------------------===// 95 96 IdentifierResolver::IdentifierResolver(const LangOptions &langOpt) 97 : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) { 98 } 99 IdentifierResolver::~IdentifierResolver() { 100 delete IdDeclInfos; 101 } 102 103 /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true 104 /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns 105 /// true if 'D' belongs to the given declaration context. 106 bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, 107 ASTContext &Context, Scope *S) const { 108 Ctx = Ctx->getRedeclContext(); 109 110 if (Ctx->isFunctionOrMethod()) { 111 // Ignore the scopes associated within transparent declaration contexts. 112 while (S->getEntity() && 113 ((DeclContext *)S->getEntity())->isTransparentContext()) 114 S = S->getParent(); 115 116 if (S->isDeclScope(D)) 117 return true; 118 if (LangOpt.CPlusPlus) { 119 // C++ 3.3.2p3: 120 // The name declared in a catch exception-declaration is local to the 121 // handler and shall not be redeclared in the outermost block of the 122 // handler. 123 // C++ 3.3.2p4: 124 // Names declared in the for-init-statement, and in the condition of if, 125 // while, for, and switch statements are local to the if, while, for, or 126 // switch statement (including the controlled statement), and shall not be 127 // redeclared in a subsequent condition of that statement nor in the 128 // outermost block (or, for the if statement, any of the outermost blocks) 129 // of the controlled statement. 130 // 131 assert(S->getParent() && "No TUScope?"); 132 if (S->getParent()->getFlags() & Scope::ControlScope) 133 return S->getParent()->isDeclScope(D); 134 } 135 return false; 136 } 137 138 return D->getDeclContext()->getRedeclContext()->Equals(Ctx); 139 } 140 141 /// AddDecl - Link the decl to its shadowed decl chain. 142 void IdentifierResolver::AddDecl(NamedDecl *D) { 143 DeclarationName Name = D->getDeclName(); 144 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 145 II->setIsFromAST(false); 146 147 void *Ptr = Name.getFETokenInfo<void>(); 148 149 if (!Ptr) { 150 Name.setFETokenInfo(D); 151 return; 152 } 153 154 IdDeclInfo *IDI; 155 156 if (isDeclPtr(Ptr)) { 157 Name.setFETokenInfo(NULL); 158 IDI = &(*IdDeclInfos)[Name]; 159 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); 160 IDI->AddDecl(PrevD); 161 } else 162 IDI = toIdDeclInfo(Ptr); 163 164 IDI->AddDecl(D); 165 } 166 167 /// RemoveDecl - Unlink the decl from its shadowed decl chain. 168 /// The decl must already be part of the decl chain. 169 void IdentifierResolver::RemoveDecl(NamedDecl *D) { 170 assert(D && "null param passed"); 171 DeclarationName Name = D->getDeclName(); 172 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 173 II->setIsFromAST(false); 174 175 void *Ptr = Name.getFETokenInfo<void>(); 176 177 assert(Ptr && "Didn't find this decl on its identifier's chain!"); 178 179 if (isDeclPtr(Ptr)) { 180 assert(D == Ptr && "Didn't find this decl on its identifier's chain!"); 181 Name.setFETokenInfo(NULL); 182 return; 183 } 184 185 return toIdDeclInfo(Ptr)->RemoveDecl(D); 186 } 187 188 bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { 189 assert(Old->getDeclName() == New->getDeclName() && 190 "Cannot replace a decl with another decl of a different name"); 191 192 DeclarationName Name = Old->getDeclName(); 193 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 194 II->setIsFromAST(false); 195 196 void *Ptr = Name.getFETokenInfo<void>(); 197 198 if (!Ptr) 199 return false; 200 201 if (isDeclPtr(Ptr)) { 202 if (Ptr == Old) { 203 Name.setFETokenInfo(New); 204 return true; 205 } 206 return false; 207 } 208 209 return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New); 210 } 211 212 /// begin - Returns an iterator for decls with name 'Name'. 213 IdentifierResolver::iterator 214 IdentifierResolver::begin(DeclarationName Name) { 215 void *Ptr = Name.getFETokenInfo<void>(); 216 if (!Ptr) return end(); 217 218 if (isDeclPtr(Ptr)) 219 return iterator(static_cast<NamedDecl*>(Ptr)); 220 221 IdDeclInfo *IDI = toIdDeclInfo(Ptr); 222 223 IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); 224 if (I != IDI->decls_begin()) 225 return iterator(I-1); 226 // No decls found. 227 return end(); 228 } 229 230 void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, 231 NamedDecl *D) { 232 II->setIsFromAST(false); 233 void *Ptr = II->getFETokenInfo<void>(); 234 235 if (!Ptr) { 236 II->setFETokenInfo(D); 237 return; 238 } 239 240 IdDeclInfo *IDI; 241 242 if (isDeclPtr(Ptr)) { 243 II->setFETokenInfo(NULL); 244 IDI = &(*IdDeclInfos)[II]; 245 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); 246 IDI->AddDecl(PrevD); 247 } else 248 IDI = toIdDeclInfo(Ptr); 249 250 IDI->AddDecl(D); 251 } 252 253 //===----------------------------------------------------------------------===// 254 // IdDeclInfoMap Implementation 255 //===----------------------------------------------------------------------===// 256 257 /// Returns the IdDeclInfo associated to the DeclarationName. 258 /// It creates a new IdDeclInfo if one was not created before for this id. 259 IdentifierResolver::IdDeclInfo & 260 IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { 261 void *Ptr = Name.getFETokenInfo<void>(); 262 263 if (Ptr) return *toIdDeclInfo(Ptr); 264 265 if (CurIndex == POOL_SIZE) { 266 CurPool = new IdDeclInfoPool(CurPool); 267 CurIndex = 0; 268 } 269 IdDeclInfo *IDI = &CurPool->Pool[CurIndex]; 270 Name.setFETokenInfo(reinterpret_cast<void*>( 271 reinterpret_cast<uintptr_t>(IDI) | 0x1) 272 ); 273 ++CurIndex; 274 return *IDI; 275 } 276 277 void IdentifierResolver::iterator::incrementSlowCase() { 278 NamedDecl *D = **this; 279 void *InfoPtr = D->getDeclName().getFETokenInfo<void>(); 280 assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); 281 IdDeclInfo *Info = toIdDeclInfo(InfoPtr); 282 283 BaseIter I = getIterator(); 284 if (I != Info->decls_begin()) 285 *this = iterator(I-1); 286 else // No more decls. 287 *this = iterator(); 288 } 289