Skip to content

Add Swift compilation flags to enable Clang's validate-per-build-session module behavior #1302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ public struct Driver {
workingDirectory: workingDirectory,
diagnosticEngine: diagnosticEngine)
Self.validateEmitDependencyGraphArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
Self.validateValidateClangModulesOnceOptions(&parsedOptions, diagnosticEngine: diagnosticEngine)
Self.validateParseableOutputArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
Self.validateCompilationConditionArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
Self.validateFrameworkSearchPathArgs(&parsedOptions, diagnosticEngine: diagnosticEngine)
Expand Down Expand Up @@ -2701,6 +2702,17 @@ extension Driver {
}
}

static func validateValidateClangModulesOnceOptions(_ parsedOptions: inout ParsedOptions,
diagnosticEngine: DiagnosticsEngine) {
// '-validate-clang-modules-once' requires '-clang-build-session-file'
if parsedOptions.hasArgument(.validateClangModulesOnce) &&
!parsedOptions.hasArgument(.clangBuildSessionFile) {
diagnosticEngine.emit(.error(Error.optionRequiresAnother(Option.validateClangModulesOnce.spelling,
Option.clangBuildSessionFile.spelling)),
location: nil)
}
}

static func validateEmitDependencyGraphArgs(_ parsedOptions: inout ParsedOptions,
diagnosticEngine: DiagnosticsEngine) {
// '-print-explicit-dependency-graph' requires '-explicit-module-build'
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ extension Driver {
commandLine.appendFlag(ver)
}

// Pass down -validate-clang-modules-once if we are working with a compiler that
// supports it.
if isFrontendArgSupported(.validateClangModulesOnce),
isFrontendArgSupported(.clangBuildSessionFile) {
try commandLine.appendLast(.validateClangModulesOnce, from: &parsedOptions)
try commandLine.appendLast(.clangBuildSessionFile, from: &parsedOptions)
}

if let workingDirectory = workingDirectory {
// Add -Xcc -working-directory before any other -Xcc options to ensure it is
// overridden by an explicit -Xcc -working-directory, although having a
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftOptions/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extension Option {
public static let candidateModuleFile: Option = Option("-candidate-module-file", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<path>", helpText: "Specify Swift module may be ready to use for an interface")
public static let checkApiAvailabilityOnly: Option = Option("-check-api-availability-only", .flag, attributes: [.helpHidden, .frontend, .noInteractive], helpText: "Only check the availability of the APIs, ignore function bodies")
public static let checkOnoneCompleteness: Option = Option("-check-onone-completeness", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Print errors if the compile OnoneSupport module is missing symbols")
public static let clangBuildSessionFile: Option = Option("-clang-build-session-file", .separate, attributes: [.frontend, .argumentIsPath], helpText: "Use the last modification time of <file> as the underlying Clang build session timestamp")
public static let clangHeaderExposeDecls: Option = Option("-clang-header-expose-decls=", .joined, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "all-public|has-expose-attr", helpText: "Which declarations should be exposed in the generated clang header.")
public static let clangTarget: Option = Option("-clang-target", .separate, attributes: [.frontend], helpText: "Separately set the target we should use for internal Clang instance")
public static let codeCompleteCallPatternHeuristics: Option = Option("-code-complete-call-pattern-heuristics", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use heuristics to guess whether we want call pattern completions")
Expand Down Expand Up @@ -128,6 +129,7 @@ extension Option {
public static let disableClangimporterSourceImport: Option = Option("-disable-clangimporter-source-import", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable ClangImporter and forward all requests straight the DWARF importer.")
public static let disableCrossModuleOptimization: Option = Option("-disable-cmo", .flag, attributes: [.helpHidden, .frontend], helpText: "Disable cross-module optimization")
public static let disableCollocateMetadataFunctions: Option = Option("-disable-collocate-metadata-functions", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable collocate metadata functions")
public static let disableColocateTypeDescriptors: Option = Option("-disable-colocate-type-descriptors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable colocate type descriptors")
public static let disableConcreteTypeMetadataMangledNameAccessors: Option = Option("-disable-concrete-type-metadata-mangled-name-accessors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable concrete type metadata access by mangled name")
public static let disableConformanceAvailabilityErrors: Option = Option("-disable-conformance-availability-errors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Diagnose conformance availability violations as warnings")
public static let disableConstraintSolverPerformanceHacks: Option = Option("-disable-constraint-solver-performance-hacks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable all the hacks in the constraint solver")
Expand Down Expand Up @@ -321,6 +323,7 @@ extension Option {
public static let enableBridgingPch: Option = Option("-enable-bridging-pch", .flag, attributes: [.helpHidden], helpText: "Enable automatic generation of bridging PCH files")
public static let enableBuiltinModule: Option = Option("-enable-builtin-module", .flag, attributes: [.frontend, .moduleInterface], helpText: "Enables the explicit import of the Builtin module")
public static let enableCollocateMetadataFunctions: Option = Option("-enable-collocate-metadata-functions", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable collocate metadata functions")
public static let enableColocateTypeDescriptors: Option = Option("-enable-colocate-type-descriptors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Enable colocate type descriptors")
public static let enableConformanceAvailabilityErrors: Option = Option("-enable-conformance-availability-errors", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Diagnose conformance availability violations as errors")
public static let copyPropagationStateEQ: Option = Option("-enable-copy-propagation=", .joined, attributes: [.frontend, .noDriver], metaVar: "true|requested-passes-only|false", helpText: "Whether to enable copy propagation")
public static let enableCopyPropagation: Option = Option("-enable-copy-propagation", .flag, attributes: [.frontend, .noDriver], helpText: "Run SIL copy propagation with lexical lifetimes to shorten object lifetimes while preserving variable lifetimes.")
Expand Down Expand Up @@ -714,6 +717,7 @@ extension Option {
public static let useStaticResourceDir: Option = Option("-use-static-resource-dir", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Use resources in the static resource directory")
public static let useTabs: Option = Option("-use-tabs", .flag, attributes: [.noInteractive, .noBatch, .indent], helpText: "Use tabs for indentation.", group: .codeFormatting)
public static let userModuleVersion: Option = Option("-user-module-version", .separate, attributes: [.frontend], metaVar: "<vers>", helpText: "Module version specified from Swift module authors")
public static let validateClangModulesOnce: Option = Option("-validate-clang-modules-once", .flag, attributes: [.frontend], helpText: "Don't verify input files for Clang modules if the module has been successfully validated or loaded during this build session")
public static let validateTbdAgainstIrEQ: Option = Option("-validate-tbd-against-ir=", .joined, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<level>", helpText: "Compare the symbols in the IR against the TBD file that would be generated.")
public static let valueRecursionThreshold: Option = Option("-value-recursion-threshold", .separate, attributes: [.helpHidden, .frontend, .doesNotAffectIncrementalBuild], helpText: "Set the maximum depth for direct recursion in value types")
public static let verifyAdditionalFile: Option = Option("-verify-additional-file", .separate, attributes: [.frontend, .noDriver], helpText: "Verify diagnostics in this file in addition to source files")
Expand Down Expand Up @@ -801,6 +805,7 @@ extension Option {
Option.candidateModuleFile,
Option.checkApiAvailabilityOnly,
Option.checkOnoneCompleteness,
Option.clangBuildSessionFile,
Option.clangHeaderExposeDecls,
Option.clangTarget,
Option.codeCompleteCallPatternHeuristics,
Expand Down Expand Up @@ -877,6 +882,7 @@ extension Option {
Option.disableClangimporterSourceImport,
Option.disableCrossModuleOptimization,
Option.disableCollocateMetadataFunctions,
Option.disableColocateTypeDescriptors,
Option.disableConcreteTypeMetadataMangledNameAccessors,
Option.disableConformanceAvailabilityErrors,
Option.disableConstraintSolverPerformanceHacks,
Expand Down Expand Up @@ -1070,6 +1076,7 @@ extension Option {
Option.enableBridgingPch,
Option.enableBuiltinModule,
Option.enableCollocateMetadataFunctions,
Option.enableColocateTypeDescriptors,
Option.enableConformanceAvailabilityErrors,
Option.copyPropagationStateEQ,
Option.enableCopyPropagation,
Expand Down Expand Up @@ -1463,6 +1470,7 @@ extension Option {
Option.useStaticResourceDir,
Option.useTabs,
Option.userModuleVersion,
Option.validateClangModulesOnce,
Option.validateTbdAgainstIrEQ,
Option.valueRecursionThreshold,
Option.verifyAdditionalFile,
Expand Down
33 changes: 33 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6663,6 +6663,39 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertTrue(job.commandLine.contains(.path(.absolute(try driver.toolchain.executableDir.parentDirectory.appending(components: "lib", "swift", "host", "plugins")))))
}

func testClangModuleValidateOnce() throws {
let flagTest = try Driver(args: ["swiftc", "-typecheck", "foo.swift"])
guard flagTest.isFrontendArgSupported(.clangBuildSessionFile),
flagTest.isFrontendArgSupported(.validateClangModulesOnce) else {
return
}

do {
var driver = try Driver(args: ["swiftc", "-typecheck", "foo.swift"])
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
let job = jobs.first!
XCTAssertFalse(job.commandLine.contains(.flag("-validate-clang-modules-once")))
XCTAssertFalse(job.commandLine.contains(.flag("-clang-build-session-file")))
}

do {
try assertDriverDiagnostics(args: ["swiftc", "-validate-clang-modules-once",
"foo.swift"]) {
$1.expect(.error("'-validate-clang-modules-once' cannot be specified if '-clang-build-session-file' is not present"))
}
}

do {
var driver = try Driver(args: ["swiftc", "-validate-clang-modules-once",
"-clang-build-session-file", "testClangModuleValidateOnce.session",
"foo.swift"])
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
let job = jobs.first!
XCTAssertTrue(job.commandLine.contains(.flag("-validate-clang-modules-once")))
XCTAssertTrue(job.commandLine.contains(.flag("-clang-build-session-file")))
}
}

func testRegistrarLookup() throws {
#if os(Windows)
let SDKROOT: AbsolutePath = localFileSystem.currentWorkingDirectory!.appending(components: "SDKROOT")
Expand Down