Skip to content

Commit 3ea5087

Browse files
committed
Add Swift compilation flags to enable Clang's validate-per-build-session module behavior
Add '-validate-clang-modules-once' and '-clang-build-session-file' corresponding to Clang's '-fmodules-validate-once-per-build-session' and '-fbuild-session-file='. Ensure they are propagated to module interface build sub-invocations. We require these to be first-class Swift options in order to ensure they are propagated to both: ClangImporter and implicit interface build compiler sub-invocations. Compiler portion of rdar://105982120
1 parent a64fc3b commit 3ea5087

File tree

9 files changed

+104
-0
lines changed

9 files changed

+104
-0
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ ERROR(error_mode_requires_one_sil_multi_sib,none,
221221
"this mode requires .sil for primary-file and only .sib for other inputs",
222222
())
223223

224+
ERROR(error_clang_validate_once_requires_session_file,none,
225+
"'-validate-clang-modules-once' also requires a '-clang-build-session-file' argument",
226+
())
227+
224228
ERROR(error_no_output_filename_specified,none,
225229
"an %0 filename was not specified for a mode which requires an "
226230
"%0 filename", (StringRef))

include/swift/Basic/LangOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,14 @@ namespace swift {
783783
/// Disable validating the persistent PCH.
784784
bool PCHDisableValidation = false;
785785

786+
/// Don't verify input files for Clang modules if the module has been
787+
/// successfully validated or loaded during this build session.
788+
bool ValidateModulesOnce = false;
789+
790+
/// Use the last modification time of this file as the underlying Clang
791+
/// build session timestamp.
792+
std::string BuildSessionFilePath;
793+
786794
/// \see Mode
787795
enum class Modes : uint8_t {
788796
/// Set up Clang for importing modules into Swift and generating IR from

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
550550
void
551551
inheritOptionsForBuildingInterface(const SearchPathOptions &SearchPathOpts,
552552
const LangOptions &LangOpts,
553+
const ClangImporterOptions &clangImporterOpts,
553554
bool suppressRemarks,
554555
RequireOSSAModules_t requireOSSAModules);
555556
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,

include/swift/Option/Options.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ def no_strict_implicit_module_context :
178178
Flags<[FrontendOption, HelpHidden]>,
179179
HelpText<"Disable the strict forwarding of compilation context to downstream implicit module dependencies">;
180180

181+
def validate_clang_modules_once :
182+
Flag<["-"], "validate-clang-modules-once">,
183+
Flags<[FrontendOption]>,
184+
HelpText<"Don't verify input files for Clang modules if the module has been successfully validated or loaded during this build session">;
185+
186+
def clang_build_session_file : Separate<["-"], "clang-build-session-file">,
187+
Flags<[FrontendOption, ArgumentIsPath]>,
188+
HelpText<"Use the last modification time of <file> as the underlying Clang build session timestamp">;
189+
181190
def disallow_forwarding_driver :
182191
Flag<["-"], "disallow-use-new-driver">, Flags<[]>,
183192
HelpText<"Disable using new swift-driver">;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,11 @@ importer::addCommonInvocationArguments(
810810
invocationArgStrs.push_back("-Xclang");
811811
invocationArgStrs.push_back("-no-opaque-pointers");
812812

813+
if (importerOpts.ValidateModulesOnce) {
814+
invocationArgStrs.push_back("-fmodules-validate-once-per-build-session");
815+
invocationArgStrs.push_back("-fbuild-session-file=" + importerOpts.BuildSessionFilePath);
816+
}
817+
813818
for (auto extraArg : importerOpts.ExtraArgs) {
814819
invocationArgStrs.push_back(extraArg);
815820
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,15 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
12201220
return HadError;
12211221
}
12221222

1223+
static bool ValidateModulesOnceOptions(const ClangImporterOptions &Opts,
1224+
DiagnosticEngine &Diags) {
1225+
if (Opts.ValidateModulesOnce && Opts.BuildSessionFilePath.empty()) {
1226+
Diags.diagnose(SourceLoc(), diag::error_clang_validate_once_requires_session_file);
1227+
return true;
1228+
}
1229+
return false;
1230+
}
1231+
12231232
static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
12241233
ArgList &Args,
12251234
DiagnosticEngine &Diags,
@@ -1314,6 +1323,12 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
13141323
Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation);
13151324
}
13161325

1326+
Opts.ValidateModulesOnce |= Args.hasArg(OPT_validate_clang_modules_once);
1327+
if (auto *A = Args.getLastArg(OPT_clang_build_session_file))
1328+
Opts.BuildSessionFilePath = A->getValue();
1329+
if (ValidateModulesOnceOptions(Opts, Diags))
1330+
return true;
1331+
13171332
if (Args.hasFlag(options::OPT_warnings_as_errors,
13181333
options::OPT_no_warnings_as_errors, false))
13191334
Opts.ExtraArgs.push_back("-Werror");

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,7 @@ void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames(
14481448

14491449
void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
14501450
const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts,
1451+
const ClangImporterOptions &clangImporterOpts,
14511452
bool suppressRemarks, RequireOSSAModules_t RequireOSSAModules) {
14521453
GenericArgs.push_back("-frontend");
14531454
// Start with a genericSubInvocation that copies various state from our
@@ -1544,6 +1545,16 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
15441545
genericSubInvocation.getLangOptions().Features.insert(
15451546
Feature::LayoutPrespecialization);
15461547
}
1548+
1549+
// Validate Clang modules once perbuild session flags must be consistent
1550+
// across all module sub-invocations
1551+
if (clangImporterOpts.ValidateModulesOnce) {
1552+
genericSubInvocation.getClangImporterOptions().ValidateModulesOnce = true;
1553+
genericSubInvocation.getClangImporterOptions().BuildSessionFilePath = clangImporterOpts.BuildSessionFilePath;
1554+
GenericArgs.push_back("-validate-clang-modules-once");
1555+
GenericArgs.push_back("-clang-build-session-file");
1556+
GenericArgs.push_back(clangImporterOpts.BuildSessionFilePath);
1557+
}
15471558
}
15481559

