Skip to content

Commit 4fb4945

Browse files
authored
Merge pull request #81908 from artemcm/FixImplicitBuildCXXInteropCycle
[C++Interop] Do not query C++ Standard Library Swift overlays when building Swift modules which were built without C++ interop
2 parents 10f0f61 + 5b501ad commit 4fb4945

File tree

8 files changed

+128
-9
lines changed

8 files changed

+128
-9
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace swift {
4545

4646
struct DiagnosticBehavior;
4747
class DiagnosticEngine;
48+
class FrontendOptions;
4849

4950
/// Kind of implicit platform conditions.
5051
enum class PlatformConditionKind {
@@ -339,7 +340,8 @@ namespace swift {
339340
std::optional<version::Version> FormalCxxInteropMode;
340341

341342
void setCxxInteropFromArgs(llvm::opt::ArgList &Args,
342-
swift::DiagnosticEngine &Diags);
343+
swift::DiagnosticEngine &Diags,
344+
const FrontendOptions &FrontendOpts);
343345

344346
/// The C++ standard library used for the current build. This can differ
345347
/// from the default C++ stdlib on a particular platform when `-Xcc

lib/ClangImporter/ClangImporter.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4354,7 +4354,14 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
43544354
// FIXME: Include proper source location.
43554355
ModuleDecl *M = getParentModule();
43564356
ASTContext &Ctx = M->getASTContext();
4357-
auto overlay = Ctx.getOverlayModule(this);
4357+
4358+
ModuleDecl *overlay = nullptr;
4359+
// During compilation of a textual interface with no formal C++ interop mode,
4360+
// i.e. it was built without C++ interop, avoid querying the 'CxxStdlib' overlay
4361+
// for it, since said overlay was not used during compilation of this module.
4362+
if (!importer::isCxxStdModule(clangModule) || Ctx.LangOpts.FormalCxxInteropMode)
4363+
overlay = Ctx.getOverlayModule(this);
4364+
43584365
if (overlay) {
43594366
Ctx.addLoadedModule(overlay);
43604367
} else {
@@ -4374,7 +4381,8 @@ ModuleDecl *ClangModuleUnit::getOverlayModule() const {
43744381
// If this Clang module is a part of the C++ stdlib, and we haven't loaded
43754382
// the overlay for it so far, it is a split libc++ module (e.g. std_vector).
43764383
// Load the CxxStdlib overlay explicitly.
4377-
if (!overlay && importer::isCxxStdModule(clangModule)) {
4384+
if (!overlay && importer::isCxxStdModule(clangModule) &&
4385+
Ctx.LangOpts.FormalCxxInteropMode) {
43784386
ImportPath::Module::Builder builder(Ctx.Id_CxxStdlib);
43794387
overlay = owner.loadModule(SourceLoc(), std::move(builder).get());
43804388
}

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,7 +1477,13 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
14771477

14781478
// If the textual interface was built without C++ interop, do not query
14791479
// the C++ Standard Library Swift overlay for its compilation.
1480-
if (llvm::find(commandLine, "-formal-cxx-interoperability-mode=off") ==
1480+
//
1481+
// FIXME: We always declare the 'Darwin' module as formally having been built
1482+
// without C++Interop, for compatibility with prior versions. Once we are certain
1483+
// that we are only building against modules built with support of
1484+
// '-formal-cxx-interoperability-mode', this hard-coded check should be removed.
1485+
if (moduleID.ModuleName != "Darwin" &&
1486+
llvm::find(commandLine, "-formal-cxx-interoperability-mode=off") ==
14811487
commandLine.end()) {
14821488
for (const auto &clangDepName : allClangDependencies) {
14831489
// If this Clang module is a part of the C++ stdlib, and we haven't

lib/DriverTool/swift_symbolgraph_extract_main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ int swift_symbolgraph_extract_main(ArrayRef<const char *> Args,
214214
Options.AvailabilityIsBlockList = A->getOption().matches(OPT_block_availability_platforms);
215215
}
216216

217-
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags);
217+
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags,
218+
Invocation.getFrontendOptions());
218219

219220
std::string InstanceSetupError;
220221
if (CI.setup(Invocation, InstanceSetupError)) {

lib/DriverTool/swift_synthesize_interface_main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ int swift_synthesize_interface_main(ArrayRef<const char *> Args,
133133
Invocation.setImportSearchPaths(ImportSearchPaths);
134134

135135
Invocation.getLangOptions().EnableObjCInterop = Target.isOSDarwin();
136-
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags);
136+
Invocation.getLangOptions().setCxxInteropFromArgs(ParsedArgs, Diags,
137+
Invocation.getFrontendOptions());
137138

138139
std::string ModuleCachePath = "";
139140
if (auto *A = ParsedArgs.getLastArg(OPT_module_cache_path)) {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,8 @@ static void diagnoseCxxInteropCompatMode(Arg *verArg, ArgList &Args,
682682
}
683683

684684
void LangOptions::setCxxInteropFromArgs(ArgList &Args,
685-
swift::DiagnosticEngine &Diags) {
685+
swift::DiagnosticEngine &Diags,
686+
const FrontendOptions &FrontendOpts) {
686687
if (Arg *A = Args.getLastArg(options::OPT_cxx_interoperability_mode)) {
687688
if (Args.hasArg(options::OPT_enable_experimental_cxx_interop)) {
688689
Diags.diagnose(SourceLoc(), diag::dont_enable_interop_and_compat);
@@ -737,7 +738,12 @@ void LangOptions::setCxxInteropFromArgs(ArgList &Args,
737738
// version, and is either 4, 5, 6, or 7 (even though only 5.9 and 6.* make
738739
// any sense). For now, we don't actually care about the version, so we'll
739740
// just use version 6 (i.e., 'swift-6') to mean that C++ interop mode is on.
740-
if (EnableCXXInterop)
741+
//
742+
// FIXME: We always declare the 'Darwin' module as formally having been built
743+
// without C++Interop, for compatibility with prior versions. Once we are certain
744+
// that we are only building against modules built with support of
745+
// '-formal-cxx-interoperability-mode', this hard-coded check should be removed.
746+
if (EnableCXXInterop && (FrontendOpts.ModuleName.compare("Darwin") != 0))
741747
FormalCxxInteropMode = {6};
742748
else
743749
FormalCxxInteropMode = std::nullopt;
@@ -1560,7 +1566,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
15601566
if (const Arg *A = Args.getLastArg(OPT_clang_target_variant))
15611567
Opts.ClangTargetVariant = llvm::Triple(A->getValue());
15621568

1563-
Opts.setCxxInteropFromArgs(Args, Diags);
1569+
Opts.setCxxInteropFromArgs(Args, Diags, FrontendOpts);
15641570
if (!Args.hasArg(options::OPT_formal_cxx_interoperability_mode))
15651571
ModuleInterfaceOpts.PublicFlags.IgnorableFlags +=
15661572
" " + printFormalCxxInteropVersion(Opts);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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: %empty-directory(%t/module-cache)
10+
// RUN: %target-swift-frontend -typecheck %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
11+
// RUN: cat %t/no_interop_dep.txt | %FileCheck %s -check-prefix=DISABLE-CHECK
12+
13+
// RUN: %empty-directory(%t/module-cache)
14+
// RUN: %target-swift-frontend -typecheck %t/clientDarwin.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/darwin_dep.txt
15+
// RUN: cat %t/darwin_dep.txt | %FileCheck %s -check-prefix=DISABLE-CHECK
16+
17+
// ENABLE-CHECK: remark: loaded module 'CxxStdlib' (overlay for a clang dependency)
18+
// DISABLE-CHECK-NOT: remark: loaded module 'CxxStdlib' (overlay for a clang dependency)
19+
20+
//--- deps/bar.h
21+
#include "std_bar.h"
22+
void bar(void);
23+
24+
//--- deps/std_bar.h
25+
void std_bar(void);
26+
27+
//--- deps/module.modulemap
28+
module std_Bar [system] {
29+
header "std_bar.h"
30+
export *
31+
}
32+
33+
module Bar [system] {
34+
header "bar.h"
35+
export *
36+
}
37+
38+
//--- deps/Foo.swiftinterface
39+
// swift-interface-format-version: 1.0
40+
// swift-module-flags: -module-name Foo -enable-library-evolution -Rmodule-loading
41+
import Bar
42+
public struct Foo1 {}
43+
44+
//--- deps/FooNoInterop.swiftinterface
45+
// swift-interface-format-version: 1.0
46+
// swift-module-flags: -module-name FooNoInterop -enable-library-evolution
47+
// swift-module-flags-ignorable: -formal-cxx-interoperability-mode=off -Rmodule-loading
48+
import Bar
49+
public struct Foo2 {}
50+
51+
//--- deps/Darwin.swiftinterface
52+
// swift-interface-format-version: 1.0
53+
// swift-module-flags: -module-name Darwin -enable-library-evolution
54+
// swift-module-flags-ignorable: -Rmodule-loading
55+
import Bar
56+
public struct Foo2 {}
57+
58+
//--- clientWithInteropDep.swift
59+
import Foo
60+
61+
//--- clientNoInteropDep.swift
62+
import FooNoInterop
63+
64+
//--- clientDarwin.swift
65+
import Darwin
66+

test/ScanDependencies/no-cxx-overlay-for-non-interop-interface.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// RUN: %target-swift-frontend -scan-dependencies -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 -verify
99
// RUN: cat %t/deps_no_interop_dep.json | %FileCheck %s -check-prefix=DISABLE-CHECK
1010

11+
// RUN: %target-swift-frontend -scan-dependencies -o %t/deps_darwin_dep.json %t/clientDarwin.swift -I %t/deps -cxx-interoperability-mode=default -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -verify
12+
// RUN: cat %t/deps_darwin_dep.json | %FileCheck %s -check-prefix=DARWIN-CHECK
13+
1114
//--- deps/bar.h
1215
void bar(void);
1316

@@ -30,12 +33,21 @@ public struct Foo1 {}
3033
import std_Bar
3134
public struct Foo2 {}
3235

36+
//--- deps/Darwin.swiftinterface
37+
// swift-interface-format-version: 1.0
38+
// swift-module-flags: -module-name Darwin -enable-library-evolution
39+
import std_Bar
40+
public struct Foo3 {}
41+
3342
//--- clientWithInteropDep.swift
3443
import Foo
3544

3645
//--- clientNoInteropDep.swift
3746
import FooNoInterop
3847

48+
//--- clientDarwin.swift
49+
import Darwin
50+
3951
// Ensure that when the 'Foo' dependency was built with C++ interop enabled,
4052
// it gets the C++ standard library overlay for its 'std_*' dependency
4153
//
@@ -75,4 +87,21 @@ import FooNoInterop
7587
// DISABLE-CHECK: }
7688
// DISABLE-CHECK: ],
7789

90+
// Ensure that the the 'Darwin' dependency does not get the C++ standard library overlay for its 'std_*' dependencies
91+
//
92+
// 'Darwin' as it appears in direct deps
93+
// DARWIN-CHECK: "swift": "Darwin"
94+
// 'Darwin' as it appears in source-import deps
95+
// DARWIN-CHECK: "swift": "Darwin"
96+
// Actual dependency info node
97+
// DARWIN-CHECK: "swift": "Darwin"
98+
// DARWIN-CHECK: "directDependencies": [
99+
// DARWIN-CHECK: {
100+
// DARWIN-CHECK: "swift": "SwiftOnoneSupport"
101+
// DARWIN-CHECK: },
102+
// DARWIN-CHECK: {
103+
// DARWIN-CHECK: "clang": "std_Bar"
104+
// DARWIN-CHECK: }
105+
// DARWIN-CHECK: ],
106+
78107

0 commit comments

Comments
 (0)