Skip to content

Commit 5752f44

Browse files
authored
Merge pull request #1100 from nkcsgexi/unknown-promote
ParsedOptions: save unknown driver flags that are recognizable for swift-frontend
2 parents 4cd8d6f + d3db5ad commit 5752f44

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)