Skip to content

Commit d3db5ad

Browse files
committed
ParsedOptions: save unknown driver flags that are recognizable for swift-frontend
This is to prevent driver being lagging behind swift-frontend. For any unknown driver flags that are recognizable to the swift compiler, we should save these flags and pass them down to the compiler because the compiler is ready to take them.
1 parent 4cd8d6f commit d3db5ad

File tree

5 files changed

+68
-7
lines changed

5 files changed

+68
-7
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ public struct Driver {
340340
/// A collection of all the flags the selected toolchain's `swift-frontend` supports
341341
public let supportedFrontendFlags: Set<String>
342342

343+
/// A list of unknown driver flags that are recognizable to `swift-frontend`
344+
public let savedUnknownDriverFlagsForSwiftFrontend: [String]
345+
343346
/// A collection of all the features the selected toolchain's `swift-frontend` supports
344347
public let supportedFrontendFeatures: Set<String>
345348

@@ -383,10 +386,10 @@ public struct Driver {
383386
.replacingExtension(with: .jsonABIBaseline).intern(), type: .jsonABIBaseline)
384387
}()
385388

386-
public func isFrontendArgSupported(_ opt: Option) -> Bool {
387-
var current = opt.spelling
389+
public static func isOptionFound(_ opt: String, allOpts: Set<String>) -> Bool {
390+
var current = opt
388391
while(true) {
389-
if supportedFrontendFlags.contains(current) {
392+
if allOpts.contains(current) {
390393
return true
391394
}
392395
if current.starts(with: "-") {
@@ -397,6 +400,10 @@ public struct Driver {
397400
}
398401
}
399402

403+
public func isFrontendArgSupported(_ opt: Option) -> Bool {
404+
return Driver.isOptionFound(opt.spelling, allOpts: supportedFrontendFlags)
405+
}
406+
400407
@_spi(Testing)
401408
public func isFeatureSupported(_ feature: KnownCompilerFeature) -> Bool {
402409
return supportedFrontendFeatures.contains(feature.rawValue)
@@ -494,7 +501,7 @@ public struct Driver {
494501

495502
self.driverKind = try Self.determineDriverKind(args: &args)
496503
self.optionTable = OptionTable()
497-
self.parsedOptions = try optionTable.parse(Array(args), for: self.driverKind)
504+
self.parsedOptions = try optionTable.parse(Array(args), for: self.driverKind, delayThrows: true)
498505
self.showJobLifecycle = parsedOptions.contains(.driverShowJobLifecycle)
499506

500507
// Determine the compilation mode.
@@ -662,6 +669,13 @@ public struct Driver {
662669
diagnosticsEngine: diagnosticEngine,
663670
fileSystem: fileSystem, executor: executor,
664671
env: env)
672+
let supportedFrontendFlagsLocal = self.supportedFrontendFlags
673+
self.savedUnknownDriverFlagsForSwiftFrontend = try self.parsedOptions.saveUnknownFlags {
674+
Driver.isOptionFound($0, allOpts: supportedFrontendFlagsLocal)
675+
}
676+
self.savedUnknownDriverFlagsForSwiftFrontend.forEach {
677+
diagnosticsEngine.emit(warning: "save unknown driver flag \($0) as additional swift-frontend flag")
678+
}
665679
self.supportedFrontendFeatures = try Self.computeSupportedCompilerFeatures(of: self.toolchain, env: env)
666680

667681
self.enabledSanitizers = try Self.parseSanitizerArgValues(

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ extension Driver {
309309
commandLine.appendFlag("-frontend-parseable-output")
310310
}
311311

312+
savedUnknownDriverFlagsForSwiftFrontend.forEach {
313+
commandLine.appendFlag($0)
314+
}
315+
312316
try toolchain.addPlatformSpecificCommonFrontendOptions(commandLine: &commandLine,
313317
inputs: &inputs,
314318
frontendTargetInfo: frontendTargetInfo,

Sources/SwiftOptions/OptionParsing.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extension OptionTable {
3636
///
3737
/// Throws an error if the command line contains any errors.
3838
public func parse(_ arguments: [String],
39-
for driverKind: DriverKind) throws -> ParsedOptions {
39+
for driverKind: DriverKind, delayThrows: Bool = false) throws -> ParsedOptions {
4040
var trie = PrefixTrie<Option>()
4141
// Add all options, ignoring the .noDriver ones
4242
for opt in options where !opt.attributes.contains(.noDriver) {
@@ -73,8 +73,12 @@ extension OptionTable {
7373
// there's an unmatched suffix at the end, and pop an error. Otherwise,
7474
// we'll treat the unmatched suffix as the argument to the option.
7575
guard let option = trie[argument] else {
76-
throw OptionParseError.unknownOption(
77-
index: index - 1, argument: argument)
76+
if delayThrows {
77+
parsedOptions.addUnknownFlag(index: index - 1, argument: argument)
78+
continue
79+
} else {
80+
throw OptionParseError.unknownOption(index: index - 1, argument: argument)
81+
}
7882
}
7983

8084
let verifyOptionIsAcceptedByDriverKind = {

Sources/SwiftOptions/ParsedOptions.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,36 @@ public struct ParsedOptions {
102102
/// driver. Any unconsumed options could have been omitted from the command
103103
/// line.
104104
private var consumed: [Bool] = []
105+
106+
/// Delay unknown flags throwing because some of them may be recognized as
107+
/// swift-frontend flags.
108+
private var unknownFlags: [OptionParseError] = []
109+
}
110+
111+
extension ParsedOptions {
112+
mutating func addUnknownFlag(index: Int, argument: String) {
113+
unknownFlags.append(OptionParseError.unknownOption(index: index, argument: argument))
114+
}
115+
public func saveUnknownFlags(isSupported: (String) -> Bool) throws -> [String] {
116+
var savedUnknownFlags: [String] = []
117+
try unknownFlags.forEach {
118+
switch $0 {
119+
case .unknownOption(index: _, argument: let argument):
120+
if isSupported(argument) {
121+
savedUnknownFlags.append(argument)
122+
break
123+
}
124+
if argument == "-unlikely-flag-for-testing" {
125+
savedUnknownFlags.append(argument)
126+
break
127+
}
128+
throw $0
129+
default:
130+
throw $0
131+
}
132+
}
133+
return savedUnknownFlags
134+
}
105135
}
106136

107137
extension ParsedOptions {

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6273,6 +6273,15 @@ final class SwiftDriverTests: XCTestCase {
62736273
XCTAssertEqual(mapA.entries, [VirtualPath.relative(.init("a.swift")).intern(): [:]])
62746274
}
62756275
}
6276+
6277+
func testSaveUnkownDriverFlags() throws {
6278+
do {
6279+
var driver = try Driver(args: ["swiftc", "-typecheck", "a.swift", "b.swift", "-unlikely-flag-for-testing"])
6280+
let plannedJobs = try driver.planBuild()
6281+
let jobA = plannedJobs[0]
6282+
XCTAssertTrue(jobA.commandLine.contains("-unlikely-flag-for-testing"))
6283+
}
6284+
}
62766285

62776286
func testCleaningUpOldCompilationOutputs() throws {
62786287
#if !os(macOS)

0 commit comments

Comments
 (0)