IdentifierResolver.cpp revision f4bae14c1c2cb086d42aecf84c6779787c6c7d89
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/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(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(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 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 143 II->setIsFromAST(false); 144 145 void *Ptr = Name.getFETokenInfo<void>(); 146 147 if (!Ptr) { 148 Name.setFETokenInfo(D); 149 return; 150 } 151 152 IdDeclInfo *IDI; 153 154 if (isDeclPtr(Ptr)) { 155 Name.setFETokenInfo(NULL); 156 IDI = &(*IdDeclInfos)[Name]; 157 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); 158 IDI->AddDecl(PrevD); 159 } else 160 IDI = toIdDeclInfo(Ptr); 161 162 IDI->AddDecl(D); 163} 164 165/// RemoveDecl - Unlink the decl from its shadowed decl chain. 166/// The decl must already be part of the decl chain. 167void IdentifierResolver::RemoveDecl(NamedDecl *D) { 168 assert(D && "null param passed"); 169 DeclarationName Name = D->getDeclName(); 170 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 171 II->setIsFromAST(false); 172 173 void *Ptr = Name.getFETokenInfo<void>(); 174 175 assert(Ptr && "Didn't find this decl on its identifier's chain!"); 176 177 if (isDeclPtr(Ptr)) { 178 assert(D == Ptr && "Didn't find this decl on its identifier's chain!"); 179 Name.setFETokenInfo(NULL); 180 return; 181 } 182 183 return toIdDeclInfo(Ptr)->RemoveDecl(D); 184} 185 186bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { 187 assert(Old->getDeclName() == New->getDeclName() && 188 "Cannot replace a decl with another decl of a different name"); 189 190 DeclarationName Name = Old->getDeclName(); 191 if (IdentifierInfo *II = Name.getAsIdentifierInfo()) 192 II->setIsFromAST(false); 193 194 void *Ptr = Name.getFETokenInfo<void>(); 195 196 if (!Ptr) 197 return false; 198 199 if (isDeclPtr(Ptr)) { 200 if (Ptr == Old) { 201 Name.setFETokenInfo(New); 202 return true; 203 } 204 return false; 205 } 206 207 return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New); 208} 209 210/// begin - Returns an iterator for decls with name 'Name'. 211IdentifierResolver::iterator 212IdentifierResolver::begin(DeclarationName Name) { 213 void *Ptr = Name.getFETokenInfo<void>(); 214 if (!Ptr) return end(); 215 216 if (isDeclPtr(Ptr)) 217 return iterator(static_cast<NamedDecl*>(Ptr)); 218 219 IdDeclInfo *IDI = toIdDeclInfo(Ptr); 220 221 IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); 222 if (I != IDI->decls_begin()) 223 return iterator(I-1); 224 // No decls found. 225 return end(); 226} 227 228void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, 229 NamedDecl *D) { 230 II->setIsFromAST(false); 231 void *Ptr = II->getFETokenInfo<void>(); 232 233 if (!Ptr) { 234 II->setFETokenInfo(D); 235 return; 236 } 237 238 IdDeclInfo *IDI; 239 240 if (isDeclPtr(Ptr)) { 241 II->setFETokenInfo(NULL); 242 IDI = &(*IdDeclInfos)[II]; 243 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); 244 IDI->AddDecl(PrevD); 245 } else 246 IDI = toIdDeclInfo(Ptr); 247 248 IDI->AddDecl(D); 249} 250 251//===----------------------------------------------------------------------===// 252// IdDeclInfoMap Implementation 253//===----------------------------------------------------------------------===// 254 255/// Returns the IdDeclInfo associated to the DeclarationName. 256/// It creates a new IdDeclInfo if one was not created before for this id. 257IdentifierResolver::IdDeclInfo & 258IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { 259 void *Ptr = Name.getFETokenInfo<void>(); 260 261 if (Ptr) return *toIdDeclInfo(Ptr); 262 263 if (CurIndex == POOL_SIZE) { 264 CurPool = new IdDeclInfoPool(CurPool); 265 CurIndex = 0; 266 } 267 IdDeclInfo *IDI = &CurPool->Pool[CurIndex]; 268 Name.setFETokenInfo(reinterpret_cast<void*>( 269 reinterpret_cast<uintptr_t>(IDI) | 0x1) 270 ); 271 ++CurIndex; 272 return *IDI; 273} 274