Skip to content

Commit b4b8778

Browse files
committed
Fixup getOverlayModule
ClangModuleUnit::getOverlayModule implies that it requests the Swift module with the same name as the top level module, and loads it if it is available. Unfortunately, it used ASTContext::getModule to do so, which consults every module loader, including the clang importer. So, even though you couldn't actually get a clang module out at the end of the day, you could still force a clang module to load implicitly. When combined with namelookup's import graph computation forcing overlays, this meant the entire transitive import graph would be loaded because of the complicated mix of recursion and re-entrancy this created. The first step in teasing this apart is to define an API that doesn't re-enter the clang importer when it loads modules. Then, the callers that were relying on this need to be updated to explicitly call ASTContext::getModule themselves. This will also fix rdar://70745521 by happenstance.
1 parent 7b3130b commit b4b8778

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,13 @@ class ASTContext final {
909909
/// \returns The requested module, or NULL if the module cannot be found.
910910
ModuleDecl *getModule(ImportPath::Module ModulePath);
911911

912+
/// Attempts to load the matching overlay module for the given clang
913+
/// module into this ASTContext.
914+
///
915+
/// \returns The Swift overlay module corresponding to the given Clang module,
916+
/// or NULL if the overlay module cannot be found.
917+
ModuleDecl *getOverlayModule(const FileUnit *ClangModule);
918+
912919
ModuleDecl *getModuleByName(StringRef ModuleName);
913920

914921
ModuleDecl *getModuleByIdentifier(Identifier ModuleID);

lib/AST/ASTContext.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,27 @@ ASTContext::getModule(ImportPath::Module ModulePath) {
19281928
return nullptr;
19291929
}
19301930

1931+
ModuleDecl *ASTContext::getOverlayModule(const FileUnit *FU) {
1932+
assert(FU && FU->getKind() == FileUnitKind::ClangModule &&
1933+
"Overlays can only be retrieved for clang modules!");
1934+
ImportPath::Module::Builder builder(FU->getParentModule()->getName());
1935+
auto ModPath = builder.get();
1936+
if (auto *Existing = getLoadedModule(ModPath)) {
1937+
if (!Existing->isNonSwiftModule())
1938+
return Existing;
1939+
}
1940+
1941+
for (auto &importer : getImpl().ModuleLoaders) {
1942+
if (importer.get() == getClangModuleLoader())
1943+
continue;
1944+
if (ModuleDecl *M = importer->loadModule(SourceLoc(), ModPath)) {
1945+
return M;
1946+
}
1947+
}
1948+
1949+
return nullptr;
1950+
}
1951+
19311952
ModuleDecl *ASTContext::getModuleByName(StringRef ModuleName) {
19321953
ImportPath::Module::Builder builder(*this, ModuleName, /*separator=*/'.');
19331954
return getModule(builder.get());

lib/ClangImporter/ClangImporter.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3425,18 +3425,23 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
34253425
// FIXME: Include proper source location.
34263426
ModuleDecl *M = getParentModule();
34273427
ASTContext &Ctx = M->getASTContext();
3428-
auto overlay = Ctx.getModuleByIdentifier(M->getName());
3429-
if (overlay == M) {
3430-
overlay = nullptr;
3431-
} else {
3432-
// FIXME: This bizarre and twisty invariant is due to nested
3433-
// re-entrancy in both clang module loading and overlay module loading.
3434-
auto *sharedModuleRef = Ctx.getLoadedModule(M->getName());
3435-
assert(!sharedModuleRef || sharedModuleRef == overlay ||
3436-
sharedModuleRef == M);
3428+
auto overlay = Ctx.getOverlayModule(this);
3429+
if (overlay) {
34373430
Ctx.addLoadedModule(overlay);
3431+
} else {
3432+
// FIXME: This is the awful legacy of the old implementation of overlay
3433+
// loading laid bare. Because the previous implementation used
3434+
// ASTContext::getModuleByIdentifier, it consulted the clang importer
3435+
// recursively which forced the current module, its dependencies, and
3436+
// the overlays of those dependencies to load and
3437+
// become visible in the current context. All of the callers of
3438+
// ClangModuleUnit::getOverlayModule are relying on this behavior, and
3439+
// untangling them is going to take a heroic amount of effort.
3440+
// Clang module loading should *never* *ever* be allowed to load unrelated
3441+
// Swift modules.
3442+
ImportPath::Module::Builder builder(M->getName());
3443+
(void) owner.loadModule(SourceLoc(), std::move(builder).get());
34383444
}
3439-
34403445
auto mutableThis = const_cast<ClangModuleUnit *>(this);
34413446
mutableThis->overlayModule.setPointerAndInt(overlay, true);
34423447
}

0 commit comments

Comments
 (0)