diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-15 00:10:27 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-15 00:10:27 +0000 |
commit | b75a3451bcae1301875282e73a13934c90b6574c (patch) | |
tree | 7eacc3951cdcb53eec7152408fb3412092415104 | |
parent | fd5f6866a7574f12ecac5cceb7359ff253f83145 (diff) |
Teach the ASTImporter to perform DeclContext lookups in a way that
avoids loading data from an external source, since those lookups were
causing some "interesting" recursion in LLDB.
This code is not efficient. I plan to remedy this inefficiency in a
follow-up commit.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142023 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclBase.h | 9 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 154 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 32 |
3 files changed, 118 insertions, 77 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 25a103a767..9f29411768 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -1262,6 +1262,15 @@ public: lookup_result lookup(DeclarationName Name); lookup_const_result lookup(DeclarationName Name) const; + /// \brief A simplistic name lookup mechanism that performs name lookup + /// into this declaration context without consulting the external source. + /// + /// This function should almost never be used, because it subverts the + /// usual relationship between a DeclContext and the external source. + /// See the ASTImporter for the (few, but important) use cases. + void localUncachedLookup(DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl *> &Results); + /// @brief Makes a declaration visible within this context. /// /// This routine makes the declaration D visible to name lookup diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 3db75bacbf..af66b04c3a 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2048,19 +2048,19 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); } else { SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; - if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) { + if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(FoundDecls[I])) { MergeWithNamespace = FoundNS; ConflictingDecls.clear(); break; } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2109,19 +2109,19 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; if (TypedefNameDecl *FoundTypedef = - dyn_cast<TypedefNameDecl>(*Lookup.first)) { + dyn_cast<TypedefNameDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2189,13 +2189,13 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(SearchName); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(SearchName, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); @@ -2206,7 +2206,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { return Importer.Imported(D, FoundEnum); } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2275,13 +2275,13 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { RecordDecl *AdoptDecl = 0; if (!DC->isFunctionOrMethod() && SearchName) { SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(SearchName); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(SearchName, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); @@ -2304,7 +2304,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2360,13 +2360,13 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2406,13 +2406,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(*Lookup.first)) { + if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) { if (isExternalLinkage(FoundFunction->getLinkage()) && isExternalLinkage(D->getLinkage())) { if (Importer.IsStructurallyEquivalent(D->getType(), @@ -2437,7 +2437,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { @@ -2567,10 +2567,10 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return 0; // Determine whether we've already imported this field. - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (FieldDecl *FoundField = dyn_cast<FieldDecl>(*Lookup.first)) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { Importer.Imported(D, FoundField); @@ -2618,11 +2618,11 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { return 0; // Determine whether we've already imported this field. - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (IndirectFieldDecl *FoundField - = dyn_cast<IndirectFieldDecl>(*Lookup.first)) { + = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { Importer.Imported(D, FoundField); @@ -2674,10 +2674,10 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { return 0; // Determine whether we've already imported this ivar - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(*Lookup.first)) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { Importer.Imported(D, FoundIvar); @@ -2729,13 +2729,13 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { VarDecl *MergeWithVar = 0; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) continue; - if (VarDecl *FoundVar = dyn_cast<VarDecl>(*Lookup.first)) { + if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) { // We have found a variable that we may need to merge with. Check it. if (isExternalLinkage(FoundVar->getLinkage()) && isExternalLinkage(D->getLinkage())) { @@ -2774,7 +2774,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (MergeWithVar) { @@ -2900,10 +2900,10 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) return 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(*Lookup.first)) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) { if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) continue; @@ -3093,13 +3093,13 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { return 0; ObjCProtocolDecl *MergeWithProtocol = 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) continue; - if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(*Lookup.first))) + if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecls[I]))) break; } @@ -3154,13 +3154,13 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { return 0; ObjCInterfaceDecl *MergeWithIface = 0; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(*Lookup.first))) + if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecls[I]))) break; } @@ -3385,11 +3385,11 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return 0; // Check whether we have already imported this property. - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (ObjCPropertyDecl *FoundProp - = dyn_cast<ObjCPropertyDecl>(*Lookup.first)) { + = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) { // Check property types. if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { @@ -3690,13 +3690,13 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - for (DeclContext::lookup_result Lookup = DC->lookup(Name); - Lookup.first != Lookup.second; - ++Lookup.first) { - if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + llvm::SmallVector<NamedDecl *, 2> FoundDecls; + DC->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - Decl *Found = *Lookup.first; + Decl *Found = FoundDecls[I]; if (ClassTemplateDecl *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { @@ -3709,7 +3709,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { } } - ConflictingDecls.push_back(*Lookup.first); + ConflictingDecls.push_back(FoundDecls[I]); } if (!ConflictingDecls.empty()) { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 844a39361b..321e40b438 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -1081,6 +1081,38 @@ DeclContext::lookup(DeclarationName Name) const { return const_cast<DeclContext*>(this)->lookup(Name); } +void DeclContext::localUncachedLookup(DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl *> &Results) { + Results.clear(); + + // If there's no external storage, just perform a normal lookup and copy + // the results. + if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage()) { + lookup_result LookupResults = lookup(Name); + Results.insert(Results.end(), LookupResults.first, LookupResults.second); + return; + } + + // If we have a lookup table, check there first. Maybe we'll get lucky. + if (LookupPtr) { + StoredDeclsMap::iterator Pos = LookupPtr->find(Name); + if (Pos != LookupPtr->end()) { + Results.insert(Results.end(), + Pos->second.getLookupResult().first, + Pos->second.getLookupResult().second); + return; + } + } + + // Slow case: grovel through the declarations in our chain looking for + // matches. + for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (ND->getDeclName() == Name) + Results.push_back(ND); + } +} + DeclContext *DeclContext::getRedeclContext() { DeclContext *Ctx = this; // Skip through transparent contexts. |