[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

Justin Cady via cfe-commits cfe-commits at lists.llvm.org
Fri May 10 12:43:59 PDT 2024


https://github.com/justincady updated https://github.com/llvm/llvm-project/pull/91400

>From a5de583aa94ef794a083c8b27df6dc6fc0762cb7 Mon Sep 17 00:00:00 2001
From: Justin Cady <desk at justincady.com>
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/5] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp   | 10 +++++++++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h     |  5 +++++
 .../clang-tidy/ClangTidyOptions.cpp              |  4 ++++
 clang-tools-extra/clang-tidy/ClangTidyOptions.h  |  4 ++++
 .../clang-tidy/tool/ClangTidyMain.cpp            | 16 ++++++++++++++++
 .../clang-tidy/infrastructure/file-filter.cpp    |  7 +++++++
 6 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..3cde0d2d68874 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -564,7 +564,8 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
                                Sources.isInMainFile(Location) ||
-                               getHeaderFilter()->match(FileName);
+                               (getHeaderFilter()->match(FileName) &&
+                                !getExcludeHeaderFilter()->match(FileName));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -578,6 +579,13 @@ llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+    ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
+        *Context.getOptions().ExcludeHeaderFilterRegex);
+  return ExcludeHeaderFilter.get();
+}
+
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..a3add5d52778d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,6 +299,10 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
+  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
+  /// in the context.
+  llvm::Regex *getExcludeHeaderFilter();
+
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -313,6 +317,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector<ClangTidyError> Errors;
   std::unique_ptr<llvm::Regex> HeaderFilter;
+  std::unique_ptr<llvm::Regex> ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..254ce7fc60fc9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -170,6 +170,8 @@ template <> struct MappingTraits<ClangTidyOptions> {
     IO.mapOptional("ImplementationFileExtensions",
                    Options.ImplementationFileExtensions);
     IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+    IO.mapOptional("ExcludeHeaderFilterRegex",
+                   Options.ExcludeHeaderFilterRegex);
     IO.mapOptional("FormatStyle", Options.FormatStyle);
     IO.mapOptional("User", Options.User);
     IO.mapOptional("CheckOptions", Options.CheckOptions);
@@ -192,6 +194,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
   Options.HeaderFilterRegex = "";
+  Options.ExcludeHeaderFilterRegex = "";
   Options.SystemHeaders = false;
   Options.FormatStyle = "none";
   Options.User = std::nullopt;
@@ -231,6 +234,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
   overrideValue(ImplementationFileExtensions,
                 Other.ImplementationFileExtensions);
   overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex);
+  overrideValue(ExcludeHeaderFilterRegex, Other.ExcludeHeaderFilterRegex);
   overrideValue(SystemHeaders, Other.SystemHeaders);
   overrideValue(FormatStyle, Other.FormatStyle);
   overrideValue(User, Other.User);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
index e7636cb5d9b06..85d5a02ebbc1b 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -83,6 +83,10 @@ struct ClangTidyOptions {
   /// main files will always be displayed.
   std::optional<std::string> HeaderFilterRegex;
 
+  /// \brief Exclude warnings from headers matching this filter, even if they
+  /// match \c HeaderFilterRegex.
+  std::optional<std::string> ExcludeHeaderFilterRegex;
+
   /// Output warnings from system headers matching \c HeaderFilterRegex.
   std::optional<bool> SystemHeaders;
 
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index f82f4417141d3..88c69a9991d26 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -132,6 +132,19 @@ option in .clang-tidy file, if any.
                                          cl::init(""),
                                          cl::cat(ClangTidyCategory));
 
