Skip to content

Commit a30c4f6

Browse files
authored
Merge pull request #369 from owenv/sanitize-coverage
Add validation for -sanitize-coverage=
2 parents 8f65c26 + b659d04 commit a30c4f6

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,10 @@ public struct Driver {
463463
toolchain: toolchain,
464464
targetInfo: frontendTargetInfo)
465465

466+
Self.validateSanitizerCoverageArgs(&parsedOptions,
467+
anySanitizersEnabled: !enabledSanitizers.isEmpty,
468+
diagnosticsEngine: diagnosticsEngine)
469+
466470
// Supplemental outputs.
467471
self.dependenciesFilePath = try Self.computeSupplementaryOutputPath(
468472
&parsedOptions, type: .dependencies, isOutputOptions: [.emitDependencies],
@@ -1411,7 +1415,7 @@ extension Driver {
14111415
}
14121416

14131417
if !parsedOptions.contains(in: .g) {
1414-
diagnosticsEngine.emit(.error_option_missing_required_argument(option: .debugInfoFormat, requiredArg: .g))
1418+
diagnosticsEngine.emit(.error_option_missing_required_argument(option: .debugInfoFormat, requiredArg: "-g"))
14151419
}
14161420
} else {
14171421
// Default to DWARF.
@@ -1885,6 +1889,28 @@ extension Driver {
18851889
}
18861890
}
18871891
}
1892+
1893+
private static func validateSanitizerCoverageArgs(_ parsedOptions: inout ParsedOptions,
1894+
anySanitizersEnabled: Bool,
1895+
diagnosticsEngine: DiagnosticsEngine) {
1896+
var foundRequiredArg = false
1897+
for arg in parsedOptions.arguments(for: .sanitizeCoverageEQ).flatMap(\.argument.asMultiple) {
1898+
if ["func", "bb", "edge"].contains(arg) {
1899+
foundRequiredArg = true
1900+
} else if !["indirect-calls", "trace-bb", "trace-cmp", "8bit-counters", "trace-pc", "trace-pc-guard"].contains(arg) {
1901+
diagnosticsEngine.emit(.error_unsupported_argument(argument: arg, option: .sanitizeCoverageEQ))
1902+
}
1903+
1904+
if !foundRequiredArg {
1905+
diagnosticsEngine.emit(.error_option_missing_required_argument(option: .sanitizeCoverageEQ,
1906+
requiredArg: #""func", "bb", "edge""#))
1907+
}
1908+
}
1909+
1910+
if parsedOptions.hasArgument(.sanitizeCoverageEQ) && !anySanitizersEnabled {
1911+
diagnosticsEngine.emit(.error_option_requires_sanitizer(option: .sanitizeCoverageEQ))
1912+
}
1913+
}
18881914
}
18891915

18901916
extension Triple {

Sources/SwiftDriver/Utilities/Diagnostics.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,22 @@ extension Diagnostic.Message {
1717
.error("-static may not be used with -emit-executable")
1818
}
1919

20-
static func error_option_missing_required_argument(option: Option, requiredArg: Option) -> Diagnostic.Message {
21-
.error("option '\(option.spelling)' is missing a required argument (\(requiredArg.spelling))")
20+
static func error_option_missing_required_argument(option: Option, requiredArg: String) -> Diagnostic.Message {
21+
.error("option '\(option.spelling)' is missing a required argument (\(requiredArg))")
2222
}
2323

2424
static func error_opt_invalid_mapping(option: Option, value: String) -> Diagnostic.Message {
2525
.error("values for '\(option.spelling)' must be in the format 'original=remapped', but '\(value)' was provided")
2626
}
2727

28+
static func error_unsupported_argument(argument: String, option: Option) -> Diagnostic.Message {
29+
.error("unsupported argument '\(argument)' to option '\(option.spelling)'")
30+
}
31+
32+
static func error_option_requires_sanitizer(option: Option) -> Diagnostic.Message {
33+
.error("option '\(option.spelling)' requires a sanitizer to be enabled. Use -sanitize= to enable a sanitizer")
34+
}
35+
2836
static func error_invalid_arg_value(arg: Option, value: String) -> Diagnostic.Message {
2937
.error("invalid value '\(value)' in '\(arg.spelling)'")
3038
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,23 @@ final class SwiftDriverTests: XCTestCase {
14201420
#endif
14211421
}
14221422

1423+
func testSanitizerCoverageArgs() throws {
1424+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-sanitize=thread", "-sanitize-coverage=bar"]) {
1425+
$1.expect(.error("option '-sanitize-coverage=' is missing a required argument (\"func\", \"bb\", \"edge\")"))
1426+
$1.expect(.error("unsupported argument 'bar' to option '-sanitize-coverage='"))
1427+
}
1428+
1429+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-sanitize=thread", "-sanitize-coverage=func,baz"]) {
1430+
$1.expect(.error("unsupported argument 'baz' to option '-sanitize-coverage='"))
1431+
}
1432+
1433+
try assertDriverDiagnostics(args: ["swiftc", "foo.swift", "-sanitize-coverage=func,trace-cmp"]) {
1434+
$1.expect(.error("option '-sanitize-coverage=' requires a sanitizer to be enabled. Use -sanitize= to enable a sanitizer"))
1435+
}
1436+
1437+
try assertNoDriverDiagnostics(args: "swiftc", "foo.swift", "-sanitize=thread", "-sanitize-coverage=edge,indirect-calls,trace-bb,trace-cmp,8bit-counters")
1438+
}
1439+
14231440
func testBatchModeCompiles() throws {
14241441
do {
14251442
var driver1 = try Driver(args: ["swiftc", "foo1.swift", "bar1.swift", "foo2.swift", "bar2.swift", "foo3.swift", "bar3.swift", "foo4.swift", "bar4.swift", "foo5.swift", "bar5.swift", "wibble.swift", "-module-name", "Test", "-enable-batch-mode", "-driver-batch-count", "3"])

0 commit comments

Comments
 (0)