Skip to content

Conversation

@felix642
Copy link
Contributor

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 (#162201 (comment)).

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.

@llvmbot
Copy link
Member

llvmbot commented Oct 21, 2025

@llvm/pr-subscribers-clang-tools-extra

@llvm/pr-subscribers-clang-tidy

Author: Félix-Antoine Constantin (felix642)

Changes

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 (#162201 (comment)).

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.


Full diff: https://github.com/llvm/llvm-project/pull/164344.diff

6 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/ClangTidy.cpp (+18)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyOptions.cpp (+3)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyOptions.h (+4)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
  • (modified) clang-tools-extra/docs/clang-tidy/index.rst (+5)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/compilation-args-to-ignore.cpp (+5)
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 7e18f3806a143..6e91e0a254c0f 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -581,6 +581,24 @@ runClangTidy(clang::tidy::ClangTidyContext &Context,
         return AdjustedArgs;
       };
 
+  // Remove unwanted arguments passed to the compiler
+  ArgumentsAdjuster CompilationArgsToRemove =
+      [&Context](const CommandLineArguments &Args, StringRef Filename) {
+        ClangTidyOptions Opts = Context.getOptionsForFile(Filename);
+        CommandLineArguments AdjustedArgs = Args;
+
+        if (Opts.RemovedArgs) {
+          for (StringRef ArgToIgnore : *Opts.RemovedArgs) {
+            AdjustedArgs.erase(std::remove(AdjustedArgs.begin(),
+                                           AdjustedArgs.end(), ArgToIgnore),
+                               AdjustedArgs.end());
+          }
+        }
+
+        return AdjustedArgs;
+      };
+
+  Tool.appendArgumentsAdjuster(CompilationArgsToRemove);
   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 b752a9beb0e34..c82ad1e6e899f 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -225,6 +225,7 @@ template <> struct MappingTraits<ClangTidyOptions> {
                    Options.ExcludeHeaderFilterRegex);
     IO.mapOptional("FormatStyle", Options.FormatStyle);
     IO.mapOptional("User", Options.User);
+    IO.mapOptional("RemovedArgs", Options.RemovedArgs);
     IO.mapOptional("CheckOptions", Options.CheckOptions);
     IO.mapOptional("ExtraArgs", Options.ExtraArgs);
     IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore);
@@ -250,6 +251,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);
@@ -290,6 +292,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
   overrideValue(SystemHeaders, Other.SystemHeaders);
   overrideValue(FormatStyle, Other.FormatStyle);
   overrideValue(User, Other.User);
+  mergeVectors(RemovedArgs, Other.RemovedArgs);
   overrideValue(UseColor, Other.UseColor);
   mergeVectors(ExtraArgs, Other.ExtraArgs);
   mergeVectors(ExtraArgsBefore, Other.ExtraArgsBefore);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
index 2aae92f1d9eb3..989b1c651c830 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -112,6 +112,10 @@ struct ClangTidyOptions {
   /// comments in the relevant check.
   std::optional<std::string> User;
 
+  /// \brief Remove command line arguments sent to the compiler matching this
+  /// regex.
+  std::optional<std::vector<std::string>> RemovedArgs;
+
   /// Helper structure for storing option value with priority of the value.
   struct ClangTidyValue {
     ClangTidyValue() = default;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 62e1987377989..1a6cc0869c571 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -123,6 +123,7 @@ Improvements to clang-tidy
   when run over C files. If ``-std`` is not specified, it defaults to
   ``c99-or-later``.
 
+<<<<<<< HEAD
 - :program:`clang-tidy` no longer attemps to analyze code from system headers
   by default, greatly improving performance. This behavior is disabled if the
   `SystemHeaders` option is enabled.
@@ -158,6 +159,10 @@ Improvements to clang-tidy
   scripts by adding the `-hide-progress` option to suppress progress and
   informational messages.
 
+- Improved :program:`clang-tidy` by adding the option 
+  :option:`RemovedArgs` to remove arguments sent to the 
+  compiler when invoking clang-tidy.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index bd2c40e948f34..43142c9121716 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -329,6 +329,10 @@ 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                  - List of arguments to remove from the command
+                                   line sent to the compiler. Please note that 
+                                   removing arguments from the command line 
+                                   might lead to false positive or negatives. 
 
     The effective configuration can be inspected using --dump-config:
 
@@ -338,6 +342,7 @@ An overview of all the command-line options:
       WarningsAsErrors:    ''
       HeaderFileExtensions:         ['', 'h','hh','hpp','hxx']
       ImplementationFileExtensions: ['c','cc','cpp','cxx']
+      RemovedArgs: ['-Werror']
       HeaderFilterRegex:   ''
       FormatStyle:         none
       InheritParentConfig: true
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/compilation-args-to-ignore.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/compilation-args-to-ignore.cpp
new file mode 100644
index 0000000000000..9a042dedce3a4
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/compilation-args-to-ignore.cpp
@@ -0,0 +1,5 @@
+// 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
+
+// INVALID-A: error: unknown argument: '-fnot-an-option' [clang-diagnostic-error]
\ No newline at end of file

@felix642 felix642 force-pushed the compiler-cmd-line-args-clang-tidy branch 2 times, most recently from 608b5f3 to f2c15c6 Compare October 21, 2025 00:17
Copy link
Contributor

@vbvictor vbvictor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also add this option to run-clang-tidy.py and clang-tidy-diff.py. They both seem to support extra-arg already so we should provide remove-arg for them too.

Copy link
Contributor

@vbvictor vbvictor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

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 llvm#108455
@felix642 felix642 force-pushed the compiler-cmd-line-args-clang-tidy branch from bf2f023 to 1b7e069 Compare November 8, 2025 16:06
@felix642
Copy link
Contributor Author

felix642 commented Nov 8, 2025

I would be ready to merge this PR. I'll wait a bit more in case someone has some comments to add, but otherwise I would be ready to merge it in ~48 hours.

// Remove unwanted arguments passed to the compiler
ArgumentsAdjuster PerFileArgumentRemover =
[&Context](const CommandLineArguments &Args, StringRef Filename) {
ClangTidyOptions Opts = Context.getOptionsForFile(Filename);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ignore unknown flags in clang-tidy

6 participants