diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 870f5169cf7c7..5ea6c78a16e59 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -586,6 +586,24 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, return AdjustedArgs; }; + // Remove unwanted arguments passed to the compiler + ArgumentsAdjuster PerFileArgumentRemover = + [&Context](const CommandLineArguments &Args, StringRef Filename) { + ClangTidyOptions Opts = Context.getOptionsForFile(Filename); + CommandLineArguments AdjustedArgs = Args; + + if (Opts.RemovedArgs) { + for (StringRef ArgToRemove : *Opts.RemovedArgs) { + AdjustedArgs.erase(std::remove(AdjustedArgs.begin(), + AdjustedArgs.end(), ArgToRemove), + AdjustedArgs.end()); + } + } + + return AdjustedArgs; + }; + + Tool.appendArgumentsAdjuster(PerFileArgumentRemover); Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter); Tool.appendArgumentsAdjuster(getStripPluginsAdjuster()); Context.setEnableProfiling(EnableCheckProfile); diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp index 550f7809d75f9..bf48824c65c4b 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp @@ -230,6 +230,7 @@ template <> struct MappingTraits { IO.mapOptional("CheckOptions", Options.CheckOptions); IO.mapOptional("ExtraArgs", Options.ExtraArgs); IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore); + IO.mapOptional("RemovedArgs", Options.RemovedArgs); IO.mapOptional("InheritParentConfig", Options.InheritParentConfig); IO.mapOptional("UseColor", Options.UseColor); IO.mapOptional("SystemHeaders", Options.SystemHeaders); @@ -252,6 +253,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() { Options.SystemHeaders = false; Options.FormatStyle = "none"; Options.User = std::nullopt; + Options.RemovedArgs = std::nullopt; for (const ClangTidyModuleRegistry::entry &Module : ClangTidyModuleRegistry::entries()) Options.mergeWith(Module.instantiate()->getModuleOptions(), 0); @@ -295,6 +297,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other, overrideValue(UseColor, Other.UseColor); mergeVectors(ExtraArgs, Other.ExtraArgs); mergeVectors(ExtraArgsBefore, Other.ExtraArgsBefore); + mergeVectors(RemovedArgs, Other.RemovedArgs); // FIXME: how to handle duplicate names check? mergeVectors(CustomChecks, Other.CustomChecks); for (const auto &KeyValue : Other.CheckOptions) { diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h index 4c97c5ba801f0..97daed448063b 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h +++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h @@ -85,7 +85,7 @@ struct ClangTidyOptions { /// main files will always be displayed. std::optional HeaderFilterRegex; - /// \brief Exclude warnings from headers matching this filter, even if they + /// Exclude warnings from headers matching this filter, even if they /// match \c HeaderFilterRegex. std::optional ExcludeHeaderFilterRegex; @@ -151,6 +151,9 @@ struct ClangTidyOptions { /// Add extra compilation arguments to the start of the list. std::optional ExtraArgsBefore; + /// Remove command line arguments sent to the compiler matching this. + std::optional RemovedArgs; + /// Only used in the FileOptionsProvider and ConfigOptionsProvider. If true /// and using a FileOptionsProvider, it will take a configuration file in the /// parent directory (if any exists) and apply this config file on top of the diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index f5e4bf020bd68..87c1fc4959859 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -18,6 +18,7 @@ #include "../ClangTidy.h" #include "../ClangTidyForceLinker.h" #include "../GlobList.h" +#include "../utils/OptionsUtils.h" #include "clang/Tooling/CommonOptionsParser.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" @@ -77,6 +78,7 @@ Configuration files: (if any exists) will be taken and the current config file will be applied on top of the parent one. + RemovedArgs - Same as '--removed-arg'. SystemHeaders - Same as '--system-headers'. UseColor - Same as '--use-color'. User - Specifies the name or e-mail of the user @@ -357,6 +359,16 @@ see https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html. cl::init(false), cl::cat(ClangTidyCategory)); +static cl::list RemovedArgs("removed-arg", desc(R"( +List of arguments to remove from the command +line sent to the compiler. Please note that +removing arguments might change the semantic +of the analzed code, possibly leading to +compiler errors, false positives or +false negatives. This option is applied +before --extra-arg and --extra-arg-before)"), + cl::cat(ClangTidyCategory)); + namespace clang::tidy { static void printStats(const ClangTidyStats &Stats) { @@ -423,6 +435,8 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr FS) { OverrideOptions.FormatStyle = FormatStyle; if (UseColor.getNumOccurrences() > 0) OverrideOptions.UseColor = UseColor; + if (RemovedArgs.getNumOccurrences() > 0) + OverrideOptions.RemovedArgs = RemovedArgs; auto LoadConfig = [&](StringRef Configuration, diff --git a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py index 5daa93dca2a99..c090bdc1151df 100755 --- a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py +++ b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py @@ -228,6 +228,13 @@ def main(): default=[], help="Additional argument to prepend to the compiler " "command line.", ) + parser.add_argument( + "-removed-arg", + dest="removed_arg", + action="append", + default=[], + help="Arguments to remove from the compiler command line.", + ) parser.add_argument( "-quiet", action="store_true", @@ -378,6 +385,8 @@ def main(): common_clang_tidy_args.append("-extra-arg=%s" % arg) for arg in args.extra_arg_before: common_clang_tidy_args.append("-extra-arg-before=%s" % arg) + for arg in args.removed_arg: + common_clang_tidy_args.append("-removed-arg=%s" % arg) for plugin in args.plugins: common_clang_tidy_args.append("-load=%s" % plugin) if args.warnings_as_errors: diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index f495f449b5b30..59523fd131185 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -96,6 +96,7 @@ def get_tidy_invocation( allow_enabling_alpha_checkers: bool, extra_arg: List[str], extra_arg_before: List[str], + removed_arg: List[str], quiet: bool, config_file_path: str, config: str, @@ -135,6 +136,8 @@ def get_tidy_invocation( start.append(f"-extra-arg={arg}") for arg in extra_arg_before: start.append(f"-extra-arg-before={arg}") + for arg in removed_arg: + start.append(f"-removed-arg={arg}") start.append(f"-p={build_path}") if quiet: start.append("-quiet") @@ -377,6 +380,7 @@ async def run_tidy( args.allow_enabling_alpha_checkers, args.extra_arg, args.extra_arg_before, + args.removed_arg, args.quiet, args.config_file, args.config, @@ -551,6 +555,13 @@ async def main() -> None: default=[], help="Additional argument to prepend to the compiler command line.", ) + parser.add_argument( + "-removed-arg", + dest="removed_arg", + action="append", + default=[], + help="Arguments to remove from the compiler command line.", + ) parser.add_argument( "-quiet", action="store_true", help="Run clang-tidy in quiet mode." ) @@ -638,6 +649,7 @@ async def main() -> None: args.allow_enabling_alpha_checkers, args.extra_arg, args.extra_arg_before, + args.removed_arg, args.quiet, args.config_file, args.config, diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 666865cfb2fcd..876f900ef341c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -177,6 +177,11 @@ Improvements to clang-tidy scripts by adding the `-hide-progress` option to suppress progress and informational messages. +- Improved :program:`clang-tidy` by adding the `--removed-arg` option to remove + arguments sent to the compiler when invoking Clang-Tidy. This option was also + added to :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` and + can be configured in the config file through the `RemovedArgs` option. + - Deprecated the :program:`clang-tidy` ``zircon`` module. All checks have been moved to the ``fuchsia`` module instead. The ``zircon`` module will be removed in the 24th release. diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst index 6ff82bf230f4b..8dcab354161d8 100644 --- a/clang-tools-extra/docs/clang-tidy/index.rst +++ b/clang-tools-extra/docs/clang-tidy/index.rst @@ -331,6 +331,7 @@ An overview of all the command-line options: example, to place the correct user name in TODO() comments in the relevant check. WarningsAsErrors - Same as '--warnings-as-errors'. + RemovedArgs - Same as '--removed-arg' The effective configuration can be inspected using --dump-config: diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp index 4bdca50af32ca..80540411e53e3 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp @@ -1,4 +1,4 @@ // RUN: not clang-tidy --invalid-arg 2>&1 | FileCheck %s // CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-tidy{{(\.exe)?}} --help' -// CHECK-NEXT: clang-tidy{{(\.exe)?}}: Did you mean '--extra-arg'? +// CHECK-NEXT: clang-tidy{{(\.exe)?}}: Did you mean '--removed-arg'? diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/removed-args.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/removed-args.cpp new file mode 100644 index 0000000000000..dd97b45dda1bb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/removed-args.cpp @@ -0,0 +1,8 @@ +// RUN: not clang-tidy %s -- -fnot-an-option | FileCheck %s -check-prefix=INVALID-A +// RUN: clang-tidy %s --config="{RemovedArgs: ['-fnot-an-option']}" -- -fnot-an-option +// RUN: clang-tidy %s --config="{RemovedArgs: ['-fnot-another-option', '-fnot-an-option']}" -- -fnot-an-option -fnot-another-option +// RUN: clang-tidy %s --removed-arg="-fnot-an-option" -- -fnot-an-option +// RUN: not clang-tidy %s --removed-arg="-fnot-an-option" -- -fnot-an-option -fnot-another-option | FileCheck %s -check-prefix=INVALID-B + +// INVALID-A: error: unknown argument: '-fnot-an-option' [clang-diagnostic-error] +// INVALID-B: error: unknown argument: '-fnot-another-option' [clang-diagnostic-error]