+static cl::opt<std::string> ExcludeHeaderFilter("exclude-header-filter",
+                                                cl::desc(R"(
+Regular expression matching the names of the
+headers to exclude diagnostics from. Diagnostics
+from the main file of each translation unit are
+always displayed.
+Can be used together with -line-filter.
+This option overrides the 'ExcludeHeaderFilterRegex'
+option in .clang-tidy file, if any.
+)"),
+                                                cl::init(""),
+                                                cl::cat(ClangTidyCategory));
+
 static cl::opt<bool> SystemHeaders("system-headers", desc(R"(
 Display the errors from system headers.
 This option overrides the 'SystemHeaders' option
@@ -353,6 +366,7 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
   DefaultOptions.Checks = DefaultChecks;
   DefaultOptions.WarningsAsErrors = "";
   DefaultOptions.HeaderFilterRegex = HeaderFilter;
+  DefaultOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
   DefaultOptions.SystemHeaders = SystemHeaders;
   DefaultOptions.FormatStyle = FormatStyle;
   DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
@@ -367,6 +381,8 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
     OverrideOptions.WarningsAsErrors = WarningsAsErrors;
   if (HeaderFilter.getNumOccurrences() > 0)
     OverrideOptions.HeaderFilterRegex = HeaderFilter;
+  if (ExcludeHeaderFilter.getNumOccurrences() > 0)
+    OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
   if (SystemHeaders.getNumOccurrences() > 0)
     OverrideOptions.SystemHeaders = SystemHeaders;
   if (FormatStyle.getNumOccurrences() > 0)
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
index a7498723de2bf..448ef9ddf166c 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/file-filter.cpp
@@ -11,6 +11,7 @@
 // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
 // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5 %s
 // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5-NO-SYSTEM-HEADERS %s
+// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -exclude-header-filter='header1\.h' %s -- -I %S/Inputs/file-filter/ -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK6 %s
 
 #include "header1.h"
 // CHECK-NOT: warning:
@@ -21,6 +22,7 @@
 // CHECK3-QUIET-NOT: warning:
 // CHECK4: header1.h:1:12: warning: single-argument constructors
 // CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors
+// CHECK6-NOT: warning:
 
 #include "header2.h"
 // CHECK-NOT: warning:
@@ -31,6 +33,7 @@
 // CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors
 // CHECK4: header2.h:1:12: warning: single-argument constructors
 // CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors
+// CHECK6: header2.h:1:12: warning: single-argument constructors
 
 #include <system-header.h>
 // CHECK-NOT: warning:
@@ -41,6 +44,7 @@
 // CHECK3-QUIET-NOT: warning:
 // CHECK4: system-header.h:1:12: warning: single-argument constructors
 // CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors
+// CHECK6-NOT: warning:
 
 class A { A(int); };
 // CHECK: :[[@LINE-1]]:11: warning: single-argument constructors
@@ -51,6 +55,7 @@ class A { A(int); };
 // CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors
 // CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors
 // CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors
+// CHECK6: :[[@LINE-9]]:11: warning: single-argument constructors
 
 // CHECK-NOT: warning:
 // CHECK-QUIET-NOT: warning:
@@ -73,6 +78,8 @@ class A { A(int); };
 // CHECK4-NOT: Suppressed {{.*}} warnings
 // CHECK4-NOT: Use -header-filter=.* {{.*}}
 // CHECK4-QUIET-NOT: Suppressed
+// CHECK6: Suppressed 2 warnings (2 in non-user code)
+// CHECK6: Use -header-filter=.* {{.*}}
 
 int x = 123;
 auto x_ptr = TO_FLOAT_PTR(&x);

>From c8823c82c6e1669af8505440aae9099b714c55c8 Mon Sep 17 00:00:00 2001
From: Justin Cady <desk at justincady.com>
Date: Wed, 8 May 2024 16:12:40 -0400
Subject: [PATCH 2/5] * Avoid matching on the ExcludeHeaderFilterRegex if it
 was not   specified by the user * Update Python wrapper to handle
 `--exclude-header-filter` * Update both release notes and clang-tidy
 documentation

---
 .../ClangTidyDiagnosticConsumer.cpp           |  22 +-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   4 -
 .../clang-tidy/ClangTidyOptions.cpp           |   2 +-
 .../clang-tidy/tool/ClangTidyMain.cpp         |   3 +-
 .../clang-tidy/tool/run-clang-tidy.py         |  13 +
 clang-tools-extra/docs/ReleaseNotes.rst       |   2 +
 clang-tools-extra/docs/clang-tidy/index.rst   | 234 +++++++++---------
 7 files changed, 149 insertions(+), 131 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 3cde0d2d68874..d9352dafec23f 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -311,7 +311,12 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
     : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
       RemoveIncompatibleErrors(RemoveIncompatibleErrors),
       GetFixesFromNotes(GetFixesFromNotes),
-      EnableNolintBlocks(EnableNolintBlocks) {}
+      EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex)
+    ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
+        *Context.getOptions().ExcludeHeaderFilterRegex);
+}
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -562,10 +567,10 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-                               Sources.isInMainFile(Location) ||
-                               (getHeaderFilter()->match(FileName) &&
-                                !getExcludeHeaderFilter()->match(FileName));
+  LastErrorRelatesToUserCode =
+      LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+      (getHeaderFilter()->match(FileName) &&
+       (ExcludeHeaderFilter ? !ExcludeHeaderFilter->match(FileName) : true));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -579,13 +584,6 @@ llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
-  if (!ExcludeHeaderFilter)
-    ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
-        *Context.getOptions().ExcludeHeaderFilterRegex);
-  return ExcludeHeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index a3add5d52778d..97e16a12febd0 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,10 +299,6 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
-  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
-  /// in the context.
-  llvm::Regex *getExcludeHeaderFilter();
-
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index 254ce7fc60fc9..ef98b7ef6e0cd 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -194,7 +194,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
   Options.HeaderFilterRegex = "";
