Frontend: Require -language-mode option when emitting swiftinterfaces.

If a `.swiftinterface` file does not include an explicit `-language-mode`
option (or its predecessor `swift-version`) and needs to be built as a
dependency of a client compilation, then the invocation to build the module
from interface would end up inheriting the language mode that the client code
is built with. This can result in spurious type checking diagnostics or even
mis-compilation. To ensure that a module interface is always built using the
language mode that its source code was originally built with, require an
explicit `-language-mode` option when emitting swiftinterface files.

Resolves rdar://145168219.
This commit is contained in:
Allan Shortlidge
2025-09-11 16:31:55 -07:00
parent 014ed51ab1
commit 13d61b0709
4 changed files with 36 additions and 2 deletions

View File

@@ -156,6 +156,9 @@ ERROR(error_load_resolved_plugin,none,
NOTE(note_valid_swift_versions, none,
"valid arguments to '-swift-version' are %0", (StringRef))
ERROR(error_module_interface_requires_language_mode,none,
"emitting module interface files requires '-language-mode'", ())
ERROR(error_mode_cannot_emit_dependencies,none,
"this mode does not support emitting dependency files", ())
ERROR(error_mode_cannot_emit_reference_dependencies,none,

View File

@@ -1034,6 +1034,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
if (!isValid)
diagnoseSwiftVersion(vers, A, Args, Diags);
} else if (FrontendOpts.InputsAndOutputs.hasModuleInterfaceOutputPath()) {
Diags.diagnose({}, diag::error_module_interface_requires_language_mode);
HadError = true;
}
if (auto A = Args.getLastArg(OPT_package_description_version)) {

View File

@@ -9,12 +9,13 @@
// CHECK-NOWARN-NOT: warning
// RUN: %swift-ide-test_plain -test-createCompilerInvocation \
// RUN: -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
// RUN: -swift-version 5 -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
// RUN: 2>&1 | %FileCheck %s --check-prefix=NORMAL_ARGS --implicit-check-not="error: "
// NORMAL_ARGS: Frontend Arguments BEGIN
// NORMAL_ARGS-DAG: -o{{$}}
// NORMAL_ARGS-DAG: foo-{{[a-z0-9]+}}.o
// NORMAL_ARGS-DAG: -c{{$}}
// NORMAL_ARGS-DAG: -swift-version
// NORMAL_ARGS-DAG: -module-name
// NORMAL_ARGS-DAG: -emit-module-path
// NORMAL_ARGS-DAG: -emit-module-doc-path
@@ -26,7 +27,7 @@
// NORMAL_ARGS: Frontend Arguments END
// RUN: %swift-ide-test_plain -test-createCompilerInvocation -force-no-outputs \
// RUN: -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
// RUN: -swift-version 5 -module-name foo -emit-module -emit-module-path %t/foo.swiftmodule -emit-objc-header -emit-objc-header-path %t/foo.h -enable-library-evolution -emit-module-interface -emit-module-interface-path %t/foo.swiftinterface -emit-library -emit-tbd -emit-tbd-path %t/foo.tbd -emit-dependencies -serialize-diagnostics %s \
// RUN: 2>&1 > %t.nooutput_args
// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS --implicit-check-not="error: " < %t.nooutput_args
// RUN: %FileCheck %s --check-prefix=NOOUTPUT_ARGS_NEG --implicit-check-not="error: " < %t.nooutput_args

View File

@@ -0,0 +1,27 @@
// RUN: %empty-directory(%t)
// RUN: not %swift_frontend_plain -target %target-swift-5.1-abi-triple %s \
// RUN: -enable-library-evolution -module-name Test \
// RUN: -emit-module-interface-path %t.swiftinterface \
// RUN: -emit-module -o /dev/null 2>&1 | %FileCheck %s
// CHECK: <unknown>:0: error: emitting module interface files requires '-language-mode'
// RUN: %swift_frontend_plain -target %target-swift-5.1-abi-triple %s \
// RUN: -enable-library-evolution -module-name Test \
// RUN: -emit-module-interface-path %t.swiftinterface \
// RUN: -emit-module -o /dev/null -language-mode 5
// RUN: %FileCheck %s --check-prefix CHECK-SWIFTINTERFACE < %t.swiftinterface
// RUN: %swift_frontend_plain -target %target-swift-5.1-abi-triple %s \
// RUN: -enable-library-evolution -module-name Test \
// RUN: -emit-module-interface-path %t.swiftinterface \
// RUN: -emit-module -o /dev/null -swift-version 5
// RUN: %FileCheck %s --check-prefix CHECK-SWIFTINTERFACE < %t.swiftinterface
// CHECK-SWIFTINTERFACE: swift-module-flags:
// CHECK-SWIFTINTERFACE-SAME: -enable-library-evolution
// CHECK-SWIFTINTERFACE-SAME: -module-name Test
// CHECK-SWIFTINTERFACE-SAME: {{-swift-version|-language-mode}} 5