Merge remote-tracking branch 'origin/master' into master-next

This commit is contained in:
swift-ci
2019-08-29 16:50:55 -07:00
23 changed files with 254 additions and 617 deletions

View File

@@ -1375,88 +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;
}
bool
ModuleDecl::forAllVisibleModules(AccessPathTy thisPath,
llvm::function_ref<bool(ImportedModule)> fn) const {
return forAllImportedModules<true>(this, thisPath, fn);
}
bool FileUnit::forAllVisibleModules(
llvm::function_ref<bool(ModuleDecl::ImportedModule)> fn) const {
if (!getParentModule()->forAllVisibleModules(ModuleDecl::AccessPathTy(), fn))
return false;
if (auto SF = dyn_cast<SourceFile>(this)) {
// Handle privately visible modules as well.
ModuleDecl::ImportFilter importFilter;
importFilter |= ModuleDecl::ImportFilterKind::Private;
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
SmallVector<ModuleDecl::ImportedModule, 4> imports;
SF->getImportedModules(imports, importFilter);
for (auto importPair : imports)
if (!importPair.second->forAllVisibleModules(importPair.first, fn))
return false;
}
return true;
}
void ModuleDecl::collectLinkLibraries(LinkLibraryCallback callback) const {
// FIXME: The proper way to do this depends on the decls used.
FORWARD(collectLinkLibraries, (callback));
@@ -1464,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) {