aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler_wrapper/bisect_flag.go1
-rw-r--r--compiler_wrapper/bisect_flag_test.go16
-rw-r--r--compiler_wrapper/clang_syntax_flag_test.go27
-rw-r--r--compiler_wrapper/clang_tidy_flag_test.go35
-rw-r--r--compiler_wrapper/compiler_wrapper.go36
-rw-r--r--compiler_wrapper/config.go22
-rw-r--r--compiler_wrapper/config_test.go24
-rw-r--r--compiler_wrapper/disable_werror_flag.go5
-rw-r--r--compiler_wrapper/disable_werror_flag_test.go30
-rw-r--r--compiler_wrapper/oldwrapper.go27
-rw-r--r--compiler_wrapper/sanitizer_flags.go5
-rw-r--r--compiler_wrapper/sanitizer_flags_test.go24
12 files changed, 213 insertions, 39 deletions
diff --git a/compiler_wrapper/bisect_flag.go b/compiler_wrapper/bisect_flag.go
index 9cab75bd..9eb59dc4 100644
--- a/compiler_wrapper/bisect_flag.go
+++ b/compiler_wrapper/bisect_flag.go
@@ -21,5 +21,6 @@ func calcBisectCommand(env env, bisectStage string, compilerCmd *command) *comma
bisectDir,
absCompilerPath,
}, compilerCmd.Args...),
+ EnvUpdates: compilerCmd.EnvUpdates,
}
}
diff --git a/compiler_wrapper/bisect_flag_test.go b/compiler_wrapper/bisect_flag_test.go
index 2b099912..1ccf6051 100644
--- a/compiler_wrapper/bisect_flag_test.go
+++ b/compiler_wrapper/bisect_flag_test.go
@@ -27,6 +27,22 @@ func TestCallBisectDriver(t *testing.T) {
})
}
+func TestCallBisectDriverWithCCache(t *testing.T) {
+ withBisectTestContext(t, func(ctx *testContext) {
+ ctx.cfg.useCCache = true
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc)))
+ if err := verifyPath(cmd, "/usr/bin/python2"); err != nil {
+ t.Error(err)
+ }
+ if err := verifyArgCount(cmd, 1, "/usr/bin/ccache"); err != nil {
+ t.Error(err)
+ }
+ if err := verifyEnvUpdate(cmd, "CCACHE_DIR=.*"); err != nil {
+ t.Error(err)
+ }
+ })
+}
+
func TestDefaultBisectDir(t *testing.T) {
withBisectTestContext(t, func(ctx *testContext) {
ctx.env = []string{
diff --git a/compiler_wrapper/clang_syntax_flag_test.go b/compiler_wrapper/clang_syntax_flag_test.go
index d2661812..c30d9795 100644
--- a/compiler_wrapper/clang_syntax_flag_test.go
+++ b/compiler_wrapper/clang_syntax_flag_test.go
@@ -124,10 +124,35 @@ func TestUseGomaForClangSyntaxCheck(t *testing.T) {
}
return nil
}
- ctx.must(callCompiler(ctx, ctx.cfg,
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg,
ctx.newCommand(gccX86_64, "-clang-syntax", mainCc)))
if ctx.cmdCount != 2 {
t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount)
}
+ if err := verifyPath(cmd, gomaPath); err != nil {
+ t.Error(err)
+ }
+ })
+}
+
+func TestPartiallyOmitCCacheForClangSyntaxCheck(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ ctx.cfg.useCCache = true
+ ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error {
+ if ctx.cmdCount == 1 {
+ if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg,
+ ctx.newCommand(gccX86_64, "-clang-syntax", mainCc)))
+ if ctx.cmdCount != 2 {
+ t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount)
+ }
+ if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil {
+ t.Error(err)
+ }
})
}
diff --git a/compiler_wrapper/clang_tidy_flag_test.go b/compiler_wrapper/clang_tidy_flag_test.go
index 9c0fc928..9ca37d8f 100644
--- a/compiler_wrapper/clang_tidy_flag_test.go
+++ b/compiler_wrapper/clang_tidy_flag_test.go
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
+ "path"
"strings"
"testing"
)
@@ -234,6 +235,40 @@ func TestOmitCCacheWithClangTidy(t *testing.T) {
})
}
+func TestPartiallyOmitGomaWithClangTidy(t *testing.T) {
+ withClangTidyTestContext(t, func(ctx *testContext) {
+ gomaPath := path.Join(ctx.tempDir, "gomacc")
+ // Create a file so the gomacc path is valid.
+ ctx.writeFile(gomaPath, "")
+ ctx.env = append(ctx.env, "GOMACC_PATH="+gomaPath)
+
+ ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error {
+ switch ctx.cmdCount {
+ case 1:
+ if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
+ t.Error(err)
+ }
+ return nil
+ case 2:
+ if err := verifyPath(cmd, "usr/bin/clang-tidy"); err != nil {
+ return err
+ }
+ return nil
+ default:
+ return nil
+ }
+ }
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg,
+ ctx.newCommand(clangX86_64, mainCc)))
+ if ctx.cmdCount != 3 {
+ t.Errorf("expected 3 calls. Got: %d", ctx.cmdCount)
+ }
+ if err := verifyPath(cmd, gomaPath); err != nil {
+ t.Error(err)
+ }
+ })
+}
+
func withClangTidyTestContext(t *testing.T, work func(ctx *testContext)) {
withTestContext(t, func(ctx *testContext) {
ctx.env = []string{"WITH_TIDY=1"}
diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go
index 314a8a71..8bee238d 100644
--- a/compiler_wrapper/compiler_wrapper.go
+++ b/compiler_wrapper/compiler_wrapper.go
@@ -50,19 +50,24 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int
clangSyntax := processClangSyntaxFlag(mainBuilder)
if mainBuilder.target.compilerType == clangType {
cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
- compilerCmd, err = calcClangCommand(useClangTidy, mainBuilder)
+ sysroot, err := prepareClangCommand(mainBuilder)
if err != nil {
return 0, err
}
+ allowCCache := true
if useClangTidy {
- if err := runClangTidy(env, compilerCmd, cSrcFile); err != nil {
+ allowCCache = false
+ clangCmdWithoutGomaAndCCache := mainBuilder.build()
+ if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
return 0, err
}
}
+ processGomaCCacheFlags(sysroot, allowCCache, mainBuilder)
+ compilerCmd = mainBuilder.build()
} else {
if clangSyntax {
- forceLocal := false
- clangCmd, err := calcClangCommand(forceLocal, mainBuilder.clone())
+ allowCCache := false
+ clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
if err != nil {
return 0, err
}
@@ -98,16 +103,22 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int
return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
}
-func calcClangCommand(forceLocal bool, builder *commandBuilder) (*command, error) {
- sysroot := processSysrootFlag(builder)
+func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
+ sysroot = processSysrootFlag(builder)
builder.addPreUserArgs(builder.cfg.clangFlags...)
calcCommonPreUserArgs(builder)
if err := processClangFlags(builder); err != nil {
- return nil, err
+ return "", err
}
- if !forceLocal {
- processGomaCCacheFlags(sysroot, builder)
+ return sysroot, nil
+}
+
+func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
+ sysroot, err := prepareClangCommand(builder)
+ if err != nil {
+ return nil, err
}
+ processGomaCCacheFlags(sysroot, allowCCache, builder)
return builder.build(), nil
}
@@ -116,7 +127,8 @@ func calcGccCommand(builder *commandBuilder) *command {
builder.addPreUserArgs(builder.cfg.gccFlags...)
calcCommonPreUserArgs(builder)
processGccFlags(builder)
- processGomaCCacheFlags(sysroot, builder)
+ allowCCache := true
+ processGomaCCacheFlags(sysroot, allowCCache, builder)
return builder.build()
}
@@ -129,9 +141,9 @@ func calcCommonPreUserArgs(builder *commandBuilder) {
processSanitizerFlags(builder)
}
-func processGomaCCacheFlags(sysroot string, builder *commandBuilder) {
+func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) {
gomaccUsed := processGomaCccFlags(builder)
- if !gomaccUsed {
+ if !gomaccUsed && allowCCache {
processCCacheFlag(sysroot, builder)
}
}
diff --git a/compiler_wrapper/config.go b/compiler_wrapper/config.go
index 5e594cc3..45e82575 100644
--- a/compiler_wrapper/config.go
+++ b/compiler_wrapper/config.go
@@ -68,29 +68,29 @@ func getCrosHardenedConfig(useCCache bool) *config {
rootRelPath: "../../../../..",
oldWrapperPath: "./sysroot_wrapper.hardened.old",
commonFlags: []string{
- "-fPIE",
- "-D_FORTIFY_SOURCE=2",
"-fstack-protector-strong",
+ "-fPIE",
"-pie",
+ "-D_FORTIFY_SOURCE=2",
"-fno-omit-frame-pointer",
},
gccFlags: []string{
+ "-fno-reorder-blocks-and-partition",
"-Wno-unused-local-typedefs",
"-Wno-maybe-uninitialized",
- "-fno-reorder-blocks-and-partition",
},
// Temporarily disable tautological-*-compare chromium:778316.
// Temporarily add no-unknown-warning-option to deal with old clang versions.
// Temporarily disable Wsection since kernel gets a bunch of these. chromium:778867
// Disable "-faddrsig" since it produces object files that strip doesn't understand, chromium:915742.
clangFlags: []string{
- "-Wno-tautological-unsigned-enum-zero-compare",
"-Qunused-arguments",
"-grecord-gcc-switches",
- "-Wno-section",
- "-Wno-unknown-warning-option",
"-fno-addrsig",
"-Wno-tautological-constant-compare",
+ "-Wno-tautological-unsigned-enum-zero-compare",
+ "-Wno-unknown-warning-option",
+ "-Wno-section",
},
newWarningsDir: "/tmp/fatal_clang_warnings",
}
@@ -104,20 +104,20 @@ func getCrosNonHardenedConfig(useCCache bool) *config {
oldWrapperPath: "./sysroot_wrapper.old",
commonFlags: []string{},
gccFlags: []string{
- "-Wno-unused-local-typedefs",
"-Wno-maybe-uninitialized",
- "-Wtrampolines",
+ "-Wno-unused-local-typedefs",
"-Wno-deprecated-declarations",
+ "-Wtrampolines",
},
// Temporarily disable tautological-*-compare chromium:778316.
// Temporarily add no-unknown-warning-option to deal with old clang versions.
// Temporarily disable Wsection since kernel gets a bunch of these. chromium:778867
clangFlags: []string{
- "-Wno-unknown-warning-option",
"-Qunused-arguments",
- "-Wno-section",
- "-Wno-tautological-unsigned-enum-zero-compare",
"-Wno-tautological-constant-compare",
+ "-Wno-tautological-unsigned-enum-zero-compare",
+ "-Wno-unknown-warning-option",
+ "-Wno-section",
},
newWarningsDir: "/tmp/fatal_clang_warnings",
}
diff --git a/compiler_wrapper/config_test.go b/compiler_wrapper/config_test.go
index bd7aec03..5578baf0 100644
--- a/compiler_wrapper/config_test.go
+++ b/compiler_wrapper/config_test.go
@@ -13,9 +13,9 @@ func TestFullHardeningConfigAndGcc(t *testing.T) {
if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil {
t.Error(err)
}
- if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-unused-local-typedefs",
- "-Wno-maybe-uninitialized", "-fno-reorder-blocks-and-partition", "-fPIE", "-D_FORTIFY_SOURCE=2", "-fstack-protector-strong",
- "-pie", "-fno-omit-frame-pointer", "main.cc", "-mno-movbe"); err != nil {
+ if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", "-fno-reorder-blocks-and-partition",
+ "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", "-fstack-protector-strong", "-fPIE", "-pie", "-D_FORTIFY_SOURCE=2",
+ "-fno-omit-frame-pointer", "main.cc", "-mno-movbe"); err != nil {
t.Error(err)
}
})
@@ -34,10 +34,10 @@ func TestFullHardeningConfigAndClang(t *testing.T) {
t.Error(err)
}
binPath, err := filepath.Rel(ctx.tempDir, "/bin")
- if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-tautological-unsigned-enum-zero-compare",
- "-Qunused-arguments", "-grecord-gcc-switches", "-Wno-section", "-Wno-unknown-warning-option", "-fno-addrsig",
- "-Wno-tautological-constant-compare", "-fPIE", "-D_FORTIFY_SOURCE=2", "-fstack-protector-strong", "-pie",
- "-fno-omit-frame-pointer", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil {
+ if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Qunused-arguments", "-grecord-gcc-switches",
+ "-fno-addrsig", "-Wno-tautological-constant-compare", "-Wno-tautological-unsigned-enum-zero-compare", "-Wno-unknown-warning-option",
+ "-Wno-section", "-fstack-protector-strong", "-fPIE", "-pie", "-D_FORTIFY_SOURCE=2", "-fno-omit-frame-pointer", "main.cc",
+ "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil {
t.Error(err)
}
})
@@ -52,8 +52,8 @@ func TestNonHardeningConfigAndGcc(t *testing.T) {
t.Error(err)
}
if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu",
- "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", "-Wtrampolines",
- "-Wno-deprecated-declarations", "main.cc", "-mno-movbe"); err != nil {
+ "-Wno-maybe-uninitialized", "-Wno-unused-local-typedefs", "-Wno-deprecated-declarations",
+ "-Wtrampolines", "main.cc", "-mno-movbe"); err != nil {
t.Error(err)
}
})
@@ -72,9 +72,9 @@ func TestNonHardeningConfigAndClang(t *testing.T) {
t.Error(err)
}
binPath, err := filepath.Rel(ctx.tempDir, "/bin")
- if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-unknown-warning-option",
- "-Qunused-arguments", "-Wno-section", "-Wno-tautological-unsigned-enum-zero-compare",
- "-Wno-tautological-constant-compare", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil {
+ if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Qunused-arguments",
+ "-Wno-tautological-constant-compare", "-Wno-tautological-unsigned-enum-zero-compare",
+ "-Wno-unknown-warning-option", "-Wno-section", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil {
t.Error(err)
}
})
diff --git a/compiler_wrapper/disable_werror_flag.go b/compiler_wrapper/disable_werror_flag.go
index e4037bad..33bb725b 100644
--- a/compiler_wrapper/disable_werror_flag.go
+++ b/compiler_wrapper/disable_werror_flag.go
@@ -15,6 +15,11 @@ func shouldForceDisableWError(env env) bool {
func doubleBuildWithWNoError(env env, cfg *config, originalCmd *command) (exitCode int, err error) {
originalStdoutBuffer := &bytes.Buffer{}
originalStderrBuffer := &bytes.Buffer{}
+ // TODO: This is a bug in the old wrapper that it drops the ccache path
+ // during double build. Fix this once we don't compare to the old wrapper anymore.
+ if originalCmd.Path == "/usr/bin/ccache" {
+ originalCmd.Path = "ccache"
+ }
originalExitCode, err := wrapSubprocessErrorWithSourceLoc(originalCmd,
env.run(originalCmd, originalStdoutBuffer, originalStderrBuffer))
if err != nil {
diff --git a/compiler_wrapper/disable_werror_flag_test.go b/compiler_wrapper/disable_werror_flag_test.go
index affd8875..7ab938e3 100644
--- a/compiler_wrapper/disable_werror_flag_test.go
+++ b/compiler_wrapper/disable_werror_flag_test.go
@@ -66,6 +66,36 @@ func TestDoubleBuildWithWNoErrorFlag(t *testing.T) {
})
}
+func TestDoubleBuildWithWNoErrorAndCCache(t *testing.T) {
+ withForceDisableWErrorTestContext(t, func(ctx *testContext) {
+ ctx.cfg.useCCache = true
+ ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error {
+ switch ctx.cmdCount {
+ case 1:
+ // TODO: This is a bug in the old wrapper that it drops the ccache path
+ // during double build. Fix this once we don't compare to the old wrapper anymore.
+ if err := verifyPath(cmd, "ccache"); err != nil {
+ return err
+ }
+ fmt.Fprint(stderr, "-Werror originalerror")
+ return newExitCodeError(1)
+ case 2:
+ if err := verifyPath(cmd, "ccache"); err != nil {
+ return err
+ }
+ return nil
+ default:
+ t.Fatalf("unexpected command: %#v", cmd)
+ return nil
+ }
+ }
+ ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc)))
+ if ctx.cmdCount != 2 {
+ t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount)
+ }
+ })
+}
+
func TestForwardStdoutAndStderrWhenDoubleBuildSucceeds(t *testing.T) {
withForceDisableWErrorTestContext(t, func(ctx *testContext) {
ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error {
diff --git a/compiler_wrapper/oldwrapper.go b/compiler_wrapper/oldwrapper.go
index 315e6ea8..a6324400 100644
--- a/compiler_wrapper/oldwrapper.go
+++ b/compiler_wrapper/oldwrapper.go
@@ -183,13 +183,15 @@ func newOldWrapperConfig(env env, cfg *config, inputCmd *command) (*oldWrapperCo
return nil, wrapErrorwithSourceLocf(err, "failed to read old wrapper")
}
oldWrapperContent := string(oldWrapperContentBytes)
+ oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "from __future__ import print_function", "")
// Disable the original call to main()
oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "__name__", "'none'")
+ // Replace sets with lists to make our comparisons deterministic
+ oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "set(", "ListSet(")
// Inject the value of cfg.useCCache
if !cfg.useCCache {
oldWrapperContent = regexp.MustCompile(`True\s+#\s+@CCACHE_DEFAULT@`).ReplaceAllString(oldWrapperContent, "False #")
}
-
return &oldWrapperConfig{
CmdPath: inputCmd.Path,
OldWrapperContent: oldWrapperContent,
@@ -207,7 +209,28 @@ func callOldWrapper(env env, cfg *oldWrapperConfig, inputCmd *command, filepatte
}
defer os.Remove(mockFile.Name())
- const mockTemplate = `{{.OldWrapperContent}}
+ const mockTemplate = `
+from __future__ import print_function
+
+class ListSet:
+ def __init__(self, values):
+ self.values = list(values)
+ def __contains__(self, key):
+ return self.values.__contains__(key)
+ def __iter__(self):
+ return self.values.__iter__()
+ def __nonzero__(self):
+ return len(self.values) > 0
+ def add(self, value):
+ if value not in self.values:
+ self.values.append(value)
+ def discard(self, value):
+ if value in self.values:
+ self.values.remove(value)
+ def intersection(self, values):
+ return ListSet([value for value in self.values if value in values])
+
+{{.OldWrapperContent}}
import subprocess
init_env = os.environ.copy()
diff --git a/compiler_wrapper/sanitizer_flags.go b/compiler_wrapper/sanitizer_flags.go
index 1823dcb1..7e513803 100644
--- a/compiler_wrapper/sanitizer_flags.go
+++ b/compiler_wrapper/sanitizer_flags.go
@@ -24,7 +24,10 @@ func processSanitizerFlags(builder *commandBuilder) {
}
builder.transformArgs(func(arg builderArg) string {
- if unsupportedSanitizerFlags[arg.value] {
+ // TODO: This is a bug in the old wrapper to not filter
+ // non user args for gcc. Fix this once we don't compare to the old wrapper anymore.
+ if (builder.target.compilerType != gccType || arg.fromUser) &&
+ unsupportedSanitizerFlags[arg.value] {
return ""
}
return arg.value
diff --git a/compiler_wrapper/sanitizer_flags_test.go b/compiler_wrapper/sanitizer_flags_test.go
index 2b348779..091af25a 100644
--- a/compiler_wrapper/sanitizer_flags_test.go
+++ b/compiler_wrapper/sanitizer_flags_test.go
@@ -32,6 +32,30 @@ func TestFilterUnsupportedSanitizerFlagsIfSanitizeGiven(t *testing.T) {
})
}
+func TestFilterUnsupportedDefaultSanitizerFlagsIfSanitizeGivenForClang(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ ctx.cfg.commonFlags = []string{"-D_FORTIFY_SOURCE=1"}
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg,
+ ctx.newCommand(clangX86_64, "-fsanitize=kernel-address", mainCc)))
+ if err := verifyArgCount(cmd, 0, "-D_FORTIFY_SOURCE=1"); err != nil {
+ t.Error(err)
+ }
+ })
+}
+
+func TestKeepUnsupportedDefaultSanitizerFlagsIfSanitizeGivenForGcc(t *testing.T) {
+ withTestContext(t, func(ctx *testContext) {
+ ctx.cfg.commonFlags = []string{"-D_FORTIFY_SOURCE=1"}
+ cmd := ctx.must(callCompiler(ctx, ctx.cfg,
+ ctx.newCommand(gccX86_64, "-fsanitize=kernel-address", mainCc)))
+ if err := verifyArgCount(cmd, 1, "-D_FORTIFY_SOURCE=1"); err != nil {
+ t.Error(err)
+ }
+ })
+}
+
+// TODO: This is a bug in the old wrapper to not filter
+// non user args for gcc. Fix this once we don't compare to the old wrapper anymore.
func TestKeepSanitizerFlagsIfNoSanitizeGiven(t *testing.T) {
withTestContext(t, func(ctx *testContext) {
cmd := ctx.must(callCompiler(ctx, ctx.cfg,