Skip to content

Commit f0b22be

Browse files
authored
Merge pull request #713 from artemcm/55AllowMultipleStdOutOutputs
[5.5] Produce an error when multiple `-o` options are specified in multi-threading mode
2 parents c30642d + 940330b commit f0b22be

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):
@@ -693,6 +696,8 @@ public struct Driver {
693696
compilerMode: compilerMode,
694697
outputFileMap: self.outputFileMap,
695698
moduleName: moduleOutputInfo.name)
699+
700+
try verifyOutputOptions()
696701
}
697702

698703
public mutating func planBuild( simulateGetInputFailure: Bool = false ) throws -> [Job] {
@@ -779,6 +784,29 @@ extension Driver {
779784
}
780785
}
781786

787+
extension Driver {
788+
// Detect mis-use of multi-threading and output file options
789+
private func verifyOutputOptions() throws {
790+
if compilerOutputType != .swiftModule,
791+
parsedOptions.hasArgument(.o),
792+
linkerOutputType == nil {
793+
let shouldComplain: Bool
794+
if numThreads > 0 {
795+
// Multi-threading compilation has multiple outputs unless there's only
796+
// one input.
797+
shouldComplain = self.inputFiles.count > 1
798+
} else {
799+
// Single-threaded compilation is a problem if we're compiling more than
800+
// one file.
801+
shouldComplain = self.inputFiles.filter { $0.type.isPartOfSwiftCompilation }.count > 1 && .singleCompile != compilerMode
802+
}
803+
if shouldComplain {
804+
diagnosticEngine.emit(Error.cannotSpecify_OForMultipleOutputs)
805+
}
806+
}
807+
}
808+
}
809+
782810
// MARK: - Response files.
783811
extension Driver {
784812
/// 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)