Skip to content

Commit 5577df7

Browse files
committed
[Implicit Module Builds] Do not query CxxStdlib Swift overlay for textual modules which were not built with c++interop
When the compiler is building a module without a defined formal C++ interop mode (e.g. building a textual interface which specifies it was built without C++ interop enabled), avoid looking up the C++ standard library Swift overlay for it. This is required for the case of the Darwin module, for example, which includes headers which map to C++ stdlib headers when the compiler is operating in C++ interop mode, but the C++ standard library Swift overlay module itself depends on 'Darwin', which results in a cycle. To resolve such situations, we can rely on the fact that Swift textual interfaces of modules which were not built with C++ interop must be able to build without importing the C++ standard library Swift overlay, so we avoid specifying it as a dependency for such modules. The primary source module, as well as Swift textual module dependencies which were built with C++ interop will continue getting a direct depedency of the 'CxxStdlib' Swift module. This was previously fixed in the dependency scanner for explicitly-built modules in #81415.
1 parent 7d6447b commit 5577df7

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4388,7 +4388,14 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
43884388
// FIXME: Include proper source location.
43894389
ModuleDecl *M = getParentModule();
43904390
ASTContext &Ctx = M->getASTContext();
4391-
auto overlay = Ctx.getOverlayModule(this);
4391+
4392+
ModuleDecl *overlay = nullptr;
4393+
// During compilation of a textual interface with no formal C++ interop mode,
4394+
// i.e. it was built without C++ interop, avoid querying the 'CxxStdlib' overlay
4395+
// for it, since said overlay was not used during compilation of this module.
4396+
if (!importer::isCxxStdModule(clangModule) || Ctx.LangOpts.FormalCxxInteropMode)
4397+
overlay = Ctx.getOverlayModule(this);
4398+
43924399
if (overlay) {
43934400
Ctx.addLoadedModule(overlay);
43944401
} else {
@@ -4408,7 +4415,8 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
44084415
// If this Clang module is a part of the C++ stdlib, and we haven't loaded
44094416
// the overlay for it so far, it is a split libc++ module (e.g. std_vector).
44104417
// Load the CxxStdlib overlay explicitly.
4411-
if (!overlay && importer::isCxxStdModule(clangModule)) {
4418+
if (!overlay && importer::isCxxStdModule(clangModule) &&
4419+
Ctx.LangOpts.FormalCxxInteropMode) {
44124420
ImportPath::Module::Builder builder(Ctx.Id_CxxStdlib);
44134421
overlay = owner.loadModule(SourceLoc(), std::move(builder).get());
44144422
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/module-cache)
3+
// RUN: %empty-directory(%t/deps)
4+
// RUN: split-file %s %t
5+
6+
// RUN: %target-swift-frontend -typecheck %t/clientWithInteropDep.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -module-cache-path %t/module-cache &> %t/interop_dep.txt
7+
// RUN: cat %t/interop_dep.txt | %FileCheck %s -check-prefix=ENABLE-CHECK
8+
9+
// RUN: %target-swift-frontend -typecheck -o %t/deps_no_interop_dep.json %t/clientNoInteropDep.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -module-cache-path %t/module-cache &> %t/no_interop_dep.txt
10+
// RUN: cat %t/no_interop_dep.txt | %FileCheck %s -check-prefix=DISABLE-CHECK
11+
12+
// ENABLE-CHECK: remark: loaded module 'CxxStdlib' (overlay for a clang dependency)
13+
// DISABLE-CHECK-NOT: remark: loaded module 'CxxStdlib' (overlay for a clang dependency)
14+
15+
//--- deps/bar.h
16+
#include "std_bar.h"
17+
void bar(void);
18+
19+
//--- deps/std_bar.h
20+
void std_bar(void);
21+
22+
//--- deps/module.modulemap
23+
module std_Bar [system] {
24+
header "std_bar.h"
25+
export *
26+
}
27+
28+
module Bar [system] {
29+
header "bar.h"
30+
export *
31+
}
32+
33+
//--- deps/Foo.swiftinterface
34+
// swift-interface-format-version: 1.0
35+
// swift-module-flags: -module-name Foo -enable-library-evolution -Rmodule-loading
36+
import Bar
37+
public struct Foo1 {}
38+
39+
//--- deps/FooNoInterop.swiftinterface
40+
// swift-interface-format-version: 1.0
41+
// swift-module-flags: -module-name FooNoInterop -enable-library-evolution
42+
// swift-module-flags-ignorable: -formal-cxx-interoperability-mode=off -Rmodule-loading
43+
import Bar
44+
public struct Foo2 {}
45+
46+
//--- clientWithInteropDep.swift
47+
import Foo
48+
49+
//--- clientNoInteropDep.swift
50+
import FooNoInterop
51+

0 commit comments

Comments
 (0)