15491560
bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs(
@@ -1586,6 +1597,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
15861597
: SM(SM), Diags(Diags), ArgSaver(Allocator) {
15871598
genericSubInvocation.setMainExecutablePath(LoaderOpts.mainExecutablePath);
15881599
inheritOptionsForBuildingInterface(searchPathOpts, langOpts,
1600+
clangImporterOpts,
15891601
Diags->getSuppressRemarks(),
15901602
requireOSSAModules);
15911603
// Configure front-end input.
@@ -1621,6 +1633,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
16211633
genericSubInvocation.getLangOptions().EnableAppExtensionRestrictions = true;
16221634
GenericArgs.push_back("-application-extension");
16231635
}
1636+
16241637
// Save the parent invocation's Target Triple
16251638
ParentInvocationTarget = langOpts.Target;
16261639

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: touch %t/Build.session
3+
// RUN: %swift %s -typecheck -dump-clang-diagnostics -validate-clang-modules-once -clang-build-session-file %t/Build.session 2>&1 | %FileCheck %s
4+
5+
public func foo() {}
6+
7+
// CHECK: '-fmodules-validate-once-per-build-session'
8+
// CHECK: '-fbuild-session-file=
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// This test ensures that the parent invocation's '-validate-clang-modules-once' flag is inherited when building dependency modules
2+
// RUN: %empty-directory(%t)
3+
// RUN: touch %t/Build.session
4+
5+
// RUN: %target-build-swift -module-name TestModule -module-link-name TestModule %S/Inputs/TestModule.swift -enable-library-evolution -emit-module-interface -o %t/TestModule.swiftmodule -swift-version 5 -Xfrontend -disable-implicit-concurrency-module-import -Xfrontend -disable-implicit-string-processing-module-import
6+
7+
// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I%t -validate-clang-modules-once -clang-build-session-file %t/Build.session -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import
8+
// RUN: %FileCheck %s < %t/deps.json
9+
10+
import TestModule
11+
12+
// CHECK: "directDependencies": [
13+
// CHECK-NEXT: {
14+
// CHECK-DAG: "swift": "TestModule"
15+
// CHECK-DAG: "swift": "Swift"
16+
// CHECK-DAG: "swift": "SwiftOnoneSupport"
17+
18+
// CHECK: "swift": "TestModule"
19+
// CHECK-NEXT: },
20+
// CHECK-NEXT: {
21+
// CHECK-NEXT: "modulePath": "{{.*}}TestModule-{{.*}}.swiftmodule",
22+
// CHECK-NEXT: "sourceFiles": [
23+
// CHECK-NEXT: ],
24+
// CHECK-NEXT: "directDependencies": [
25+
// CHECK-NEXT: {
26+
// CHECK-NEXT: "swift": "Swift"
27+
// CHECK-NEXT: },
28+
// CHECK-NEXT: {
29+
// CHECK-NEXT: "swift": "SwiftOnoneSupport"
30+
// CHECK-NEXT: }
31+
// CHECK-NEXT: ],
32+
// CHECK-NEXT: "details": {
33+
// CHECK-NEXT: "swift": {
34+
// CHECK-NEXT: "moduleInterfacePath":
35+
// CHECK-NEXT: "contextHash":
36+
// CHECK-NEXT: "commandLine": [
37+
// CHECK-NEXT: "-frontend",
38+
// CHECK-NEXT: "-compile-module-from-interface",
39+
// CHECK: "-validate-clang-modules-once",
40+
// CHECK-NEXT: "-clang-build-session-file",
41+
// CHECK-NEXT: "{{.*}}Build.session"

0 commit comments

Comments
 (0)