-  Options.ExcludeHeaderFilterRegex = "";
+  Options.ExcludeHeaderFilterRegex = std::nullopt;
   Options.SystemHeaders = false;
   Options.FormatStyle = "none";
   Options.User = std::nullopt;
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 88c69a9991d26..b449c2ed50bd1 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -53,6 +53,7 @@ Configuration files:
   Checks                       - Same as '--checks'. Additionally, the list of
                                  globs can be specified as a list instead of a
                                  string.
+  ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
   ExtraArgs                    - Same as '--extra-args'.
   ExtraArgsBefore              - Same as '--extra-args-before'.
   FormatStyle                  - Same as '--format-style'.
@@ -133,7 +134,7 @@ option in .clang-tidy file, if any.
                                          cl::cat(ClangTidyCategory));
 
 static cl::opt<std::string> ExcludeHeaderFilter("exclude-header-filter",
-                                                cl::desc(R"(
+                                                desc(R"(
 Regular expression matching the names of the
 headers to exclude diagnostics from. Diagnostics
 from the main file of each translation unit are
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 1bd4a5b283091..f9750b2a2c56d 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -106,11 +106,14 @@ def get_tidy_invocation(
     use_color,
     plugins,
     warnings_as_errors,
+    exclude_header_filter,
 ):
     """Gets a command line for clang-tidy."""
     start = [clang_tidy_binary]
     if allow_enabling_alpha_checkers:
         start.append("-allow-enabling-analyzer-alpha-checkers")
+    if exclude_header_filter is not None:
+        start.append("--exclude-header-filter=" + exclude_header_filter)
     if header_filter is not None:
         start.append("-header-filter=" + header_filter)
     if line_filter is not None:
@@ -228,6 +231,7 @@ def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_fi
             args.use_color,
             args.plugins,
             args.warnings_as_errors,
+            args.exclude_header_filter,
         )
 
         proc = subprocess.Popen(
@@ -292,6 +296,14 @@ def main():
         "-config option after reading specified config file. "
         "Use either -config-file or -config, not both.",
     )
+    parser.add_argument(
+        "-exclude-header-filter",
+        default=None,
+        help="regular expression matching the names of the "
+        "headers to exclude diagnostics from. Diagnostics from "
+        "the main file of each translation unit are always "
+        "displayed.",
+    )
     parser.add_argument(
         "-header-filter",
         default=None,
@@ -450,6 +462,7 @@ def main():
             args.use_color,
             args.plugins,
             args.warnings_as_errors,
+            args.exclude_header_filter,
         )
         invocation.append("-list-checks")
         invocation.append("-")
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5d6d0351362e4..2e093ea1d44fe 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,6 +113,8 @@ Improvements to clang-tidy
 - Fixed `--verify-config` option not properly parsing checks when using the
   literal operator in the `.clang-tidy` config.
 
+- Added argument `--exclude-header-filter` to exclude headers from analysis via a RegEx.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index 852566f266723..f674ebfc273b5 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -116,122 +116,129 @@ An overview of all the command-line options:
 
   Generic Options:
 
-    --help                          - Display available options (--help-hidden for more)
-    --help-list                     - Display list of available options (--help-list-hidden for more)
-    --version                       - Display the version of this program
+    --help                           - Display available options (--help-hidden for more)
+    --help-list                      - Display list of available options (--help-list-hidden for more)
+    --version                        - Display the version of this program
 
   clang-tidy options:
 
-    --checks=<string>               - Comma-separated list of globs with optional '-'
-                                      prefix. Globs are processed in order of
-                                      appearance in the list. Globs without '-'
-                                      prefix add checks with matching names to the
-                                      set, globs with the '-' prefix remove checks
-                                      with matching names from the set of enabled
-                                      checks. This option's value is appended to the
-                                      value of the 'Checks' option in .clang-tidy
-                                      file, if any.
-    --config=<string>               - Specifies a configuration in YAML/JSON format:
-                                        -config="{Checks: '*',
-                                                  CheckOptions: {x: y}}"
-                                      When the value is empty, clang-tidy will
-                                      attempt to find a file named .clang-tidy for
-                                      each source file in its parent directories.
-    --config-file=<string>          - Specify the path of .clang-tidy or custom config file:
-                                       e.g. --config-file=/some/path/myTidyConfigFile
-                                      This option internally works exactly the same way as
-                                       --config option after reading specified config file.
-                                      Use either --config-file or --config, not both.
-    --dump-config                   - Dumps configuration in the YAML format to
-                                      stdout. This option can be used along with a
-                                      file name (and '--' if the file is outside of a
-                                      project with configured compilation database).
-                                      The configuration used for this file will be
-                                      printed.
-                                      Use along with -checks=* to include
-                                      configuration of all checks.
-    --enable-check-profile          - Enable per-check timing profiles, and print a
-                                      report to stderr.
-    --enable-module-headers-parsing - Enables preprocessor-level module header parsing
-                                      for C++20 and above, empowering specific checks
-                                      to detect macro definitions within modules. This
-                                      feature may cause performance and parsing issues
-                                      and is therefore considered experimental.
-    --explain-config                - For each enabled check explains, where it is
-                                      enabled, i.e. in clang-tidy binary, command
-                                      line or a specific configuration file.
-    --export-fixes=<filename>       - YAML file to store suggested fixes in. The
-                                      stored fixes can be applied to the input source
-                                      code with clang-apply-replacements.
-    --extra-arg=<string>            - Additional argument to append to the compiler command line
-    --extra-arg-before=<string>     - Additional argument to prepend to the compiler command line
-    --fix                           - Apply suggested fixes. Without -fix-errors
-                                      clang-tidy will bail out if any compilation
-                                      errors were found.
-    --fix-errors                    - Apply suggested fixes even if compilation
-                                      errors were found. If compiler errors have
-                                      attached fix-its, clang-tidy will apply them as
-                                      well.
-    --fix-notes                     - If a warning has no fix, but a single fix can
-                                      be found through an associated diagnostic note,
-                                      apply the fix.
-                                      Specifying this flag will implicitly enable the
-                                      '--fix' flag.
-    --format-style=<string>         - Style for formatting code around applied fixes:
-                                        - 'none' (default) turns off formatting
-                                        - 'file' (literally 'file', not a placeholder)
-                                          uses .clang-format file in the closest parent
-                                          directory
-                                        - '{ <json> }' specifies options inline, e.g.
-                                          -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
-                                        - 'llvm', 'google', 'webkit', 'mozilla'
-                                      See clang-format documentation for the up-to-date
-                                      information about formatting styles and options.
-                                      This option overrides the 'FormatStyle` option in
-                                      .clang-tidy file, if any.
-    --header-filter=<string>        - Regular expression matching the names of the
-                                      headers to output diagnostics from. Diagnostics
-                                      from the main file of each translation unit are
-                                      always displayed.
-                                      Can be used together with -line-filter.
-                                      This option overrides the 'HeaderFilterRegex'
-                                      option in .clang-tidy file, if any.
-    --line-filter=<string>          - List of files with line ranges to filter the
-                                      warnings. Can be used together with
-                                      -header-filter. The format of the list is a
-                                      JSON array of objects:
-                                        [
-                                          {"name":"file1.cpp","lines":[[1,3],[5,7]]},
-                                          {"name":"file2.h"}
-                                        ]
-    --list-checks                   - List all enabled checks and exit. Use with
-                                      -checks=* to list all available checks.
-    --load=<pluginfilename>         - Load the specified plugin
-    -p <string>                     - Build path
-    --quiet                         - Run clang-tidy in quiet mode. This suppresses
-                                      printing statistics about ignored warnings and
-                                      warnings treated as errors if the respective
-                                      options are specified.
-    --store-check-profile=<prefix>  - By default reports are printed in tabulated
-                                      format to stderr. When this option is passed,
-                                      these per-TU profiles are instead stored as JSON.
-    --system-headers                - Display the errors from system headers.
-                                      This option overrides the 'SystemHeaders' option
-                                      in .clang-tidy file, if any.
-    --use-color                     - Use colors in diagnostics. If not set, colors
-                                      will be used if the terminal connected to
-                                      standard output supports colors.
-                                      This option overrides the 'UseColor' option in
-                                      .clang-tidy file, if any.
-    --verify-config                 - Check the config files to ensure each check and
-                                      option is recognized.
-    --vfsoverlay=<filename>         - Overlay the virtual filesystem described by file
-                                      over the real file system.
-    --warnings-as-errors=<string>   - Upgrades warnings to errors. Same format as
-                                      '-checks'.
-                                      This option's value is appended to the value of
-                                      the 'WarningsAsErrors' option in .clang-tidy
-                                      file, if any.
+    --checks=<string>                - Comma-separated list of globs with optional '-'
+                                       prefix. Globs are processed in order of
+                                       appearance in the list. Globs without '-'
+                                       prefix add checks with matching names to the
+                                       set, globs with the '-' prefix remove checks
+                                       with matching names from the set of enabled
+                                       checks. This option's value is appended to the
+                                       value of the 'Checks' option in .clang-tidy
+                                       file, if any.
+    --config=<string>                - Specifies a configuration in YAML/JSON format:
+                                         -config="{Checks: '*',
+                                                   CheckOptions: {x: y}}"
+                                       When the value is empty, clang-tidy will
+                                       attempt to find a file named .clang-tidy for
+                                       each source file in its parent directories.
+    --config-file=<string>           - Specify the path of .clang-tidy or custom config file:
+                                        e.g. --config-file=/some/path/myTidyConfigFile
+                                       This option internally works exactly the same way as
+                                        --config option after reading specified config file.
+                                       Use either --config-file or --config, not both.
+    --dump-config                    - Dumps configuration in the YAML format to
+                                       stdout. This option can be used along with a
+                                       file name (and '--' if the file is outside of a
+                                       project with configured compilation database).
+                                       The configuration used for this file will be
+                                       printed.
+                                       Use along with -checks=* to include
+                                       configuration of all checks.
+    --enable-check-profile           - Enable per-check timing profiles, and print a
+                                       report to stderr.
+    --enable-module-headers-parsing  - Enables preprocessor-level module header parsing
+                                       for C++20 and above, empowering specific checks
+                                       to detect macro definitions within modules. This
+                                       feature may cause performance and parsing issues
+                                       and is therefore considered experimental.
+    --exclude-header-filter=<string> - Regular expression matching the names of the
+                                       headers to exclude diagnostics from. Diagnostics
+                                       from the main file of each translation unit are
+                                       always displayed.
+                                       Can be used together with -line-filter.
+                                       This option overrides the 'ExcludeHeaderFilterRegex'
+                                       option in .clang-tidy file, if any.
+    --explain-config                 - For each enabled check explains, where it is
+                                       enabled, i.e. in clang-tidy binary, command
+                                       line or a specific configuration file.
+    --export-fixes=<filename>        - YAML file to store suggested fixes in. The
+                                       stored fixes can be applied to the input source
+                                       code with clang-apply-replacements.
+    --extra-arg=<string>             - Additional argument to append to the compiler command line
+    --extra-arg-before=<string>      - Additional argument to prepend to the compiler command line
+    --fix                            - Apply suggested fixes. Without -fix-errors
+                                       clang-tidy will bail out if any compilation
+                                       errors were found.
+    --fix-errors                     - Apply suggested fixes even if compilation
+                                       errors were found. If compiler errors have
+                                       attached fix-its, clang-tidy will apply them as
+                                       well.
+    --fix-notes                      - If a warning has no fix, but a single fix can
+                                       be found through an associated diagnostic note,
+                                       apply the fix.
+                                       Specifying this flag will implicitly enable the
+                                       '--fix' flag.
+    --format-style=<string>          - Style for formatting code around applied fixes:
+                                         - 'none' (default) turns off formatting
+                                         - 'file' (literally 'file', not a placeholder)
+                                           uses .clang-format file in the closest parent
+                                           directory
+                                         - '{ <json> }' specifies options inline, e.g.
+                                           -format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
+                                         - 'llvm', 'google', 'webkit', 'mozilla'
+                                       See clang-format documentation for the up-to-date
+                                       information about formatting styles and options.
+                                       This option overrides the 'FormatStyle` option in
+                                       .clang-tidy file, if any.
+    --header-filter=<string>         - Regular expression matching the names of the
+                                       headers to output diagnostics from. Diagnostics
+                                       from the main file of each translation unit are
+                                       always displayed.
+                                       Can be used together with -line-filter.
+                                       This option overrides the 'HeaderFilterRegex'
+                                       option in .clang-tidy file, if any.
+    --line-filter=<string>           - List of files with line ranges to filter the
+                                       warnings. Can be used together with
+                                       -header-filter. The format of the list is a
+                                       JSON array of objects:
+                                         [
+                                           {"name":"file1.cpp","lines":[[1,3],[5,7]]},
+                                           {"name":"file2.h"}
+                                         ]
+    --list-checks                    - List all enabled checks and exit. Use with
+                                       -checks=* to list all available checks.
+    --load=<pluginfilename>          - Load the specified plugin
+    -p <string>                      - Build path
+    --quiet                          - Run clang-tidy in quiet mode. This suppresses
+                                       printing statistics about ignored warnings and
+                                       warnings treated as errors if the respective
+                                       options are specified.
+    --store-check-profile=<prefix>   - By default reports are printed in tabulated
+                                       format to stderr. When this option is passed,
+                                       these per-TU profiles are instead stored as JSON.
+    --system-headers                 - Display the errors from system headers.
+                                       This option overrides the 'SystemHeaders' option
+                                       in .clang-tidy file, if any.
+    --use-color                      - Use colors in diagnostics. If not set, colors
+                                       will be used if the terminal connected to
+                                       standard output supports colors.
+                                       This option overrides the 'UseColor' option in
+                                       .clang-tidy file, if any.
+    --verify-config                  - Check the config files to ensure each check and
+                                       option is recognized.
+    --vfsoverlay=<filename>          - Overlay the virtual filesystem described by file
+                                       over the real file system.
+    --warnings-as-errors=<string>    - Upgrades warnings to errors. Same format as
+                                       '-checks'.
+                                       This option's value is appended to the value of
+                                       the 'WarningsAsErrors' option in .clang-tidy
+                                       file, if any.
 
   -p <build-path> is used to read a compile command database.
 
