summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/IdentifierResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/IdentifierResolver.cpp')
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp444
1 files changed, 444 insertions, 0 deletions
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
new file mode 100644
index 0000000..4d62cab
--- /dev/null
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -0,0 +1,444 @@
+//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap class
+//===----------------------------------------------------------------------===//
+
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
+/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
+/// individual IdDeclInfo to heap.
+class IdentifierResolver::IdDeclInfoMap {
+ static const unsigned int POOL_SIZE = 512;
+
+ /// We use our own linked-list implementation because it is sadly
+ /// impossible to add something to a pre-C++0x STL container without
+ /// a completely unnecessary copy.
+ struct IdDeclInfoPool {
+ IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
+
+ IdDeclInfoPool *Next;
+ IdDeclInfo Pool[POOL_SIZE];
+ };
+
+ IdDeclInfoPool *CurPool;
+ unsigned int CurIndex;
+
+public:
+ IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
+
+ ~IdDeclInfoMap() {
+ IdDeclInfoPool *Cur = CurPool;
+ while (IdDeclInfoPool *P = Cur) {
+ Cur = Cur->Next;
+ delete P;
+ }
+ }
+
+ /// Returns the IdDeclInfo associated to the DeclarationName.
+ /// It creates a new IdDeclInfo if one was not created before for this id.
+ IdDeclInfo &operator[](DeclarationName Name);
+};
+
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfo Implementation
+//===----------------------------------------------------------------------===//
+
+/// RemoveDecl - Remove the decl from the scope chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (D == *(I-1)) {
+ Decls.erase(I-1);
+ return;
+ }
+ }
+
+ llvm_unreachable("Didn't find this decl on its identifier's chain!");
+}
+
+bool
+IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (Old == *(I-1)) {
+ *(I - 1) = New;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// IdentifierResolver Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierResolver::IdentifierResolver(Preprocessor &PP)
+ : LangOpt(PP.getLangOpts()), PP(PP),
+ IdDeclInfos(new IdDeclInfoMap) {
+}
+
+IdentifierResolver::~IdentifierResolver() {
+ delete IdDeclInfos;
+}
+
+/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+/// true if 'D' belongs to the given declaration context.
+bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
+ ASTContext &Context, Scope *S,
+ bool ExplicitInstantiationOrSpecialization) const {
+ Ctx = Ctx->getRedeclContext();
+
+ if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
+ // Ignore the scopes associated within transparent declaration contexts.
+ while (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext())
+ S = S->getParent();
+
+ if (S->isDeclScope(D))
+ return true;
+ if (LangOpt.CPlusPlus) {
+ // C++ 3.3.2p3:
+ // The name declared in a catch exception-declaration is local to the
+ // handler and shall not be redeclared in the outermost block of the
+ // handler.
+ // C++ 3.3.2p4:
+ // Names declared in the for-init-statement, and in the condition of if,
+ // while, for, and switch statements are local to the if, while, for, or
+ // switch statement (including the controlled statement), and shall not be
+ // redeclared in a subsequent condition of that statement nor in the
+ // outermost block (or, for the if statement, any of the outermost blocks)
+ // of the controlled statement.
+ //
+ assert(S->getParent() && "No TUScope?");
+ if (S->getParent()->getFlags() & Scope::ControlScope)
+ return S->getParent()->isDeclScope(D);
+ }
+ return false;
+ }
+
+ DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
+ return ExplicitInstantiationOrSpecialization
+ ? Ctx->InEnclosingNamespaceSetOf(DCtx)
+ : Ctx->Equals(DCtx);
+}
+
+/// AddDecl - Link the decl to its shadowed decl chain.
+void IdentifierResolver::AddDecl(NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ updatingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr) {
+ Name.setFETokenInfo(D);
+ return;
+ }
+
+ IdDeclInfo *IDI;
+
+ if (isDeclPtr(Ptr)) {
+ Name.setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[Name];
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ IDI->AddDecl(PrevD);
+ } else
+ IDI = toIdDeclInfo(Ptr);
+
+ IDI->AddDecl(D);
+}
+
+void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
+ DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ updatingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr) {
+ AddDecl(D);
+ return;
+ }
+
+ if (isDeclPtr(Ptr)) {
+ // We only have a single declaration: insert before or after it,
+ // as appropriate.
+ if (Pos == iterator()) {
+ // Add the new declaration before the existing declaration.
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ RemoveDecl(PrevD);
+ AddDecl(D);
+ AddDecl(PrevD);
+ } else {
+ // Add new declaration after the existing declaration.
+ AddDecl(D);
+ }
+
+ return;
+ }
+
+ // General case: insert the declaration at the appropriate point in the
+ // list, which already has at least two elements.
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ if (Pos.isIterator()) {
+ IDI->InsertDecl(Pos.getIterator() + 1, D);
+ } else
+ IDI->InsertDecl(IDI->decls_begin(), D);
+}
+
+/// RemoveDecl - Unlink the decl from its shadowed decl chain.
+/// The decl must already be part of the decl chain.
+void IdentifierResolver::RemoveDecl(NamedDecl *D) {
+ assert(D && "null param passed");
+ DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ updatingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ assert(Ptr && "Didn't find this decl on its identifier's chain!");
+
+ if (isDeclPtr(Ptr)) {
+ assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
+ Name.setFETokenInfo(NULL);
+ return;
+ }
+
+ return toIdDeclInfo(Ptr)->RemoveDecl(D);
+}
+
+bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
+ assert(Old->getDeclName() == New->getDeclName() &&
+ "Cannot replace a decl with another decl of a different name");
+
+ DeclarationName Name = Old->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ updatingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr)
+ return false;
+
+ if (isDeclPtr(Ptr)) {
+ if (Ptr == Old) {
+ Name.setFETokenInfo(New);
+ return true;
+ }
+ return false;
+ }
+
+ return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
+}
+
+/// begin - Returns an iterator for decls with name 'Name'.
+IdentifierResolver::iterator
+IdentifierResolver::begin(DeclarationName Name) {
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ readingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+ if (!Ptr) return end();
+
+ if (isDeclPtr(Ptr))
+ return iterator(static_cast<NamedDecl*>(Ptr));
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+
+ IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
+ if (I != IDI->decls_begin())
+ return iterator(I-1);
+ // No decls found.
+ return end();
+}
+
+namespace {
+ enum DeclMatchKind {
+ DMK_Different,
+ DMK_Replace,
+ DMK_Ignore
+ };
+}
+
+/// \brief Compare two declarations to see whether they are different or,
+/// if they are the same, whether the new declaration should replace the
+/// existing declaration.
+static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
+ // If the declarations are identical, ignore the new one.
+ if (Existing == New)
+ return DMK_Ignore;
+
+ // If the declarations have different kinds, they're obviously different.
+ if (Existing->getKind() != New->getKind())
+ return DMK_Different;
+
+ // If the declarations are redeclarations of each other, keep the newest one.
+ if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
+ // If the existing declaration is somewhere in the previous declaration
+ // chain of the new declaration, then prefer the new declaration.
+ for (Decl::redecl_iterator RD = New->redecls_begin(),
+ RDEnd = New->redecls_end();
+ RD != RDEnd; ++RD) {
+ if (*RD == Existing)
+ return DMK_Replace;
+
+ if (RD->isCanonicalDecl())
+ break;
+ }
+
+ return DMK_Ignore;
+ }
+
+ return DMK_Different;
+}
+
+bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ readingIdentifier(*II);
+
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (!Ptr) {
+ Name.setFETokenInfo(D);
+ return true;
+ }
+
+ IdDeclInfo *IDI;
+
+ if (isDeclPtr(Ptr)) {
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+
+ switch (compareDeclarations(PrevD, D)) {
+ case DMK_Different:
+ break;
+
+ case DMK_Ignore:
+ return false;
+
+ case DMK_Replace:
+ Name.setFETokenInfo(D);
+ return true;
+ }
+
+ Name.setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[Name];
+
+ // If the existing declaration is not visible in translation unit scope,
+ // then add the new top-level declaration first.
+ if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+ IDI->AddDecl(D);
+ IDI->AddDecl(PrevD);
+ } else {
+ IDI->AddDecl(PrevD);
+ IDI->AddDecl(D);
+ }
+ return true;
+ }
+
+ IDI = toIdDeclInfo(Ptr);
+
+ // See whether this declaration is identical to any existing declarations.
+ // If not, find the right place to insert it.
+ for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
+ IEnd = IDI->decls_end();
+ I != IEnd; ++I) {
+
+ switch (compareDeclarations(*I, D)) {
+ case DMK_Different:
+ break;
+
+ case DMK_Ignore:
+ return false;
+
+ case DMK_Replace:
+ *I = D;
+ return true;
+ }
+
+ if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
+ // We've found a declaration that is not visible from the translation
+ // unit (it's in an inner scope). Insert our declaration here.
+ IDI->InsertDecl(I, D);
+ return true;
+ }
+ }
+
+ // Add the declaration to the end.
+ IDI->AddDecl(D);
+ return true;
+}
+
+void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
+ if (II.isOutOfDate())
+ PP.getExternalSource()->updateOutOfDateIdentifier(II);
+}
+
+void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
+ if (II.isOutOfDate())
+ PP.getExternalSource()->updateOutOfDateIdentifier(II);
+
+ if (II.isFromAST())
+ II.setChangedSinceDeserialization();
+}
+
+//===----------------------------------------------------------------------===//
+// IdDeclInfoMap Implementation
+//===----------------------------------------------------------------------===//
+
+/// Returns the IdDeclInfo associated to the DeclarationName.
+/// It creates a new IdDeclInfo if one was not created before for this id.
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+ void *Ptr = Name.getFETokenInfo<void>();
+
+ if (Ptr) return *toIdDeclInfo(Ptr);
+
+ if (CurIndex == POOL_SIZE) {
+ CurPool = new IdDeclInfoPool(CurPool);
+ CurIndex = 0;
+ }
+ IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
+ Name.setFETokenInfo(reinterpret_cast<void*>(
+ reinterpret_cast<uintptr_t>(IDI) | 0x1)
+ );
+ ++CurIndex;
+ return *IDI;
+}
+
+void IdentifierResolver::iterator::incrementSlowCase() {
+ NamedDecl *D = **this;
+ void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+ assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+ IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+
+ BaseIter I = getIterator();
+ if (I != Info->decls_begin())
+ *this = iterator(I-1);
+ else // No more decls.
+ *this = iterator();
+}