Author: Félix-Antoine Constantin
Date: 2025-12-15T19:20:35+03:00
New Revision: 5ba62562b63458e238bf556167a41ed8ef70f79d

URL: 
https://github.com/llvm/llvm-project/commit/5ba62562b63458e238bf556167a41ed8ef70f79d
DIFF: 
https://github.com/llvm/llvm-project/commit/5ba62562b63458e238bf556167a41ed8ef70f79d.diff

LOG: [clang-tidy] New option to remove arguments from the command line (#164344)

When using clang-tidy from a compilation database, some options might
not be
recognized by clang if the compilation database was generated for
another compiler.
This forces the user to add conditional code in their CMakeLists.txt to
remove
those arguments when using clang-tidy.
A new option was added to the .clang-tidy config to remove
those unknown flags without the need to generate a second
compilation_commands.json
    
Fixes #108455

Please see #111453 and #162201 for previous discussions regarding this
option.
This implementation was slightly changed from the initial PR based on
the following comment
(https://github.com/llvm/llvm-project/pull/162201#issuecomment-3393569422).

The goal is to keep this feature as simple as possible and to make sure
there aren't any side effects. So the user has to explicitly list the
arguments he wants to remove. A mention was also added to warn the user
that removing arguments might lead to false positive / negative if the
code isn't properly recognized by the clang compiler.

Added: 
    clang-tools-extra/test/clang-tidy/infrastructure/removed-args.cpp

Modified: 
    clang-tools-extra/clang-tidy/ClangTidy.cpp
    clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
    clang-tools-extra/clang-tidy/ClangTidyOptions.h
    clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
    clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
    clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/index.rst
    clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp 
b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 4af328cd5110a..46cf7b1e6ef50 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
+  const ArgumentsAdjuster PerFileArgumentRemover =
+      [&Context](const CommandLineArguments &Args, StringRef Filename) {
+        ClangTidyOptions Opts = Context.getOptionsForFile(Filename);
+        CommandLineArguments AdjustedArgs = Args;
+
+        if (Opts.RemovedArgs) {
+          for (const 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 f61540069d071..2ebab00b3ed91 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -232,6 +232,7 @@ template <> struct MappingTraits<ClangTidyOptions> {
     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);
@@ -254,6 +255,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);
@@ -297,6 +299,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<std::string> 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<std::string> ExcludeHeaderFilterRegex;
 
@@ -151,6 +151,9 @@ struct ClangTidyOptions {
   /// Add extra compilation arguments to the start of the list.
   std::optional<ArgList> ExtraArgsBefore;
 
+  /// Remove command line arguments sent to the compiler matching this.
+  std::optional<ArgList> 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 6a1f61dd6b9e1..efcd508965fb5 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
@@ -356,6 +358,16 @@ see 
https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html.
                                               cl::init(false),
                                               cl::cat(ClangTidyCategory));
 
+static cl::list<std::string> 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 analyzed 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) {
@@ -422,6 +434,8 @@ 
createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> 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 d2b7642bdf01e..fc2e52c5fa38d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -199,6 +199,11 @@ Improvements to clang-tidy
   From now on, users should specify explicitly that they want CSA checks to run
   in :program:`clang-tidy`.
 
+- 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..6647661a13104
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/removed-args.cpp
@@ -0,0 +1,8 @@
+// RUN: not clang-tidy %s --checks="readability-function-size" -- 
-fnot-an-option | FileCheck %s -check-prefix=INVALID-A
+// RUN: clang-tidy %s --checks="readability-function-size" 
--config="{RemovedArgs: ['-fnot-an-option']}" -- -fnot-an-option
+// RUN: clang-tidy %s --checks="readability-function-size" 
--config="{RemovedArgs: ['-fnot-another-option', '-fnot-an-option']}" -- 
-fnot-an-option -fnot-another-option
+// RUN: clang-tidy %s --checks="readability-function-size" 
--removed-arg="-fnot-an-option" -- -fnot-an-option
+// RUN: not clang-tidy %s --checks="readability-function-size" 
--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]


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to