Skip to content

Commit c0fd5d7

Browse files
committed
Add driver flags for C++ interop.
The flags (-enable-experimental-cxx-interop and -experimental-cxx-stdlib) carry "experimental" in the name to emphasize that C++ interop is still an experimental feature.
1 parent e9b8e61 commit c0fd5d7

File tree

10 files changed

+72
-36
lines changed

10 files changed

+72
-36
lines changed

include/swift/AST/DiagnosticsDriver.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ ERROR(cannot_find_migration_script, none,
207207
ERROR(error_darwin_static_stdlib_not_supported, none,
208208
"-static-stdlib is no longer supported on Apple platforms", ())
209209

210+
ERROR(error_darwin_only_supports_libcxx, none,
211+
"The only C++ standard library supported on Apple platforms is libc++",
212+
())
213+
210214
WARNING(warn_drv_darwin_sdk_invalid_settings, none,
211215
"SDK settings were ignored because 'SDKSettings.json' could not be parsed",
212216
())

include/swift/Driver/ToolChain.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ class ToolChain {
105105

106106
const char *computeFrontendModeForCompile() const;
107107

108-
bool cxxInteropEnabled() const;
109-
110108
void addFrontendInputAndOutputArguments(
111109
llvm::opt::ArgStringList &Arguments,
112110
std::vector<FilelistInfo> &FilelistInfos) const;

include/swift/Option/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,14 @@ def enable_experimental_concise_pound_file : Flag<["-"],
516516
Flags<[FrontendOption]>,
517517
HelpText<"Enable experimental concise '#file' identifier">;
518518

519+
def enable_experimental_cxx_interop :
520+
Flag<["-"], "enable-experimental-cxx-interop">,
521+
HelpText<"Enable C++ interop code generation and config directives">;
522+
523+
def experimental_cxx_stdlib :
524+
Separate<["-"], "experimental-cxx-stdlib">,
525+
HelpText<"C++ standard library to use; forwarded to Clang's -stdlib flag">;
526+
519527
// Diagnostic control options
520528
def suppress_warnings : Flag<["-"], "suppress-warnings">,
521529
Flags<[FrontendOption]>,

lib/Driver/DarwinToolChains.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,8 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job,
712712
Arguments.push_back("-arch");
713713
Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName()));
714714

715-
if (context.cxxInteropEnabled()) {
716-
// On Darwin, we only support libc++.
715+
// On Darwin, we only support libc++.
716+
if (context.Args.hasArg(options::OPT_enable_experimental_cxx_interop)) {
717717
Arguments.push_back("-lc++");
718718
}
719719

@@ -860,6 +860,13 @@ toolchains::Darwin::validateArguments(DiagnosticEngine &diags,
860860
if (args.hasArg(options::OPT_static_stdlib)) {
861861
diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported);
862862
}
863+
864+
// If a C++ standard library is specified, it has to be libc++.
865+
if (auto arg = args.getLastArg(options::OPT_experimental_cxx_stdlib)) {
866+
if (StringRef(arg->getValue()) != "libc++") {
867+
diags.diagnose(SourceLoc(), diag::error_darwin_only_supports_libcxx);
868+
}
869+
}
863870
}
864871

865872
void

lib/Driver/ToolChain.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,6 @@ ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name,
6767
return C.getArgs().MakeArgString(buffer.str());
6868
}
6969

70-
bool
71-
ToolChain::JobContext::cxxInteropEnabled() const {
72-
// TODO: Eventually, we'll want to have a driver flag to control C++ interop,
73-
// but for the time being, we just query the frontend flag.
74-
for (const Arg *A : Args.filtered(options::OPT_Xfrontend)) {
75-
if (A->containsValue("-enable-cxx-interop")) {
76-
return true;
77-
}
78-
}
79-
80-
return false;
81-
}
82-
8370
Optional<Job::ResponseFileInfo>
8471
ToolChain::getResponseFileInfo(const Compilation &C, const char *executablePath,
8572
const ToolChain::InvocationInfo &invocationInfo,

lib/Driver/ToolChains.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,17 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
170170
arguments.push_back("-disable-objc-interop");
171171
}
172172

173+
// Add flags for C++ interop.
174+
if (inputArgs.hasArg(options::OPT_enable_experimental_cxx_interop)) {
175+
arguments.push_back("-enable-cxx-interop");
176+
}
177+
if (const Arg *arg =
178+
inputArgs.getLastArg(options::OPT_experimental_cxx_stdlib)) {
179+
arguments.push_back("-Xcc");
180+
arguments.push_back(inputArgs.MakeArgString(
181+
Twine("-stdlib=") + arg->getValue()));
182+
}
183+
173184
// Handle the CPU and its preferences.
174185
inputArgs.AddLastArg(arguments, options::OPT_target_cpu);
175186

lib/Driver/UnixToolChains.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -186,19 +186,9 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
186186
// a C++ standard library if it's not needed, in particular because the
187187
// standard library that `clang++` selects by default may not be the one that
188188
// is desired.
189-
//
190-
// TODO: In principle, it should be possible to use a different C++ standard
191-
// library than the one configured by default by passing a `-stdlib` option
192-
// to `-Xcc` and `-Xclang-linker`, e.g.
193-
// `-Xcc -stdlib=libc++ -Xclang-linker -stdlib=libc++`.
194-
// Once there is a driver flag for C++ interop, we will probably also want to
195-
// add a driver flag for selecting the C++ standard library.
196-
//
197-
// In practice, using libc++ on Linux, for example, does not work because the
198-
// SwiftGlibc module definition is incompatible with libc++'s header layout.
199-
// We probably need to ensure that we use libc++'s own module map instead of
200-
// the SwiftGlibc module map.
201-
const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang";
189+
const char *Clang =
190+
context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ?
191+
"clang++" : "clang";
202192
if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) {
203193
StringRef toolchainPath(A->getValue());
204194

@@ -306,6 +296,13 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
306296
}
307297
}
308298

