Skip to content

Commit 940330b

Browse files
committed
Produce an error when multiple -o options are specified in multi-threading mode
Causing the behavior to be analagous to the Legacy driver's here: https://github.com/apple/swift/blob/main/lib/Driver/Driver.cpp#L2415 Otherwise, this isn't a supported flow and leads to driver crashes downstream. Resolves rdar://79171618
1 parent 1b03427 commit 940330b

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public struct Driver {
2424
case relativeFrontendPath(String)
2525
case subcommandPassedToDriver
2626
case integratedReplRemoved
27+
case cannotSpecify_OForMultipleOutputs
2728
case conflictingOptions(Option, Option)
2829
case unableToLoadOutputFileMap(String)
2930
case unableToDecodeFrontendTargetInfo(String?, [String], String)
@@ -57,6 +58,8 @@ public struct Driver {
5758
return "subcommand passed to driver"
5859
case .integratedReplRemoved:
5960
return "Compiler-internal integrated REPL has been removed; use the LLDB-enhanced REPL instead."
61+
case .cannotSpecify_OForMultipleOutputs:
62+
return "cannot specify -o when generating multiple output files"
6063
case .conflictingOptions(let one, let two):
6164
return "conflicting options '\(one.spelling)' and '\(two.spelling)'"
6265
case let .unableToDecodeFrontendTargetInfo(outputString, arguments, errorDesc):
@@ -679,6 +682,8 @@ public struct Driver {
679682
compilerMode: compilerMode,
680683
outputFileMap: self.outputFileMap,
681684
moduleName: moduleOutputInfo.name)
685+
686+
try verifyOutputOptions()
682687
}
683688

684689
public mutating func planBuild( simulateGetInputFailure: Bool = false ) throws -> [Job] {
@@ -765,6 +770,29 @@ extension Driver {
765770
}
766771
}
767772

773+
extension Driver {
774+
// Detect mis-use of multi-threading and output file options
775+
private func verifyOutputOptions() throws {
776+
if compilerOutputType != .swiftModule,
777+
parsedOptions.hasArgument(.o),
778+
linkerOutputType == nil {
779+
let shouldComplain: Bool
780+
if numThreads > 0 {
781+
// Multi-threading compilation has multiple outputs unless there's only
782+
// one input.
783+
shouldComplain = self.inputFiles.count > 1
784+
} else {
785+
// Single-threaded compilation is a problem if we're compiling more than
786+
// one file.
787+
shouldComplain = self.inputFiles.filter { $0.type.isPartOfSwiftCompilation }.count > 1 && .singleCompile != compilerMode
788+
}
789+
if shouldComplain {
790+
diagnosticEngine.emit(Error.cannotSpecify_OForMultipleOutputs)
791+
}
792+
}
793+
}
794+
}
795+
768796
// MARK: - Response files.
769797
extension Driver {
770798
/// Tokenize a single line in a response file.

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ extension Driver {
8585
-> ([Job], IncrementalCompilationState?) {
8686
precondition(compilerMode.isStandardCompilationForPlanning,
8787
"compiler mode \(compilerMode) is handled elsewhere")
88-
8988
// Determine the initial state for incremental compilation that is required during
9089
// the planning process. This state contains the module dependency graph and
9190
// cross-module dependency information.

Sources/SwiftDriverExecution/MultiJobExecutor.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ public final class MultiJobExecutor {
191191
to producerMap: inout [VirtualPath.Handle: Int]
192192
) {
193193
for output in job.outputs {
194-
if let otherJobIndex = producerMap.updateValue(index, forKey: output.fileHandle) {
194+
if output.file != .standardOutput,
195+
let otherJobIndex = producerMap.updateValue(index, forKey: output.fileHandle) {
195196
fatalError("multiple producers for output \(output.file): \(job) & \(knownJobs[otherJobIndex])")
196197
}
197198
producerMap[output.fileHandle] = index

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ final class SwiftDriverTests: XCTestCase {
314314
}
315315
}
316316

317+
func testMultiThreadingOutputs() throws {
318+
try assertDriverDiagnostics(args: "swiftc", "-c", "foo.swift", "bar.swift", "-o", "bar.ll", "-o", "foo.ll", "-num-threads", "2", "-whole-module-optimization") {
319+
$1.expect(.error("cannot specify -o when generating multiple output files"))
320+
}
321+
322+
try assertDriverDiagnostics(args: "swiftc", "-c", "foo.swift", "bar.swift", "-o", "bar.ll", "-o", "foo.ll", "-num-threads", "0") {
323+
$1.expect(.error("cannot specify -o when generating multiple output files"))
324+
}
325+
}
326+
317327
func testBaseOutputPaths() throws {
318328
// Test the combination of -c and -o includes the base output path.
319329
do {

0 commit comments

Comments
 (0)