@@ -269,6 +276,7 @@ An overview of all the command-line options:
     Checks                       - Same as '--checks'. Additionally, the list of
                                    globs can be specified as a list instead of a
                                    string.
+    ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
     ExtraArgs                    - Same as '--extra-args'.
     ExtraArgsBefore              - Same as '--extra-args-before'.
     FormatStyle                  - Same as '--format-style'.

>From 569779de7c391ae0bf85c4dd0b5fc93cc5f8f57a Mon Sep 17 00:00:00 2001
From: Justin Cady <desk at justincady.com>
Date: Thu, 9 May 2024 13:24:14 -0400
Subject: [PATCH 3/5] * Simplify the conditional for checking
 ExcludeHeaderFilter * Add test for ExcludeHeaderFilterRegex in .clang-tidy *
 Add tests for --dump-config with ExcludeHeaderFilterRegex set and unset

---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp    |  2 +-
 .../Inputs/config-files/.clang-tidy               |  1 +
 .../Inputs/config-files/1/.clang-tidy             |  1 +
 .../Inputs/config-files/3/.clang-tidy             |  1 +
 .../clang-tidy/infrastructure/config-files.cpp    | 15 ++++++++++++++-
 5 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index d9352dafec23f..e0f6eb661a9ff 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -570,7 +570,7 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   LastErrorRelatesToUserCode =
       LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
       (getHeaderFilter()->match(FileName) &&
-       (ExcludeHeaderFilter ? !ExcludeHeaderFilter->match(FileName) : true));
+       !(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName)));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy
index 942169f2ec429..83605c85dd92c 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/.clang-tidy
@@ -1,2 +1,3 @@
 Checks: 'from-parent'
 HeaderFilterRegex: 'parent'
