AST: Fold forAllImportedModules() into collectLinkLibraries()

This commit is contained in:
Slava Pestov
2019-08-27 13:56:37 -04:00
parent 2256b1fcc2
commit 3956fc0653

View File

@@ -1375,62 +1375,6 @@ bool ModuleDecl::registerEntryPointFile(FileUnit *file, SourceLoc diagLoc,
return true;
}
template<bool respectVisibility>
static bool
forAllImportedModules(const ModuleDecl *topLevel,
ModuleDecl::AccessPathTy thisPath,
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn) {
using ImportedModule = ModuleDecl::ImportedModule;
using AccessPathTy = ModuleDecl::AccessPathTy;
llvm::SmallSet<ImportedModule, 32, ModuleDecl::OrderImportedModules> visited;
SmallVector<ImportedModule, 32> stack;
ModuleDecl::ImportFilter filter = ModuleDecl::ImportFilterKind::Public;
if (!respectVisibility)
filter |= ModuleDecl::ImportFilterKind::Private;
ModuleDecl::ImportFilter topLevelFilter = filter;
if (!respectVisibility)
topLevelFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
topLevel->getImportedModules(stack, topLevelFilter);
// Make sure the top-level module is first; we want pre-order-ish traversal.
AccessPathTy overridingPath;
if (respectVisibility)
overridingPath = thisPath;
stack.emplace_back(overridingPath, const_cast<ModuleDecl *>(topLevel));
while (!stack.empty()) {
auto next = stack.pop_back_val();
// Filter any whole-module imports, and skip specific-decl imports if the
// import path doesn't match exactly.
if (next.first.empty() || !respectVisibility)
next.first = overridingPath;
else if (!overridingPath.empty() &&
!ModuleDecl::isSameAccessPath(next.first, overridingPath)) {
// If we ever allow importing non-top-level decls, it's possible the rule
// above isn't what we want.
assert(next.first.size() == 1 && "import of non-top-level decl");
continue;
}
if (!visited.insert(next).second)
continue;
if (!fn(next))
return false;
if (respectVisibility)
next.second->getImportedModulesForLookup(stack);
else
next.second->getImportedModules(stack, filter);
}
return true;
}
void ModuleDecl::collectLinkLibraries(LinkLibraryCallback callback) const {
// FIXME: The proper way to do this depends on the decls used.
FORWARD(collectLinkLibraries, (callback));
@@ -1438,21 +1382,40 @@ void ModuleDecl::collectLinkLibraries(LinkLibraryCallback callback) const {
void
SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const {
forAllImportedModules<false>(getParentModule(), /*thisPath*/{},
[=](ModuleDecl::ImportedModule import) -> bool {
swift::ModuleDecl *next = import.second;
if (next->getName() == getParentModule()->getName())
return true;
llvm::SmallDenseSet<ModuleDecl *, 32> visited;
SmallVector<ModuleDecl::ImportedModule, 32> stack;
// Hack: Assume other REPL files already have their libraries linked.
if (!next->getFiles().empty())
if (auto *nextSource = dyn_cast<SourceFile>(next->getFiles().front()))
if (nextSource->Kind == SourceFileKind::REPL)
return true;
ModuleDecl::ImportFilter filter = ModuleDecl::ImportFilterKind::Public;
filter |= ModuleDecl::ImportFilterKind::Private;
next->collectLinkLibraries(callback);
return true;
});
auto *topLevel = getParentModule();
ModuleDecl::ImportFilter topLevelFilter = filter;
topLevelFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
topLevel->getImportedModules(stack, topLevelFilter);
// Make sure the top-level module is first; we want pre-order-ish traversal.
stack.emplace_back(ModuleDecl::AccessPathTy(),
const_cast<ModuleDecl *>(topLevel));
while (!stack.empty()) {
auto next = stack.pop_back_val().second;
if (!visited.insert(next).second)
continue;
if (next->getName() != getParentModule()->getName()) {
// Hack: Assume other REPL files already have their libraries linked.
if (!next->getFiles().empty())
if (auto *nextSource = dyn_cast<SourceFile>(next->getFiles().front()))
if (nextSource->Kind == SourceFileKind::REPL)
continue;
next->collectLinkLibraries(callback);
}
next->getImportedModules(stack, filter);
}
}
bool ModuleDecl::walk(ASTWalker &Walker) {