diff options
author | George Burgess IV <gbiv@google.com> | 2020-07-20 16:53:39 -0700 |
---|---|---|
committer | George Burgess <gbiv@chromium.org> | 2020-07-22 16:43:35 +0000 |
commit | cb46500d29085ee65b524981f0fbf4af3badc0bb (patch) | |
tree | b7286ea46ca78cfa7cb79a718fe13d0f111ea4f9 | |
parent | 6c2e5c4448ade8e7764d3ebfb8a168441f59cf92 (diff) | |
download | toolchain-utils-cb46500d29085ee65b524981f0fbf4af3badc0bb.tar.gz |
compiler_wrapper: add -clang-tidy-flag support
This CL adds support for specifying compiler flags that're meant to be
passed only to clang-tidy. This allows for easier local experimentation
with clang-tidy by users.
BUG=chromium:982944
TEST=`WITH_TIDY=1 emerge-amd64-generic biod` with custom cflags; cq+1
on crrev.com/c/2308774
Change-Id: I654559d14a78ade4920fe37757fb5b249a997290
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2309152
Reviewed-by: Caroline Tice <cmtice@chromium.org>
Tested-by: George Burgess <gbiv@chromium.org>
-rw-r--r-- | compiler_wrapper/clang_tidy_flag.go | 30 | ||||
-rw-r--r-- | compiler_wrapper/clang_tidy_flag_test.go | 53 | ||||
-rw-r--r-- | compiler_wrapper/compiler_wrapper.go | 80 |
3 files changed, 115 insertions, 48 deletions
diff --git a/compiler_wrapper/clang_tidy_flag.go b/compiler_wrapper/clang_tidy_flag.go index edbbb412..2d97ddd3 100644 --- a/compiler_wrapper/clang_tidy_flag.go +++ b/compiler_wrapper/clang_tidy_flag.go @@ -21,10 +21,20 @@ const ( tidyModeTricium ) -func processClangTidyFlags(builder *commandBuilder) (cSrcFile string, mode useTidyMode) { +func processClangTidyFlags(builder *commandBuilder) (cSrcFile string, clangTidyFlags []string, mode useTidyMode) { + builder.transformArgs(func(arg builderArg) string { + const prefix = "-clang-tidy-flag=" + if !strings.HasPrefix(arg.value, prefix) { + return arg.value + } + + clangTidyFlags = append(clangTidyFlags, arg.value[len(prefix):]) + return "" + }) + withTidy, _ := builder.env.getenv("WITH_TIDY") if withTidy == "" { - return "", tidyModeNone + return "", clangTidyFlags, tidyModeNone } srcFileSuffixes := []string{ ".c", @@ -51,7 +61,7 @@ func processClangTidyFlags(builder *commandBuilder) (cSrcFile string, mode useTi } if cSrcFile == "" { - return "", tidyModeNone + return "", clangTidyFlags, tidyModeNone } if withTidy == "tricium" { @@ -65,7 +75,7 @@ func processClangTidyFlags(builder *commandBuilder) (cSrcFile string, mode useTi } else { mode = tidyModeAll } - return cSrcFile, mode + return cSrcFile, clangTidyFlags, mode } func calcClangTidyInvocation(env env, clangCmd *command, cSrcFile string, tidyFlags ...string) (*command, error) { @@ -85,7 +95,7 @@ func calcClangTidyInvocation(env env, clangCmd *command, cSrcFile string, tidyFl }, nil } -func runClangTidyForTricium(env env, clangCmd *command, cSrcFile, fixesDir string) error { +func runClangTidyForTricium(env env, clangCmd *command, cSrcFile, fixesDir string, extraTidyFlags []string) error { if err := os.MkdirAll(fixesDir, 0777); err != nil { return fmt.Errorf("creating fixes directory at %q: %v", fixesDir, err) } @@ -103,7 +113,8 @@ func runClangTidyForTricium(env env, clangCmd *command, cSrcFile, fixesDir strin // FIXME(gbiv): Remove `-checks=*` when testing is complete; we should defer to .clang-tidy // files, which are both more expressive and more approachable than `-checks=*`. - clangTidyCmd, err := calcClangTidyInvocation(env, clangCmd, cSrcFile, "-checks=*", "--export-fixes="+fixesFilePath) + extraTidyFlags = append(extraTidyFlags, "-checks=*", "--export-fixes="+fixesFilePath) + clangTidyCmd, err := calcClangTidyInvocation(env, clangCmd, cSrcFile, extraTidyFlags...) if err != nil { return fmt.Errorf("calculating tidy invocation: %v", err) } @@ -149,9 +160,9 @@ func runClangTidyForTricium(env env, clangCmd *command, cSrcFile, fixesDir strin return nil } -func runClangTidy(env env, clangCmd *command, cSrcFile string) error { - clangTidyCmd, err := calcClangTidyInvocation(env, clangCmd, cSrcFile, "-checks="+ - strings.Join([]string{ +func runClangTidy(env env, clangCmd *command, cSrcFile string, extraTidyFlags []string) error { + extraTidyFlags = append(extraTidyFlags, + "-checks="+strings.Join([]string{ "*", "-bugprone-narrowing-conversions", "-cppcoreguidelines-*", @@ -165,6 +176,7 @@ func runClangTidy(env env, clangCmd *command, cSrcFile string) error { "-modernize-*", "-readability-*", }, ",")) + clangTidyCmd, err := calcClangTidyInvocation(env, clangCmd, cSrcFile, extraTidyFlags...) if err != nil { return fmt.Errorf("calculating clang-tidy invocation: %v", err) } diff --git a/compiler_wrapper/clang_tidy_flag_test.go b/compiler_wrapper/clang_tidy_flag_test.go index d45d1bdd..54159cdc 100644 --- a/compiler_wrapper/clang_tidy_flag_test.go +++ b/compiler_wrapper/clang_tidy_flag_test.go @@ -333,6 +333,59 @@ func TestTriciumClangTidySkipsProtobufFiles(t *testing.T) { }) } +func testClangTidyFiltersClangTidySpecificFlagsWithPresetEnv(t *testing.T, ctx *testContext) { + addedFlag := "--some_clang_tidy=flag" + ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { + switch ctx.cmdCount { + case 1: + if err := verifyPath(cmd, "usr/bin/clang"); err != nil { + t.Error(err) + } else if err := verifyArgCount(cmd, 0, addedFlag); err != nil { + t.Error(err) + } + return nil + case 2: + if err := verifyPath(cmd, "usr/bin/clang-tidy"); err != nil { + t.Error(err) + } else if verifyArgCount(cmd, 1, addedFlag); err != nil { + t.Error(err) + } + return nil + default: + return nil + } + } + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc, "-clang-tidy-flag="+addedFlag))) + if ctx.cmdCount != 3 { + t.Errorf("expected 3 calls. Got: %d", ctx.cmdCount) + } + if err := verifyPath(cmd, "usr/bin/clang"); err != nil { + t.Error(err) + } +} + +func TestClangTidyFiltersClangTidySpecificFlagsForTricium(t *testing.T) { + withClangTidyTestContext(t, func(ctx *testContext) { + ctx.env = []string{"WITH_TIDY=tricium"} + testClangTidyFiltersClangTidySpecificFlagsWithPresetEnv(t, ctx) + }) +} + +func TestClangTidyFiltersClangTidySpecificFlags(t *testing.T) { + withClangTidyTestContext(t, func(ctx *testContext) { + testClangTidyFiltersClangTidySpecificFlagsWithPresetEnv(t, ctx) + }) +} + +func TestClangTidyFlagsAreFilteredFromGccInvocations(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc, "-clang-tidy-flag=--foo"))) + if err := verifyArgCount(cmd, 0, ".*--foo.*"); 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 14de210a..a5d35a2c 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -89,53 +89,55 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int default: return 0, newErrorwithSourceLocf("unsupported compiler: %s", mainBuilder.target.compiler) } - } else if mainBuilder.target.compilerType == clangType { - cSrcFile, tidyMode := processClangTidyFlags(mainBuilder) - err := prepareClangCommand(mainBuilder) - if err != nil { - return 0, err - } - allowCCache := true - if tidyMode != tidyModeNone { - allowCCache = false - clangCmdWithoutGomaAndCCache := mainBuilder.build() - var err error - switch tidyMode { - case tidyModeTricium: - if cfg.triciumNitsDir == "" { - return 0, newErrorwithSourceLocf("tricium linting was requested, but no nits directory is configured") - } - err = runClangTidyForTricium(env, clangCmdWithoutGomaAndCCache, cSrcFile, cfg.triciumNitsDir) - case tidyModeAll: - err = runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile) - default: - panic(fmt.Sprintf("Unknown tidy mode: %v", tidyMode)) - } - + } else { + cSrcFile, tidyFlags, tidyMode := processClangTidyFlags(mainBuilder) + if mainBuilder.target.compilerType == clangType { + err := prepareClangCommand(mainBuilder) if err != nil { return 0, err } - } - if err := processGomaCCacheFlags(allowCCache, mainBuilder); err != nil { - return 0, err - } - compilerCmd = mainBuilder.build() - } else { - if clangSyntax { - allowCCache := false - clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone()) - if err != nil { + allowCCache := true + if tidyMode != tidyModeNone { + allowCCache = false + clangCmdWithoutGomaAndCCache := mainBuilder.build() + var err error + switch tidyMode { + case tidyModeTricium: + if cfg.triciumNitsDir == "" { + return 0, newErrorwithSourceLocf("tricium linting was requested, but no nits directory is configured") + } + err = runClangTidyForTricium(env, clangCmdWithoutGomaAndCCache, cSrcFile, cfg.triciumNitsDir, tidyFlags) + case tidyModeAll: + err = runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile, tidyFlags) + default: + panic(fmt.Sprintf("Unknown tidy mode: %v", tidyMode)) + } + + if err != nil { + return 0, err + } + } + if err := processGomaCCacheFlags(allowCCache, mainBuilder); err != nil { return 0, err } - gccCmd, err := calcGccCommand(mainBuilder) + compilerCmd = mainBuilder.build() + } else { + if clangSyntax { + allowCCache := false + clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone()) + if err != nil { + return 0, err + } + gccCmd, err := calcGccCommand(mainBuilder) + if err != nil { + return 0, err + } + return checkClangSyntax(env, clangCmd, gccCmd) + } + compilerCmd, err = calcGccCommand(mainBuilder) if err != nil { return 0, err } - return checkClangSyntax(env, clangCmd, gccCmd) - } - compilerCmd, err = calcGccCommand(mainBuilder) - if err != nil { - return 0, err } } rusageLogfileName := getRusageLogFilename(env) |