+ExcludeHeaderFilterRegex: 'exc-parent'
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy
index 800fd4e8eb2a9..c37f16bc2d7d2 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/1/.clang-tidy
@@ -1,2 +1,3 @@
 Checks: 'from-child1'
 HeaderFilterRegex: 'child1'
+ExcludeHeaderFilterRegex: 'exc-child1'
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy
index 28dc8517ac9fe..9365108255bd8 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/config-files/3/.clang-tidy
@@ -1,3 +1,4 @@
 InheritParentConfig: true
 Checks: 'from-child3'
 HeaderFilterRegex: 'child3'
+ExcludeHeaderFilterRegex: 'exc-child3'
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp
index d287412454cad..44d43ebbf8d20 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp
@@ -1,18 +1,23 @@
 // RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE
 // CHECK-BASE: Checks: {{.*}}from-parent
 // CHECK-BASE: HeaderFilterRegex: parent
+// CHECK-BASE: ExcludeHeaderFilterRegex: exc-parent
 // RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1
 // CHECK-CHILD1: Checks: {{.*}}from-child1
 // CHECK-CHILD1: HeaderFilterRegex: child1
+// CHECK-CHILD1: ExcludeHeaderFilterRegex: exc-child1
 // RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2
 // CHECK-CHILD2: Checks: {{.*}}from-parent
 // CHECK-CHILD2: HeaderFilterRegex: parent
