From 46274318c3d3d273070be4d8b313216f0ab9afc7 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Wed, 8 Apr 2020 17:06:29 +0200 Subject: [PATCH 1/8] Link against the C++ standard library when C++ interop is enabled. This doesn't yet allow including C++ headers on platforms where libc++ isn't the default; see comments in UnixToolChains.cpp for details. However, it does, for example, allow throwing and catching exceptions in C++ code used through interop, unblocking https://github.com/apple/swift/pull/30674/files. --- include/swift/Driver/ToolChain.h | 2 ++ lib/Driver/DarwinToolChains.cpp | 5 +++++ lib/Driver/ToolChain.cpp | 13 +++++++++++ lib/Driver/UnixToolChains.cpp | 37 +++++++++++++++++--------------- lib/Driver/WindowsToolChains.cpp | 20 +++-------------- test/Driver/linker.swift | 31 ++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 34 deletions(-) diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index cdd7b2873db4c..9287dde89f69d 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -105,6 +105,8 @@ class ToolChain { const char *computeFrontendModeForCompile() const; + bool cxxInteropEnabled() const; + void addFrontendInputAndOutputArguments( llvm::opt::ArgStringList &Arguments, std::vector &FilelistInfos) const; diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 7681ef5960dec..086f13dced3cb 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -712,6 +712,11 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back("-arch"); Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName())); + if (context.cxxInteropEnabled()) { + // We only support libc++ on Darwin. + Arguments.push_back("-lc++"); + } + addArgsToLinkStdlib(Arguments, job, context); addProfileGenerationArgs(Arguments, context); diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 784348922f6fb..6b6f23caaf2f4 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -67,6 +67,19 @@ ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name, return C.getArgs().MakeArgString(buffer.str()); } +bool +ToolChain::JobContext::cxxInteropEnabled() const { + // TODO: Eventually, we'll want to have a driver flag to control C++ interop, + // but for the time being, we just query the frontend flag. + for (const Arg *A : Args.filtered(options::OPT_Xfrontend)) { + if (A->containsValue("-enable-cxx-interop")) { + return true; + } + } + + return false; +} + Optional ToolChain::getResponseFileInfo(const Compilation &C, const char *executablePath, const ToolChain::InvocationInfo &invocationInfo, diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 4383d298e00b5..6b9b1cd1229b0 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -182,27 +182,30 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // Configure the toolchain. // - // By default use the system `clang` to perform the link. We use `clang` for - // the driver here because we do not wish to select a particular C++ runtime. - // Furthermore, until C++ interop is enabled, we cannot have a dependency on - // C++ code from pure Swift code. If linked libraries are C++ based, they - // should properly link C++. In the case of static linking, the user can - // explicitly specify the C++ runtime to link against. This is particularly - // important for platforms like android where as it is a Linux platform, the - // default C++ runtime is `libstdc++` which is unsupported on the target but - // as the builds are usually cross-compiled from Linux, libstdc++ is going to - // be present. This results in linking the wrong version of libstdc++ - // generating invalid binaries. It is also possible to use different C++ - // runtimes than the default C++ runtime for the platform (e.g. libc++ on - // Windows rather than msvcprt). When C++ interop is enabled, we will need to - // surface this via a driver flag. For now, opt for the simpler approach of - // just using `clang` and avoid a dependency on the C++ runtime. - const char *Clang = "clang"; + // We use `clang++` if C++ interop is enabled, `clang` otherwise. + // + // We don't use `clang++` unconditionally because we want to avoid pulling in + // a C++ standard library if it's not needed, in particular because the + // standard library that `clang++` selects by default may not be the one that + // is desired. + // + // TODO: In principle, it should be possible to use a different C++ standard + // library than the one configured by default by passing a `-stdlib` option + // to `-Xcc` and `-Xclang-linker`, e.g. + // `-Xcc -stdlib=libc++ -Xclang-linker -stdlib=libc++`. + // Once there is a driver flag for C++ interop, we will probably also want to + // add a driver flag for selecting the C++ standard library. + // + // In practice, using libc++ on Linux, for example, does not work because the + // SwiftGlibc module definition is incompatible with libc++'s header layout. + // We probably need to ensure that we use libc++'s own module map instead of + // the SwiftGlibc module map. + const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); // If there is a clang in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName("clang", {toolchainPath})) { + if (auto tool = llvm::sys::findProgramByName(Clang, {toolchainPath})) { Clang = context.Args.MakeArgString(tool.get()); } diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 0fe623675eb1a..2a5b51e97ab87 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -86,27 +86,13 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, // Configure the toolchain. // - // By default use the system `clang` to perform the link. We use `clang` for - // the driver here because we do not wish to select a particular C++ runtime. - // Furthermore, until C++ interop is enabled, we cannot have a dependency on - // C++ code from pure Swift code. If linked libraries are C++ based, they - // should properly link C++. In the case of static linking, the user can - // explicitly specify the C++ runtime to link against. This is particularly - // important for platforms like android where as it is a Linux platform, the - // default C++ runtime is `libstdc++` which is unsupported on the target but - // as the builds are usually cross-compiled from Linux, libstdc++ is going to - // be present. This results in linking the wrong version of libstdc++ - // generating invalid binaries. It is also possible to use different C++ - // runtimes than the default C++ runtime for the platform (e.g. libc++ on - // Windows rather than msvcprt). When C++ interop is enabled, we will need to - // surface this via a driver flag. For now, opt for the simpler approach of - // just using `clang` and avoid a dependency on the C++ runtime. - const char *Clang = "clang"; + // We use `clang++` if C++ interop is enabled, `clang` otherwise. + const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); // If there is a clang in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName("clang", {toolchainPath})) + if (auto tool = llvm::sys::findProgramByName(Clang, {toolchainPath})) Clang = context.Args.MakeArgString(tool.get()); } diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index 8e5017922f1d2..a192e62aa4a4d 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -101,6 +101,12 @@ // INFERRED_NAMED_DARWIN tests above: 'libLINKER.dylib'. // 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 +// 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 + +// 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 + +// 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 + // Check reading the SDKSettings.json from an SDK // 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 // RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -sdk %S/Inputs/MacOSX10.15.4.versioned.sdk %s 2>&1 | %FileCheck -check-prefix MACOS_10_15_4 %s @@ -408,6 +414,31 @@ // INFERRED_NAME_WINDOWS: -o LINKER.dll // INFERRED_NAME_WASI: -o libLINKER.so +// IOS-cxx-interop: swift +// IOS-cxx-interop-DAG: -enable-cxx-interop +// IOS-cxx-interop-DAG: -o [[OBJECTFILE:.*]] + +// IOS-cxx-interop: {{(bin/)?}}ld{{"? }} +// IOS-cxx-interop-DAG: [[OBJECTFILE]] +// IOS-cxx-interop-DAG: -lc++ +// IOS-cxx-interop: -o linker + +// LINUX-cxx-interop: swift +// LINUX-cxx-interop-DAG: -enable-cxx-interop +// LINUX-cxx-interop-DAG: -o [[OBJECTFILE:.*]] + +// LINUX-cxx-interop: clang++{{(\.exe)?"? }} +// LINUX-cxx-interop: [[OBJECTFILE]] +// LINUX-cxx-interop: -o linker + +// WINDOWS-cxx-interop: swift +// WINDOWS-cxx-interop-DAG: -enable-cxx-interop +// WINDOWS-cxx-interop-DAG: -o [[OBJECTFILE:.*]] + +// WINDOWS-cxx-interop: clang++{{(\.exe)?"? }} +// WINDOWS-cxx-interop: [[OBJECTFILE]] +// WINDOWS-cxx-interop: -o linker + // Test ld detection. We use hard links to make sure // the Swift driver really thinks it's been moved. From e9b8e61cb0c46f69ce33c2b1e650c278c9dcb242 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Thu, 9 Apr 2020 10:01:28 +0200 Subject: [PATCH 2/8] Address review comments by MForster. --- lib/Driver/DarwinToolChains.cpp | 2 +- lib/Driver/UnixToolChains.cpp | 2 -- lib/Driver/WindowsToolChains.cpp | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 086f13dced3cb..f1ec36be31c01 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -713,7 +713,7 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName())); if (context.cxxInteropEnabled()) { - // We only support libc++ on Darwin. + // On Darwin, we only support libc++. Arguments.push_back("-lc++"); } diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 6b9b1cd1229b0..b6d04e43f57a6 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -182,8 +182,6 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // Configure the toolchain. // - // We use `clang++` if C++ interop is enabled, `clang` otherwise. - // // We don't use `clang++` unconditionally because we want to avoid pulling in // a C++ standard library if it's not needed, in particular because the // standard library that `clang++` selects by default may not be the one that diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 2a5b51e97ab87..c9ae59cd8e9f8 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -85,8 +85,6 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, } // Configure the toolchain. - // - // We use `clang++` if C++ interop is enabled, `clang` otherwise. const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); From c0fd5d7ebb1c1b22be3f1c893fb8eb7ca6836b02 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Tue, 14 Apr 2020 12:11:03 +0200 Subject: [PATCH 3/8] 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. --- include/swift/AST/DiagnosticsDriver.def | 4 ++++ include/swift/Driver/ToolChain.h | 2 -- include/swift/Option/Options.td | 8 ++++++++ lib/Driver/DarwinToolChains.cpp | 11 +++++++++-- lib/Driver/ToolChain.cpp | 13 ------------- lib/Driver/ToolChains.cpp | 11 +++++++++++ lib/Driver/UnixToolChains.cpp | 23 ++++++++++------------- lib/Driver/WindowsToolChains.cpp | 11 ++++++++++- test/Driver/cxx_interop.swift | 10 ++++++++++ test/Driver/linker.swift | 15 ++++++++++----- 10 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 test/Driver/cxx_interop.swift diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def index 03ed4832f8406..f2525773f2f1d 100644 --- a/include/swift/AST/DiagnosticsDriver.def +++ b/include/swift/AST/DiagnosticsDriver.def @@ -207,6 +207,10 @@ ERROR(cannot_find_migration_script, none, ERROR(error_darwin_static_stdlib_not_supported, none, "-static-stdlib is no longer supported on Apple platforms", ()) +ERROR(error_darwin_only_supports_libcxx, none, + "The only C++ standard library supported on Apple platforms is libc++", + ()) + WARNING(warn_drv_darwin_sdk_invalid_settings, none, "SDK settings were ignored because 'SDKSettings.json' could not be parsed", ()) diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index 9287dde89f69d..cdd7b2873db4c 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -105,8 +105,6 @@ class ToolChain { const char *computeFrontendModeForCompile() const; - bool cxxInteropEnabled() const; - void addFrontendInputAndOutputArguments( llvm::opt::ArgStringList &Arguments, std::vector &FilelistInfos) const; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index b698629f55da0..618d151248790 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -516,6 +516,14 @@ def enable_experimental_concise_pound_file : Flag<["-"], Flags<[FrontendOption]>, HelpText<"Enable experimental concise '#file' identifier">; +def enable_experimental_cxx_interop : + Flag<["-"], "enable-experimental-cxx-interop">, + HelpText<"Enable C++ interop code generation and config directives">; + +def experimental_cxx_stdlib : + Separate<["-"], "experimental-cxx-stdlib">, + HelpText<"C++ standard library to use; forwarded to Clang's -stdlib flag">; + // Diagnostic control options def suppress_warnings : Flag<["-"], "suppress-warnings">, Flags<[FrontendOption]>, diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index f1ec36be31c01..d4e25b8778bcd 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -712,8 +712,8 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back("-arch"); Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName())); - if (context.cxxInteropEnabled()) { - // On Darwin, we only support libc++. + // On Darwin, we only support libc++. + if (context.Args.hasArg(options::OPT_enable_experimental_cxx_interop)) { Arguments.push_back("-lc++"); } @@ -860,6 +860,13 @@ toolchains::Darwin::validateArguments(DiagnosticEngine &diags, if (args.hasArg(options::OPT_static_stdlib)) { diags.diagnose(SourceLoc(), diag::error_darwin_static_stdlib_not_supported); } + + // If a C++ standard library is specified, it has to be libc++. + if (auto arg = args.getLastArg(options::OPT_experimental_cxx_stdlib)) { + if (StringRef(arg->getValue()) != "libc++") { + diags.diagnose(SourceLoc(), diag::error_darwin_only_supports_libcxx); + } + } } void diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 6b6f23caaf2f4..784348922f6fb 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -67,19 +67,6 @@ ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name, return C.getArgs().MakeArgString(buffer.str()); } -bool -ToolChain::JobContext::cxxInteropEnabled() const { - // TODO: Eventually, we'll want to have a driver flag to control C++ interop, - // but for the time being, we just query the frontend flag. - for (const Arg *A : Args.filtered(options::OPT_Xfrontend)) { - if (A->containsValue("-enable-cxx-interop")) { - return true; - } - } - - return false; -} - Optional ToolChain::getResponseFileInfo(const Compilation &C, const char *executablePath, const ToolChain::InvocationInfo &invocationInfo, diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 88165f372ddda..c21bf1563c5fb 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -170,6 +170,17 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI, arguments.push_back("-disable-objc-interop"); } + // Add flags for C++ interop. + if (inputArgs.hasArg(options::OPT_enable_experimental_cxx_interop)) { + arguments.push_back("-enable-cxx-interop"); + } + if (const Arg *arg = + inputArgs.getLastArg(options::OPT_experimental_cxx_stdlib)) { + arguments.push_back("-Xcc"); + arguments.push_back(inputArgs.MakeArgString( + Twine("-stdlib=") + arg->getValue())); + } + // Handle the CPU and its preferences. inputArgs.AddLastArg(arguments, options::OPT_target_cpu); diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index b6d04e43f57a6..a4a7a83e8d3c8 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -186,19 +186,9 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // a C++ standard library if it's not needed, in particular because the // standard library that `clang++` selects by default may not be the one that // is desired. - // - // TODO: In principle, it should be possible to use a different C++ standard - // library than the one configured by default by passing a `-stdlib` option - // to `-Xcc` and `-Xclang-linker`, e.g. - // `-Xcc -stdlib=libc++ -Xclang-linker -stdlib=libc++`. - // Once there is a driver flag for C++ interop, we will probably also want to - // add a driver flag for selecting the C++ standard library. - // - // In practice, using libc++ on Linux, for example, does not work because the - // SwiftGlibc module definition is incompatible with libc++'s header layout. - // We probably need to ensure that we use libc++'s own module map instead of - // the SwiftGlibc module map. - const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang"; + const char *Clang = + context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? + "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); @@ -306,6 +296,13 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, } } + // Link against the desired C++ standard library. + if (const Arg *A = + context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) { + Arguments.push_back(context.Args.MakeArgString( + Twine("-stdlib=") + A->getValue())); + } + // Explicitly pass the target to the linker Arguments.push_back( context.Args.MakeArgString("--target=" + getTriple().str())); diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index c9ae59cd8e9f8..932e2da238cf3 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -85,7 +85,9 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, } // Configure the toolchain. - const char *Clang = context.cxxInteropEnabled()? "clang++" : "clang"; + const char *Clang = + context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? + "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); @@ -143,6 +145,13 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath)); } + // Link against the desired C++ standard library. + if (const Arg *A = + context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) { + Arguments.push_back(context.Args.MakeArgString( + Twine("-stdlib=") + A->getValue())); + } + if (job.getKind() == LinkKind::Executable) { if (context.OI.SelectedSanitizers & SanitizerKind::Address) addLinkRuntimeLib(context.Args, Arguments, diff --git a/test/Driver/cxx_interop.swift b/test/Driver/cxx_interop.swift new file mode 100644 index 0000000000000..7795e80b7777b --- /dev/null +++ b/test/Driver/cxx_interop.swift @@ -0,0 +1,10 @@ +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s -enable-experimental-cxx-interop 2>^1 | %FileCheck -check-prefix ENABLE %s + +// 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 + +// ENABLE: swift +// ENABLE: -enable-cxx-interop + +// STDLIB: swift +// STDLIB-DAG: -enable-cxx-interop +// STDLIB-DAG: -Xcc -stdlib=libc++ diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index a192e62aa4a4d..d22aef8c6fd1f 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -101,11 +101,12 @@ // INFERRED_NAMED_DARWIN tests above: 'libLINKER.dylib'. // 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 -// 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 +// 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 +// 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 -// 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 +// 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 -// 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 +// 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 // Check reading the SDKSettings.json from an SDK // 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,12 +424,15 @@ // IOS-cxx-interop-DAG: -lc++ // IOS-cxx-interop: -o linker +// IOS-cxx-interop-libstdcxx: error: The only C++ standard library supported on Apple platforms is libc++ + // LINUX-cxx-interop: swift // LINUX-cxx-interop-DAG: -enable-cxx-interop // LINUX-cxx-interop-DAG: -o [[OBJECTFILE:.*]] // LINUX-cxx-interop: clang++{{(\.exe)?"? }} -// LINUX-cxx-interop: [[OBJECTFILE]] +// LINUX-cxx-interop-DAG: [[OBJECTFILE]] +// LINUX-cxx-interop-DAG: -stdlib=libc++ // LINUX-cxx-interop: -o linker // WINDOWS-cxx-interop: swift @@ -436,7 +440,8 @@ // WINDOWS-cxx-interop-DAG: -o [[OBJECTFILE:.*]] // WINDOWS-cxx-interop: clang++{{(\.exe)?"? }} -// WINDOWS-cxx-interop: [[OBJECTFILE]] +// WINDOWS-cxx-interop-DAG: [[OBJECTFILE]] +// WINDOWS-cxx-interop-DAG: -stdlib=libc++ // WINDOWS-cxx-interop: -o linker // Test ld detection. We use hard links to make sure From 332506f257fa3678b7fefa0464618e152cf33a01 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Tue, 21 Apr 2020 14:08:50 +0200 Subject: [PATCH 4/8] Respond to review comments from @compnerd. --- lib/Driver/UnixToolChains.cpp | 10 ++--- lib/Driver/WindowsToolChains.cpp | 10 ++--- test/Driver/linker.swift | 72 +++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index fa349fc311192..7c5452099b291 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -186,15 +186,15 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // a C++ standard library if it's not needed, in particular because the // standard library that `clang++` selects by default may not be the one that // is desired. - const char *Clang = + const char *LinkerDriver = context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); - // If there is a clang in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName(Clang, {toolchainPath})) { - Clang = context.Args.MakeArgString(tool.get()); + // If there is a linker driver in the toolchain folder, use that instead. + if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) { + LinkerDriver = context.Args.MakeArgString(tool.get()); } // Look for binutils in the toolchain folder. @@ -350,7 +350,7 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back( context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); - InvocationInfo II{Clang, Arguments}; + InvocationInfo II{LinkerDriver, Arguments}; II.allowsResponseFiles = true; return II; diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 932e2da238cf3..9ebda9a999768 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -85,15 +85,15 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, } // Configure the toolchain. - const char *Clang = + const char *LinkerDriver = context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); - // If there is a clang in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName(Clang, {toolchainPath})) - Clang = context.Args.MakeArgString(tool.get()); + // If there is a linker driver in the toolchain folder, use that instead. + if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) + LinkerDriver = context.Args.MakeArgString(tool.get()); } // Rely on `-libc` to correctly identify the MSVC Runtime Library. We use @@ -189,7 +189,7 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back( context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); - InvocationInfo II{Clang, Arguments}; + InvocationInfo II{LinkerDriver, Arguments}; II.allowsResponseFiles = true; return II; diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index d22aef8c6fd1f..8d159c2f7ccf2 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -101,12 +101,20 @@ // INFERRED_NAMED_DARWIN tests above: 'libLINKER.dylib'. // 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 -// 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 +// On Darwin, when C++ interop is turned on, we link against libc++ explicitly +// regardless of whether -experimental-cxx-stdlib is specified or not. So also +// run a test where C++ interop is turned off to make sure we don't link +// against libc++ in this case. +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix IOS-no-cxx-interop %s +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop-libcxx %s +// 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-libcxx %s // 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 -// 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 +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-linux-gnu -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix LINUX-cxx-interop %s +// 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-libcxx %s -// 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 +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-windows-msvc -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix WINDOWS-cxx-interop %s +// 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-libcxx %s // Check reading the SDKSettings.json from an SDK // 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 @@ -415,34 +423,48 @@ // INFERRED_NAME_WINDOWS: -o LINKER.dll // INFERRED_NAME_WASI: -o libLINKER.so -// IOS-cxx-interop: swift -// IOS-cxx-interop-DAG: -enable-cxx-interop -// IOS-cxx-interop-DAG: -o [[OBJECTFILE:.*]] - -// IOS-cxx-interop: {{(bin/)?}}ld{{"? }} -// IOS-cxx-interop-DAG: [[OBJECTFILE]] -// IOS-cxx-interop-DAG: -lc++ -// IOS-cxx-interop: -o linker +// Instead of a single "NOT" check for this run, we would really want to check +// for all of the driver arguments that we _do_ expect, and then use an +// --implicit-check-not to check that -lc++ doesn't occur. +// However, --implicit-check-not has a bug where it fails to flag the +// unexpected text when it occurs after text matched by a CHECK-DAG; see +// https://bugs.llvm.org/show_bug.cgi?id=45629 +// For this reason, we use a single "NOT" check for the time being here. +// The same consideration applies to the Linux and Windows cases below. +// IOS-no-cxx-interop-NOT: -lc++ + +// IOS-cxx-interop-libcxx: swift +// IOS-cxx-interop-libcxx-DAG: -enable-cxx-interop +// IOS-cxx-interop-libcxx-DAG: -o [[OBJECTFILE:.*]] + +// IOS-cxx-interop-libcxx: {{(bin/)?}}ld{{"? }} +// IOS-cxx-interop-libcxx-DAG: [[OBJECTFILE]] +// IOS-cxx-interop-libcxx-DAG: -lc++ +// IOS-cxx-interop-libcxx: -o linker // IOS-cxx-interop-libstdcxx: error: The only C++ standard library supported on Apple platforms is libc++ -// LINUX-cxx-interop: swift -// LINUX-cxx-interop-DAG: -enable-cxx-interop -// LINUX-cxx-interop-DAG: -o [[OBJECTFILE:.*]] +// LINUX-cxx-interop-NOT: -stdlib + +// LINUX-cxx-interop-libcxx: swift +// LINUX-cxx-interop-libcxx-DAG: -enable-cxx-interop +// LINUX-cxx-interop-libcxx-DAG: -o [[OBJECTFILE:.*]] + +// LINUX-cxx-interop-libcxx: clang++{{(\.exe)?"? }} +// LINUX-cxx-interop-libcxx-DAG: [[OBJECTFILE]] +// LINUX-cxx-interop-libcxx-DAG: -stdlib=libc++ +// LINUX-cxx-interop-libcxx: -o linker -// LINUX-cxx-interop: clang++{{(\.exe)?"? }} -// LINUX-cxx-interop-DAG: [[OBJECTFILE]] -// LINUX-cxx-interop-DAG: -stdlib=libc++ -// LINUX-cxx-interop: -o linker +// WINDOWS-cxx-interop-NOT: -stdlib -// WINDOWS-cxx-interop: swift -// WINDOWS-cxx-interop-DAG: -enable-cxx-interop -// WINDOWS-cxx-interop-DAG: -o [[OBJECTFILE:.*]] +// WINDOWS-cxx-interop-libcxx: swift +// WINDOWS-cxx-interop-libcxx-DAG: -enable-cxx-interop +// WINDOWS-cxx-interop-libcxx-DAG: -o [[OBJECTFILE:.*]] -// WINDOWS-cxx-interop: clang++{{(\.exe)?"? }} -// WINDOWS-cxx-interop-DAG: [[OBJECTFILE]] -// WINDOWS-cxx-interop-DAG: -stdlib=libc++ -// WINDOWS-cxx-interop: -o linker +// WINDOWS-cxx-interop-libcxx: clang++{{(\.exe)?"? }} +// WINDOWS-cxx-interop-libcxx-DAG: [[OBJECTFILE]] +// WINDOWS-cxx-interop-libcxx-DAG: -stdlib=libc++ +// WINDOWS-cxx-interop-libcxx: -o linker // Test ld detection. We use hard links to make sure // the Swift driver really thinks it's been moved. From 97ec750555b27cf1829760d352e27d7067f6e420 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Thu, 23 Apr 2020 15:52:37 +0200 Subject: [PATCH 5/8] Factor out logic for finding the linker driver into a common function. --- include/swift/Driver/ToolChain.h | 3 +++ lib/Driver/ToolChains.cpp | 20 ++++++++++++++++++++ lib/Driver/UnixToolChains.cpp | 15 +-------------- lib/Driver/WindowsToolChains.cpp | 14 +------------- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index cd8bebfdeceaa..cd55451a01c8b 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -294,6 +294,9 @@ class ToolChain { void getClangLibraryPath(const llvm::opt::ArgList &Args, SmallString<128> &LibPath) const; + // Returns the Clang driver executable to use for linking. + const char *getClangLinkerDriver(const llvm::opt::ArgList &Args) const; + /// Returns the name the clang library for a given sanitizer would have on /// the current toolchain. /// diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 4832982e9b0ae..a492be24f400a 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1332,6 +1332,26 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibP } } +const char *ToolChain::getClangLinkerDriver( + const llvm::opt::ArgList &Args) const { + // We don't use `clang++` unconditionally because we want to avoid pulling in + // a C++ standard library if it's not needed, in particular because the + // standard library that `clang++` selects by default may not be the one that + // is desired. + const char *LinkerDriver = + Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? + "clang++" : "clang"; + if (const Arg *A = Args.getLastArg(options::OPT_tools_directory)) { + StringRef toolchainPath(A->getValue()); + + // If there is a linker driver in the toolchain folder, use that instead. + if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) + LinkerDriver = Args.MakeArgString(tool.get()); + } + + return LinkerDriver; +} + bool ToolChain::sanitizerRuntimeLibExists(const ArgList &args, StringRef sanitizerName, bool shared) const { diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 7c5452099b291..b08ecf37a12d9 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -181,22 +181,9 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, } // Configure the toolchain. - // - // We don't use `clang++` unconditionally because we want to avoid pulling in - // a C++ standard library if it's not needed, in particular because the - // standard library that `clang++` selects by default may not be the one that - // is desired. - const char *LinkerDriver = - context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? - "clang++" : "clang"; if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); - // If there is a linker driver in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) { - LinkerDriver = context.Args.MakeArgString(tool.get()); - } - // Look for binutils in the toolchain folder. Arguments.push_back("-B"); Arguments.push_back(context.Args.MakeArgString(A->getValue())); @@ -350,7 +337,7 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back( context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); - InvocationInfo II{LinkerDriver, Arguments}; + InvocationInfo II{getClangLinkerDriver(context.Args), Arguments}; II.allowsResponseFiles = true; return II; diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 9ebda9a999768..643cde578eb75 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -84,18 +84,6 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back("/DEBUG"); } - // Configure the toolchain. - const char *LinkerDriver = - context.Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? - "clang++" : "clang"; - if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { - StringRef toolchainPath(A->getValue()); - - // If there is a linker driver in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) - LinkerDriver = context.Args.MakeArgString(tool.get()); - } - // Rely on `-libc` to correctly identify the MSVC Runtime Library. We use // `-nostartfiles` as that limits the difference to just the // `-defaultlib:libcmt` which is passed unconditionally with the `clang++` @@ -189,7 +177,7 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back( context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); - InvocationInfo II{LinkerDriver, Arguments}; + InvocationInfo II{getClangLinkerDriver(context.Args), Arguments}; II.allowsResponseFiles = true; return II; From e705d8622cd10e697c8928ef24e5cf913cd47161 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Thu, 23 Apr 2020 15:54:19 +0200 Subject: [PATCH 6/8] Change help text for -enable-experimental-cxx-interop. --- include/swift/Option/Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index b7069407ecd97..dfbfad7f2c0f8 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -521,7 +521,7 @@ def enable_experimental_concise_pound_file : Flag<["-"], def enable_experimental_cxx_interop : Flag<["-"], "enable-experimental-cxx-interop">, - HelpText<"Enable C++ interop code generation and config directives">; + HelpText<"Allow importing C++ modules into Swift (experimental feature)">; def experimental_cxx_stdlib : Separate<["-"], "experimental-cxx-stdlib">, From 78c3222f8b539101a587645ebb62a5839ba1dc69 Mon Sep 17 00:00:00 2001 From: Martin Boehme Date: Mon, 4 May 2020 09:26:08 +0200 Subject: [PATCH 7/8] Apply clang-format. --- lib/Driver/ToolChains.cpp | 10 +++++----- lib/Driver/UnixToolChains.cpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a492be24f400a..ca3a8f8f4e20f 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -171,10 +171,10 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, arguments.push_back("-enable-cxx-interop"); } if (const Arg *arg = - inputArgs.getLastArg(options::OPT_experimental_cxx_stdlib)) { + inputArgs.getLastArg(options::OPT_experimental_cxx_stdlib)) { arguments.push_back("-Xcc"); - arguments.push_back(inputArgs.MakeArgString( - Twine("-stdlib=") + arg->getValue())); + arguments.push_back( + inputArgs.MakeArgString(Twine("-stdlib=") + arg->getValue())); } // Handle the CPU and its preferences. @@ -1339,8 +1339,8 @@ const char *ToolChain::getClangLinkerDriver( // standard library that `clang++` selects by default may not be the one that // is desired. const char *LinkerDriver = - Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? - "clang++" : "clang"; + Args.hasArg(options::OPT_enable_experimental_cxx_interop) ? "clang++" + : "clang"; if (const Arg *A = Args.getLastArg(options::OPT_tools_directory)) { StringRef toolchainPath(A->getValue()); diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index b08ecf37a12d9..aa3468734b0be 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -287,9 +287,9 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // Link against the desired C++ standard library. if (const Arg *A = - context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) { - Arguments.push_back(context.Args.MakeArgString( - Twine("-stdlib=") + A->getValue())); + context.Args.getLastArg(options::OPT_experimental_cxx_stdlib)) { + Arguments.push_back( + context.Args.MakeArgString(Twine("-stdlib=") + A->getValue())); } // Explicitly pass the target to the linker From 44e4e790675f919ede65def87703cf4e3bf7507e Mon Sep 17 00:00:00 2001 From: Michael Forster Date: Thu, 9 Jul 2020 11:41:11 +0200 Subject: [PATCH 8/8] Specify -sdk "" for linker tests. This is necessary after commit 1be17a255029b4fd6a2e848baf6354687fbcc76a --- test/Driver/linker.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index 061dd3c876127..339a3b964540d 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -105,16 +105,16 @@ // regardless of whether -experimental-cxx-stdlib is specified or not. So also // run a test where C++ interop is turned off to make sure we don't link // against libc++ in this case. -// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix IOS-no-cxx-interop %s -// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios7.1 -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop-libcxx %s -// 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-libcxx %s -// 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 +// RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-apple-ios7.1 %s 2>&1 | %FileCheck -check-prefix IOS-no-cxx-interop %s +// RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-apple-ios7.1 -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix IOS-cxx-interop-libcxx %s +// RUN: %swiftc_driver -sdk "" -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-libcxx %s +// RUN: not %swiftc_driver -sdk "" -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 -// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-linux-gnu -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix LINUX-cxx-interop %s -// 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-libcxx %s +// RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-unknown-linux-gnu -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix LINUX-cxx-interop %s +// RUN: %swiftc_driver -sdk "" -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-libcxx %s -// RUN: %swiftc_driver -driver-print-jobs -target x86_64-unknown-windows-msvc -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix WINDOWS-cxx-interop %s -// 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-libcxx %s +// RUN: %swiftc_driver -sdk "" -driver-print-jobs -target x86_64-unknown-windows-msvc -enable-experimental-cxx-interop %s 2>&1 | %FileCheck -check-prefix WINDOWS-cxx-interop %s +// RUN: %swiftc_driver -sdk "" -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-libcxx %s // Check reading the SDKSettings.json from an SDK // RUN: %swiftc_driver -sdk "" -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