299+
// Link against the desired C++ standard library.
300+
if (const Arg *A =
301+
context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) {
302+
Arguments.push_back(context.Args.MakeArgString(
303+
Twine("-stdlib=") + A->getValue()));
304+
}
305+
309306
// Explicitly pass the target to the linker
310307
Arguments.push_back(
311308
context.Args.MakeArgString("--target=" + getTriple().str()));

lib/Driver/WindowsToolChains.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job,
8585
}
8686

8787
// Configure the toolchain.
88-
const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang";
88+
const char *Clang =
89+
context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ?
90+
"clang++" : "clang";
8991
if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) {
9092
StringRef toolchainPath(A->getValue());
9193

@@ -143,6 +145,13 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job,
143145
Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath));
144146
}
145147

148+
// Link against the desired C++ standard library.
149+
if (const Arg *A =
150+
context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) {
151+
Arguments.push_back(context.Args.MakeArgString(
152+
Twine("-stdlib=") + A->getValue()));
153+
}
154+
146155
if (job.getKind() == LinkKind::Executable) {
147156
if (context.OI.SelectedSanitizers & SanitizerKind::Address)
148157
addLinkRuntimeLib(context.Args, Arguments,

test/Driver/cxx_interop.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s -enable-experimental-cxx-interop 2>^1 | %FileCheck -check-prefix ENABLE %s
2+
3+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s -enable-experimental-cxx-interop -experimental-cxx-stdlib libc++ 2>^1 | %FileCheck -check-prefix STDLIB %s
4+
5+
// ENABLE: swift
6+
// ENABLE: -enable-cxx-interop
7+
8+
// STDLIB: swift
9+
// STDLIB-DAG: -enable-cxx-interop
10+
// STDLIB-DAG: -Xcc -stdlib=libc++

test/Driver/linker.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@
101101
// INFERRED_NAMED_DARWIN tests above: 'libLINKER.dylib'.
102102
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -emit-library %s -o libLINKER.dylib | %FileCheck -check-prefix INFERRED_NAME_DARWIN %s
103103

104-
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 -Xfrontend -enable-cxx-interop %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop %s
104+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 -enable-experimental-cxx-interop -experimental-cxx-stdlib libc++ %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop %s
105+
// RUN: not %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 -enable-experimental-cxx-interop -experimental-cxx-stdlib libstdc++ %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop-libstdcxx %s
105106

106-
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-linux-gnu -Xfrontend -enable-cxx-interop %s 2>&1 | %FileCheck -check-prefix LINUX-cxx-interop %s
107+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-linux-gnu -enable-experimental-cxx-interop -experimental-cxx-stdlib libc++ %s 2>&1 | %FileCheck -check-prefix LINUX-cxx-interop %s
107108

108-
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-windows-msvc -Xfrontend -enable-cxx-interop %s 2>&1 | %FileCheck -check-prefix WINDOWS-cxx-interop %s
109+
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-windows-msvc -enable-experimental-cxx-interop -experimental-cxx-stdlib libc++ %s 2>&1 | %FileCheck -check-prefix WINDOWS-cxx-interop %s
109110

110111
// Check reading the SDKSettings.json from an SDK
111112
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -sdk %S/Inputs/MacOSX10.15.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15 %s
@@ -423,20 +424,24 @@
423424
// IOS-cxx-interop-DAG: -lc++
424425
// IOS-cxx-interop: -o linker
425426

427+
// IOS-cxx-interop-libstdcxx: error: The only C++ standard library supported on Apple platforms is libc++
428+
426429
// LINUX-cxx-interop: swift
427430
// LINUX-cxx-interop-DAG: -enable-cxx-interop
428431
// LINUX-cxx-interop-DAG: -o [[OBJECTFILE:.*]]
429432

430433
// LINUX-cxx-interop: clang++{{(\.exe)?"? }}
431-
// LINUX-cxx-interop: [[OBJECTFILE]]
434+
// LINUX-cxx-interop-DAG: [[OBJECTFILE]]
435+
// LINUX-cxx-interop-DAG: -stdlib=libc++
432436
// LINUX-cxx-interop: -o linker
433437

434438
// WINDOWS-cxx-interop: swift
435439
// WINDOWS-cxx-interop-DAG: -enable-cxx-interop
436440
// WINDOWS-cxx-interop-DAG: -o [[OBJECTFILE:.*]]
437441

438442
// WINDOWS-cxx-interop: clang++{{(\.exe)?"? }}
439-
// WINDOWS-cxx-interop: [[OBJECTFILE]]
443+
// WINDOWS-cxx-interop-DAG: [[OBJECTFILE]]
444+
// WINDOWS-cxx-interop-DAG: -stdlib=libc++
440445
// WINDOWS-cxx-interop: -o linker
441446

442447
// Test ld detection. We use hard links to make sure

0 commit comments

Comments
 (0)