+// CHECK-CHILD2: ExcludeHeaderFilterRegex: exc-parent
 // RUN: clang-tidy -dump-config %S/Inputs/config-files/3/- -- | FileCheck %s -check-prefix=CHECK-CHILD3
 // CHECK-CHILD3: Checks: {{.*}}from-parent,from-child3
 // CHECK-CHILD3: HeaderFilterRegex: child3
-// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE
+// CHECK-CHILD3: ExcludeHeaderFilterRegex: exc-child3
+// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' -exclude-header-filter='from_command_line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE
 // CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line
 // CHECK-COMMAND-LINE: HeaderFilterRegex: from command line
+// CHECK-COMMAND-LINE: ExcludeHeaderFilterRegex: from_command_line
 
 // For this test we have to use names of the real checks because otherwise values are ignored.
 // Running with the old key: <Key>, value: <value> CheckOptions
@@ -68,3 +73,11 @@
 // Dumped config does not overflow for unsigned options
 // RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- -- | FileCheck %s -check-prefix=CHECK-OVERFLOW
 // CHECK-OVERFLOW: misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976'
+
+// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='foo/*' -exclude-header-filter='bar*' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-EXCLUDE-HEADERS
+// CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: 'foo/*'
+// CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: 'bar*'
+
+// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='' -exclude-header-filter='' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=EMPTY-CHECK-EXCLUDE-HEADERS
+// EMPTY-CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: ''
+// EMPTY-CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: ''

