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