aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-08-24 21:27:34 +0000
committerDouglas Gregor <dgregor@apple.com>2011-08-24 21:27:34 +0000
commit851c75a279bb4441bc6802d0258ceb4ab64738d4 (patch)
tree5df49171adc9505b03a6497b7a00abc079352266 /lib/Serialization
parentbba43efdec3b2aa483b55d4287ba1c48c55935d4 (diff)
Introduce a depth-first search of modules into the module manager,
which supports both pre-order and post-order traversal via a visitor mechanism. Use this depth-first search with a post-order traversal to give predictable ordering semantics when walking all of the lexical declarations in the translation unit. Eventually, module imports will occur in the source code rather than at the beginning, and we'll have to revisit this walk. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138490 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization')
-rw-r--r--lib/Serialization/ASTReader.cpp121
1 files changed, 97 insertions, 24 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 8264a7421c..0a2992baa5 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4264,34 +4264,69 @@ Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
return ReadStmtFromStream(*Loc.F);
}
+namespace {
+ class FindExternalLexicalDeclsVisitor {
+ ASTReader &Reader;
+ const DeclContext *DC;
+ bool (*isKindWeWant)(Decl::Kind);
+ SmallVectorImpl<Decl*> &Decls;
+ bool PredefsVisited[NUM_PREDEF_DECL_IDS];
+
+ public:
+ FindExternalLexicalDeclsVisitor(ASTReader &Reader, const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ SmallVectorImpl<Decl*> &Decls)
+ : Reader(Reader), DC(DC), isKindWeWant(isKindWeWant), Decls(Decls)
+ {
+ for (unsigned I = 0; I != NUM_PREDEF_DECL_IDS; ++I)
+ PredefsVisited[I] = false;
+ }
+
+ static bool visit(Module &M, bool Preorder, void *UserData) {
+ if (Preorder)
+ return false;
+
+ FindExternalLexicalDeclsVisitor *This
+ = static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
+
+ Module::DeclContextInfosMap::iterator Info
+ = M.DeclContextInfos.find(This->DC);
+ if (Info == M.DeclContextInfos.end() || !Info->second.LexicalDecls)
+ return false;
+
+ // Load all of the declaration IDs
+ for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
+ *IDE = ID + Info->second.NumLexicalDecls;
+ ID != IDE; ++ID) {
+ if (This->isKindWeWant && !This->isKindWeWant((Decl::Kind)ID->first))
+ continue;
+
+ // Don't add predefined declarations to the lexical context more
+ // than once.
+ if (ID->second < NUM_PREDEF_DECL_IDS) {
+ if (This->PredefsVisited[ID->second])
+ continue;
+
+ This->PredefsVisited[ID->second] = true;
+ }
+
+ Decl *D = This->Reader.GetLocalDecl(M, ID->second);
+ assert(D && "Null decl in lexical decls");
+ This->Decls.push_back(D);
+ }
+
+ return false;
+ }
+ };
+}
+
ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
bool (*isKindWeWant)(Decl::Kind),
SmallVectorImpl<Decl*> &Decls) {
// There might be lexical decls in multiple modules, for the TU at
- // least.
- // FIXME: We might want a faster way to zero
- // FIXME: Going backwards through the chain does the right thing for
- // chained PCH; for modules, it isn't clear what the right thing is.
- for (ModuleReverseIterator M = ModuleMgr.rbegin(), MEnd = ModuleMgr.rend();
- M != MEnd; ++M) {
- Module::DeclContextInfosMap::iterator Info
- = (*M)->DeclContextInfos.find(DC);
- if (Info == (*M)->DeclContextInfos.end() || !Info->second.LexicalDecls)
- continue;
-
- // Load all of the declaration IDs
- for (const KindDeclIDPair *ID = Info->second.LexicalDecls,
- *IDE = ID + Info->second.NumLexicalDecls;
- ID != IDE; ++ID) {
- if (isKindWeWant && !isKindWeWant((Decl::Kind)ID->first))
- continue;
-
- Decl *D = GetLocalDecl(**M, ID->second);
- assert(D && "Null decl in lexical decls");
- Decls.push_back(D);
- }
- }
-
+ // least. Walk all of the modules in the order they were loaded.
+ FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
+ ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
++NumLexicalDeclContextsRead;
return ELR_Success;
}
@@ -5888,3 +5923,41 @@ void ModuleManager::visit(bool (*Visitor)(Module &M, void *UserData),
}
}
}
+
+/// \brief Perform a depth-first visit of the current module.
+static bool visitDepthFirst(Module &M,
+ bool (*Visitor)(Module &M, bool Preorder,
+ void *UserData),
+ void *UserData,
+ llvm::SmallPtrSet<Module *, 4> &Visited) {
+ // Preorder visitation
+ if (Visitor(M, /*Preorder=*/true, UserData))
+ return true;
+
+ // Visit children
+ for (llvm::SetVector<Module *>::iterator IM = M.Imports.begin(),
+ IMEnd = M.Imports.end();
+ IM != IMEnd; ++IM) {
+ if (!Visited.insert(*IM))
+ continue;
+
+ if (visitDepthFirst(**IM, Visitor, UserData, Visited))
+ return true;
+ }
+
+ // Postorder visitation
+ return Visitor(M, /*Preorder=*/false, UserData);
+}
+
+void ModuleManager::visitDepthFirst(bool (*Visitor)(Module &M, bool Preorder,
+ void *UserData),
+ void *UserData) {
+ llvm::SmallPtrSet<Module *, 4> Visited;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ if (!Visited.insert(Chain[I]))
+ continue;
+
+ if (::visitDepthFirst(*Chain[I], Visitor, UserData, Visited))
+ return;
+ }
+}