>From 1b68670db6fc3f52579cacc7825733eb0c1362cb Mon Sep 17 00:00:00 2001
From: Justin Cady <desk at justincady.com>
Date: Fri, 10 May 2024 10:17:44 -0400
Subject: [PATCH 4/5] Check if ExcludeHeaderFilterRegex is set to empty string

---
 clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index e0f6eb661a9ff..05ba8ca492f5c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -313,7 +313,8 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
       GetFixesFromNotes(GetFixesFromNotes),
       EnableNolintBlocks(EnableNolintBlocks) {
 
-  if (Context.getOptions().ExcludeHeaderFilterRegex)
+  if (Context.getOptions().ExcludeHeaderFilterRegex &&
+      !Context.getOptions().ExcludeHeaderFilterRegex->empty())
     ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
         *Context.getOptions().ExcludeHeaderFilterRegex);
 }

>From a5610e8ab1defd4607bf79773a34a09ead5f4670 Mon Sep 17 00:00:00 2001
From: Justin Cady <desk at justincady.com>
Date: Fri, 10 May 2024 15:42:45 -0400
Subject: [PATCH 5/5] Apply the new ExcludeHeaderFilterRegex pattern to
 HeaderFilterRegex

---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp  | 17 ++++++++---------
 .../clang-tidy/ClangTidyOptions.cpp             |  2 +-
 .../clang-tidy/tool/ClangTidyMain.cpp           |  1 +
 clang-tools-extra/docs/clang-tidy/index.rst     |  1 +
 4 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 05ba8ca492f5c..200bb87a5ac3c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -313,6 +313,11 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
       GetFixesFromNotes(GetFixesFromNotes),
       EnableNolintBlocks(EnableNolintBlocks) {
 
+  if (Context.getOptions().HeaderFilterRegex &&
+      !Context.getOptions().HeaderFilterRegex->empty())
+    HeaderFilter =
+        std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
+
   if (Context.getOptions().ExcludeHeaderFilterRegex &&
       !Context.getOptions().ExcludeHeaderFilterRegex->empty())
     ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
@@ -570,21 +575,15 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode =
       LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
-      (getHeaderFilter()->match(FileName) &&
-       !(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName)));
+      (HeaderFilter &&
+       (HeaderFilter->match(FileName) &&
+        !(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName))));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
       LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-    HeaderFilter =
-        std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index ef98b7ef6e0cd..445c7f85c900c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -193,7 +193,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.WarningsAsErrors = "";
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
-  Options.HeaderFilterRegex = "";
+  Options.HeaderFilterRegex = std::nullopt;
   Options.ExcludeHeaderFilterRegex = std::nullopt;
   Options.SystemHeaders = false;
   Options.FormatStyle = "none";
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index b449c2ed50bd1..7388f20ef288e 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -139,6 +139,7 @@ Regular expression matching the names of the
 headers to exclude diagnostics from. Diagnostics
 from the main file of each translation unit are
 always displayed.
+Must be used together with --header-filter.
 Can be used together with -line-filter.
 This option overrides the 'ExcludeHeaderFilterRegex'
 option in .clang-tidy file, if any.
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index f674ebfc273b5..9ccacefa3c2c5 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -161,6 +161,7 @@ An overview of all the command-line options:
                                        headers to exclude diagnostics from. Diagnostics
                                        from the main file of each translation unit are
                                        always displayed.
+                                       Must be used together with --header-filter.
                                        Can be used together with -line-filter.
                                        This option overrides the 'ExcludeHeaderFilterRegex'
                                        option in .clang-tidy file, if any.



More information about the cfe-commits mailing list