diff options
-rw-r--r-- | compiler_wrapper/disable_werror_flag.go | 23 | ||||
-rw-r--r-- | compiler_wrapper/disable_werror_flag_test.go | 69 | ||||
-rw-r--r-- | compiler_wrapper/testutil_test.go | 21 |
3 files changed, 99 insertions, 14 deletions
diff --git a/compiler_wrapper/disable_werror_flag.go b/compiler_wrapper/disable_werror_flag.go index f68786d4..75f71a0d 100644 --- a/compiler_wrapper/disable_werror_flag.go +++ b/compiler_wrapper/disable_werror_flag.go @@ -14,6 +14,8 @@ import ( "syscall" ) +const numWErrorEstimate = 30 + func getNewWarningsDir(env env, cfg *config) (dirName string, ok bool) { if cfg.isAndroidWrapper { if cfg.useLlvmNext { @@ -32,13 +34,17 @@ func getNewWarningsDir(env env, cfg *config) (dirName string, ok bool) { } func disableWerrorFlags(originalArgs []string) []string { - noErrors := []string{"-Wno-error"} + extraArgs := []string{"-Wno-error"} + newArgs := make([]string, 0, len(originalArgs)+numWErrorEstimate) for _, flag := range originalArgs { if strings.HasPrefix(flag, "-Werror=") { - noErrors = append(noErrors, strings.Replace(flag, "-Werror", "-Wno-error", 1)) + extraArgs = append(extraArgs, strings.Replace(flag, "-Werror", "-Wno-error", 1)) + } + if !strings.Contains(flag, "-warnings-as-errors") { + newArgs = append(newArgs, flag) } } - return noErrors + return append(newArgs, extraArgs...) } func isLikelyAConfTest(cfg *config, cmd *command) bool { @@ -75,9 +81,16 @@ func doubleBuildWithWNoError(env env, cfg *config, newWarningsDir string, origin if err != nil { return 0, err } + // The only way we can do anything useful is if it looks like the failure // was -Werror-related. - if originalExitCode == 0 || !bytes.Contains(originalStderrBuffer.Bytes(), []byte("-Werror")) || isLikelyAConfTest(cfg, originalCmd) { + originalStdoutBufferBytes := originalStdoutBuffer.Bytes() + shouldRetry := originalExitCode != 0 && + !isLikelyAConfTest(cfg, originalCmd) && + (bytes.Contains(originalStderrBuffer.Bytes(), []byte("-Werror")) || + bytes.Contains(originalStdoutBufferBytes, []byte("warnings-as-errors")) || + bytes.Contains(originalStdoutBufferBytes, []byte("clang-diagnostic-"))) + if !shouldRetry { originalStdoutBuffer.WriteTo(env.stdout()) originalStderrBuffer.WriteTo(env.stderr()) return originalExitCode, nil @@ -87,7 +100,7 @@ func doubleBuildWithWNoError(env env, cfg *config, newWarningsDir string, origin retryStderrBuffer := &bytes.Buffer{} retryCommand := &command{ Path: originalCmd.Path, - Args: append(originalCmd.Args, disableWerrorFlags(originalCmd.Args)...), + Args: disableWerrorFlags(originalCmd.Args), EnvUpdates: originalCmd.EnvUpdates, } retryExitCode, err := wrapSubprocessErrorWithSourceLoc(retryCommand, diff --git a/compiler_wrapper/disable_werror_flag_test.go b/compiler_wrapper/disable_werror_flag_test.go index 53b0fb52..28e48371 100644 --- a/compiler_wrapper/disable_werror_flag_test.go +++ b/compiler_wrapper/disable_werror_flag_test.go @@ -449,3 +449,72 @@ func TestChromeOSGetNewWarningsDirOff(t *testing.T) { } }) } + +func TestClangTidyNoDoubleBuild(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.isAndroidWrapper = true + ctx.cfg.useLlvmNext = true + ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangTidyAndroid, "--", mainCc))) + if ctx.cmdCount != 1 { + t.Errorf("expected 1 call. Got: %d", ctx.cmdCount) + } + }) +} + +func withAndroidClangTidyTestContext(t *testing.T, work func(ctx *testContext)) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.isAndroidWrapper = true + ctx.cfg.useLlvmNext = true + ctx.env = []string{"OUT_DIR=/tmp"} + + ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { + hasArg := func(s string) bool { + for _, e := range cmd.Args { + if strings.Contains(e, s) { + return true + } + } + return false + } + switch ctx.cmdCount { + case 1: + if hasArg("-Werror") { + fmt.Fprint(stdout, "clang-diagnostic-") + return newExitCodeError(1) + } + if hasArg("-warnings-as-errors") { + fmt.Fprint(stdout, "warnings-as-errors") + return newExitCodeError(1) + } + return nil + case 2: + if hasArg("warnings-as-errors") { + return fmt.Errorf("Unexpected arg warnings-as-errors found. All args: %s", cmd.Args) + } + return nil + default: + t.Fatalf("unexpected command: %#v", cmd) + return nil + } + } + work(ctx) + }) +} + +func TestClangTidyDoubleBuildClangTidyError(t *testing.T) { + withAndroidClangTidyTestContext(t, func(ctx *testContext) { + ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangTidyAndroid, "-warnings-as-errors=*", "--", mainCc))) + if ctx.cmdCount != 2 { + t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) + } + }) +} + +func TestClangTidyDoubleBuildClangError(t *testing.T) { + withAndroidClangTidyTestContext(t, func(ctx *testContext) { + ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangTidyAndroid, "-Werrors=*", "--", mainCc))) + if ctx.cmdCount != 2 { + t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) + } + }) +} diff --git a/compiler_wrapper/testutil_test.go b/compiler_wrapper/testutil_test.go index 57a68df2..5d8ef920 100644 --- a/compiler_wrapper/testutil_test.go +++ b/compiler_wrapper/testutil_test.go @@ -17,15 +17,18 @@ import ( "testing" ) -const mainCc = "main.cc" -const clangAndroid = "./clang" -const clangX86_64 = "./x86_64-cros-linux-gnu-clang" -const gccX86_64 = "./x86_64-cros-linux-gnu-gcc" -const gccX86_64Eabi = "./x86_64-cros-eabi-gcc" -const gccArmV7 = "./armv7m-cros-linux-gnu-gcc" -const gccArmV7Eabi = "./armv7m-cros-eabi-gcc" -const gccArmV8 = "./armv8m-cros-linux-gnu-gcc" -const gccArmV8Eabi = "./armv8m-cros-eabi-gcc" +const ( + mainCc = "main.cc" + clangAndroid = "./clang" + clangTidyAndroid = "./clang-tidy" + clangX86_64 = "./x86_64-cros-linux-gnu-clang" + gccX86_64 = "./x86_64-cros-linux-gnu-gcc" + gccX86_64Eabi = "./x86_64-cros-eabi-gcc" + gccArmV7 = "./armv7m-cros-linux-gnu-gcc" + gccArmV7Eabi = "./armv7m-cros-eabi-gcc" + gccArmV8 = "./armv8m-cros-linux-gnu-gcc" + gccArmV8Eabi = "./armv8m-cros-eabi-gcc" +) type testContext struct { t *testing.T |