Skip to content

Commit 0ff5cd9

Browse files
authored
Merge pull request #64088 from zoecarver/cxx-compatibility-mode
[cxx-interop] Add `-cxx-interoperability-mode` driver flag; deprecate `-…
2 parents d154dfd + 440b6bf commit 0ff5cd9

File tree

9 files changed

+120
-16
lines changed

9 files changed

+120
-16
lines changed

docs/CppInteroperability/GettingStartedWithC++Interop.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,9 @@ module CxxTest {
3232
Add the C++ module to the include path and enable C++ interop:
3333
- Navigate to your project directory
3434
- In `Project` navigate to `Build Settings` -> `Swift Compiler`
35-
- Under `Custom Flags` -> `Other Swift Flags` add `-Xfrontend -enable-experimental-cxx-interop`
35+
- Under `Custom Flags` -> `Other Swift Flags` add `-cxx-compatibility-mode=swift-5.9`
3636
- Under `Search Paths` -> `Import Paths` add your search path to the C++ module (i.e, `./ProjectName/CxxTest`).
3737

38-
```
39-
// Add to Other Swift Flags and Import Paths respectively
40-
-Xfrontend -enable-experimental-cxx-interop
41-
-I./ProjectName/CxxTest
42-
```
43-
4438
- This should now allow your to import your C++ Module into any `.swift` file.
4539

4640
```
@@ -87,7 +81,7 @@ After creating your Swift package project, follow the steps [Creating a Module t
8781
- Swift code will be in `Sources/CxxInterop` called `main.swift`
8882
- C++ source code follows the example shown in [Creating a Module to contain your C++ source code](#creating-a-module-to-contain-your-c-source-code)
8983
- Under targets, add the name of your C++ module and the directory containing the Swift code as a target.
90-
- In the target defining your Swift target, add a`dependencies` to the C++ Module, the `path`, `source`, and `swiftSettings` with `unsafeFlags` with the source to the C++ Module, and enable `-enable-experimental-cxx-interop`
84+
- In the target defining your Swift target, add a`dependencies` to the C++ Module, the `path`, `source`, and `swiftSettings` with `unsafeFlags` with the source to the C++ Module, and enable `-cxx-interoperability-mode=swift-5.9`
9185

9286
```
9387
//In Package Manifest
@@ -117,7 +111,7 @@ let package = Package(
117111
sources: [ "main.swift" ],
118112
swiftSettings: [.unsafeFlags([
119113
"-I", "Sources/CxxTest",
120-
"-enable-experimental-cxx-interop",
114+
"-cxx-interoperability-mode=swift-5.9",
121115
])]
122116
),
123117
]
@@ -150,7 +144,7 @@ After creating your project follow the steps [Creating a Module to contain your
150144
- Create a `CMakeLists.txt` file and configure for your project
151145
- In`add_library` invoke `cxx-support` with the path to the C++ implementation file
152146
- Add the `target_include_directories` with `cxx-support` and path to the C++ Module `${CMAKE_SOURCE_DIR}/Sources/CxxTest`
153-
- Add the `add_executable` to the specific files/directory you would like to generate source, with`SHELL:-enable-experimental-cxx-interop`.
147+
- Add the `add_executable` to the specific files/directory you would like to generate source, with`SHELL:-cxx-interoperability-mode=swift-5.9`.
154148
- In the example below we will be following the file structure used in [Creating a Swift Package](#Creating-a-Swift-Package)
155149

156150
```
@@ -173,7 +167,7 @@ target_include_directories(cxx-support PUBLIC
173167
174168
add_executable(CxxInterop ./Sources/CxxInterop/main.swift)
175169
target_compile_options(CxxInterop PRIVATE
176-
"SHELL:-enable-experimental-cxx-interop"
170+
"SHELL:-cxx-interoperability-mode=swift-5.9"
177171
target_link_libraries(CxxInterop PRIVATE cxx-support)
178172
179173
```

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,21 @@ REMARK(warning_in_access_notes_file,none,
513513

514514
WARNING(compiler_plugin_not_loaded,none,
515515
"compiler plugin not loaded: %0; loader error: %1", (StringRef, StringRef))
516+
517+
ERROR(dont_enable_interop_and_compat,none,
518+
"do not pass both -enable-experimental-cxx-interop and "
519+
"-cxx-interoperability-mode. Remove -enable-experimental-cxx-interop.", ())
520+
521+
ERROR(invalid_interop_compat_mode,none,
522+
"invalid option passed to -cxx-interoperability-mode. Please select either "
523+
"'off' or 'swift-5.9'.", ())
524+
NOTE(swift_will_maintain_compat,none,
525+
"Swift will maintain source compatibility for imported APIs based on the "
526+
"selected compatibility mode, so updating the Swift compiler will not "
527+
"change how APIs are imported.", ())
528+
WARNING(enable_interop_flag_deprecated,none,
529+
"the -enable-experimental-cxx-interop flag is deprecated. Please pass "
530+
"'-cxx-interoperability-mode=' instead.", ())
516531

517532
#define UNDEFINE_DIAGNOSTIC_MACROS
518533
#include "DefineDiagnosticMacros.h"

include/swift/Option/Options.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,15 @@ def enable_experimental_concise_pound_file : Flag<["-"],
663663

664664
def enable_experimental_cxx_interop :
665665
Flag<["-"], "enable-experimental-cxx-interop">,
666-
Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>,
666+
Flags<[NoDriverOption, FrontendOption, HelpHidden, ModuleInterfaceOption]>,
667667
HelpText<"Enable experimental C++ interop code generation and config directives">;
668668

669+
def cxx_interoperability_mode :
670+
Joined<["-"], "cxx-interoperability-mode=">,
671+
Flags<[FrontendOption, ModuleInterfaceOption]>,
672+
HelpText<"Enables C++ interoperability; requires compatbility version to be "
673+
"specified.">;
674+
669675
def experimental_c_foreign_reference_types :
670676
Flag<["-"], "experimental-c-foreign-reference-types">,
671677
Flags<[FrontendOption, HelpHidden, ModuleInterfaceOption]>,

lib/Driver/ToolChains.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
305305
inputArgs.AddLastArg(arguments, options::OPT_library_level);
306306
inputArgs.AddLastArg(arguments, options::OPT_enable_bare_slash_regex);
307307
inputArgs.AddLastArg(arguments, options::OPT_enable_experimental_cxx_interop);
308+
inputArgs.AddLastArg(arguments, options::OPT_cxx_interoperability_mode);
308309
inputArgs.AddLastArg(arguments, options::OPT_load_plugin_library);
309310
inputArgs.AddLastArg(arguments, options::OPT_load_plugin_executable);
310311
inputArgs.AddLastArg(arguments, options::OPT_enable_builtin_module);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,20 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
429429
}
430430
}
431431

432+
enum class CxxCompatMode {
433+
invalid,
434+
enabled,
435+
off
436+
};
437+
438+
static CxxCompatMode validateCxxInteropCompatibilityMode(StringRef mode) {
439+
if (mode == "off")
440+
return CxxCompatMode::off;
441+
if (mode == "swift-5.9")
442+
return CxxCompatMode::enabled;
443+
return CxxCompatMode::invalid;
444+
}
445+
432446
static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
433447
DiagnosticEngine &Diags,
434448
const FrontendOptions &FrontendOpts) {
@@ -899,7 +913,26 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
899913
Opts.ClangTarget = llvm::Triple(A->getValue());
900914
}
901915

902-
Opts.EnableCXXInterop |= Args.hasArg(OPT_enable_experimental_cxx_interop);
916+
if (Arg *A = Args.getLastArg(OPT_cxx_interoperability_mode)) {
917+
if (Args.hasArg(OPT_enable_experimental_cxx_interop)) {
918+
Diags.diagnose(SourceLoc(), diag::dont_enable_interop_and_compat);
919+
}
920+
921+
auto interopCompatMode = validateCxxInteropCompatibilityMode(A->getValue());
922+
Opts.EnableCXXInterop |= (interopCompatMode == CxxCompatMode::enabled);
923+
924+
if (interopCompatMode == CxxCompatMode::invalid) {
925+
Diags.diagnose(SourceLoc(), diag::invalid_interop_compat_mode);
926+
Diags.diagnose(SourceLoc(), diag::swift_will_maintain_compat);
927+
}
928+
}
929+
930+
if (Args.hasArg(OPT_enable_experimental_cxx_interop)) {
931+
Diags.diagnose(SourceLoc(), diag::enable_interop_flag_deprecated);
932+
Diags.diagnose(SourceLoc(), diag::swift_will_maintain_compat);
933+
Opts.EnableCXXInterop |= true;
934+
}
935+
903936
Opts.EnableObjCInterop =
904937
Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
905938
Target.isOSDarwin());
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop 2>&1 | %FileCheck %s
4+
5+
//--- Inputs/module.modulemap
6+
module Test {
7+
header "test.h"
8+
requires cplusplus
9+
}
10+
11+
//--- Inputs/test.h
12+
13+
14+
//--- test.swift
15+
16+
import Test
17+
18+
// CHECK: warning: the -enable-experimental-cxx-interop flag is deprecated. Please pass '-cxx-interoperability-mode=' instead.
19+
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -cxx-interoperability-mode=swift-5.9 2>&1 | %FileCheck %s
4+
5+
//--- Inputs/module.modulemap
6+
module Test {
7+
header "test.h"
8+
requires cplusplus
9+
}
10+
11+
//--- Inputs/test.h
12+
13+
//--- test.swift
14+
15+
import Test
16+
17+
// CHECK: error: do not pass both -enable-experimental-cxx-interop and -cxx-interoperability-mode. Remove -enable-experimental-cxx-interop.
18+
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -cxx-interoperability-mode=swift-5.8 2>&1 | %FileCheck %s
4+
5+
//--- Inputs/module.modulemap
6+
module Test {
7+
header "test.h"
8+
requires cplusplus
9+
}
10+
11+
//--- Inputs/test.h
12+
13+
//--- test.swift
14+
15+
import Test
16+
17+
// CHECK: error: invalid option passed to -cxx-interoperability-mode. Please select either 'off' or 'swift-5.9'.
18+
// CHECK: note: Swift will maintain source compatibility for imported APIs based on the selected compatibility mode, so updating the Swift compiler will not change how APIs are imported.

test/lit.cfg

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,8 @@ elif swift_test_mode == 'with_cxx_interop':
727727
config.available_features.add("nonexecutable_test")
728728
config.available_features.add("executable_test")
729729
config.available_features.add("with_cxx_interop")
730-
config.swift_frontend_test_options += ' -enable-experimental-cxx-interop'
731-
config.swift_driver_test_options += ' -Xfrontend -enable-experimental-cxx-interop'
730+
config.swift_frontend_test_options += ' -cxx-interoperability-mode=swift-5.9'
731+
config.swift_driver_test_options += ' -cxx-interoperability-mode=swift-5.9'
732732
else:
733733
lit_config.fatal("Unknown test mode %r" % swift_test_mode)
734734

@@ -2381,7 +2381,7 @@ config.substitutions.insert(0, ('%check-cxx-header-in-clang',
23812381
config.substitutions.append(('%env-', config.target_env_prefix))
23822382

23832383
config.substitutions.append(('%target-clangxx', '%s -std=c++11' % config.target_clang))
2384-
config.substitutions.append(('%target-swiftxx-frontend', '%s -enable-experimental-cxx-interop' % config.target_swift_frontend))
2384+
config.substitutions.append(('%target-swiftxx-frontend', '%s -cxx-interoperability-mode=swift-5.9' % config.target_swift_frontend))
23852385

23862386
config.substitutions.append(('%target-runtime', config.target_runtime))
23872387

0 commit comments

Comments
 (0)