[clang] [clang-tools-extra] [clang-tidy] Add experimental header-filter scope (PR #194370)

Vladimir Makaev via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 27 06:50:17 PDT 2026


https://github.com/VladimirMakaev updated https://github.com/llvm/llvm-project/pull/194370

>From 4bdd0af7549bb74e568a91a52ef0934311480aa8 Mon Sep 17 00:00:00 2001
From: Vladimir Makaev <vmakaev at gmail.com>
Date: Mon, 27 Apr 2026 13:37:30 +0000
Subject: [PATCH 1/2] [clang-tidy] Add experimental header-filter scope

---
 clang-tools-extra/clang-tidy/ClangTidy.cpp    | 11 ++++
 .../ClangTidyDiagnosticConsumer.cpp           | 33 ++++------
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  | 15 ++---
 .../clang-tidy/ClangTidyOptions.cpp           |  5 ++
 .../clang-tidy/ClangTidyOptions.h             |  6 ++
 .../clang-tidy/HeaderFilterHelpers.h          | 64 +++++++++++++++++++
 .../clang-tidy/tool/ClangTidyMain.cpp         | 26 ++++++++
 .../clang-tidy/tool/run-clang-tidy.py         | 18 ++++++
 clang-tools-extra/docs/ReleaseNotes.rst       |  7 ++
 clang-tools-extra/docs/clang-tidy/index.rst   | 22 ++++++-
 .../Inputs/config-files/.clang-tidy           |  1 +
 .../Inputs/config-files/1/.clang-tidy         |  1 +
 .../Inputs/config-files/3/.clang-tidy         |  1 +
 .../confusable_header.h                       |  1 +
 .../infrastructure/config-files.cpp           |  7 +-
 .../clang-tidy/infrastructure/diagnostic.cpp  |  2 +
 .../infrastructure/dump-config-filtering.cpp  |  2 +
 .../experimental-header-filter-scope.cpp      | 16 +++++
 .../infrastructure/run-clang-tidy.cpp         | 15 +++++
 .../clang/ASTMatchers/ASTMatchFinder.h        |  8 +++
 clang/lib/ASTMatchers/ASTMatchFinder.cpp      | 21 +++++-
 .../ASTMatchers/ASTMatchersInternalTest.cpp   | 50 +++++++++++++++
 22 files changed, 296 insertions(+), 36 deletions(-)
 create mode 100644 clang-tools-extra/clang-tidy/HeaderFilterHelpers.h
 create mode 100644 clang-tools-extra/test/clang-tidy/infrastructure/Inputs/experimental-header-filter-scope/confusable_header.h
 create mode 100644 clang-tools-extra/test/clang-tidy/infrastructure/experimental-header-filter-scope.cpp

diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 05c8fd02fe86a..3292dc44b3539 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -20,6 +20,7 @@
 #include "ClangTidyModule.h"
 #include "ClangTidyProfiling.h"
 #include "ExpandModularHeadersPPCallbacks.h"
+#include "HeaderFilterHelpers.h"
 #include "clang-tidy-config.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -448,6 +449,16 @@ ClangTidyASTConsumerFactory::createASTConsumer(CompilerInstance &Compiler,
   if (!Context.getOptions().SystemHeaders.value_or(false))
     FinderOptions.IgnoreSystemHeaders = true;
 
+  if (Context.getOptions().ExperimentalHeaderFilterScope.value_or(false)) {
+    auto LocationFilter = std::make_shared<HeaderFilterLocationFilter>(
+        Context.getOptions().HeaderFilterRegex.value_or(""),
+        Context.getOptions().ExcludeHeaderFilterRegex.value_or(""));
+    FinderOptions.ShouldSkipLocation =
+        [LocationFilter, SM](SourceLocation Location) {
+          return !LocationFilter->shouldInclude(Location, *SM);
+        };
+  }
+
   auto Finder =
       std::make_unique<ast_matchers::MatchFinder>(std::move(FinderOptions));
 
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index f7232645a329c..6b3569f7cad9e 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -36,7 +36,6 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Regex.h"
 #include <optional>
 #include <tuple>
 #include <utility>
@@ -372,6 +371,7 @@ void ClangTidyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
 
   assert(!InSourceFile);
   InSourceFile = true;
+  HeaderFilterLocation.reset();
 }
 
 void ClangTidyDiagnosticConsumer::EndSourceFile() {
@@ -568,9 +568,10 @@ void ClangTidyDiagnosticConsumer::forwardDiagnostic(const Diagnostic &Info) {
 
 void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
                                                const SourceManager &Sources) {
-  // Invalid location may mean a diagnostic in a command line, don't skip these.
   if (!Location.isValid()) {
-    LastErrorRelatesToUserCode = true;
+    LastErrorRelatesToUserCode =
+        LastErrorRelatesToUserCode ||
+        getHeaderFilterLocationFilter().shouldInclude(Location, Sources);
     LastErrorPassesLineFilter = true;
     return;
   }
@@ -579,6 +580,10 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
       (Sources.isInSystemHeader(Location) || Sources.isInSystemMacro(Location)))
     return;
 
+  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
+                               getHeaderFilterLocationFilter().shouldInclude(
+                                   Location, Sources);
+
   // FIXME: We start with a conservative approach here, but the actual type of
   // location needed depends on the check (in particular, where this check wants
   // to apply fixes).
@@ -588,34 +593,24 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   // -DMACRO definitions on the command line have locations in a virtual buffer
   // that doesn't have a FileEntry. Don't skip these as well.
   if (!File) {
-    LastErrorRelatesToUserCode = true;
     LastErrorPassesLineFilter = true;
     return;
   }
 
   const StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-                               Sources.isInMainFile(Location) ||
-                               (getHeaderFilter()->match(FileName) &&
-                                !getExcludeHeaderFilter()->match(FileName));
 
   const 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.value_or(""));
-  return HeaderFilter.get();
-}
-
-llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
-  if (!ExcludeHeaderFilter)
-    ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
+HeaderFilterLocationFilter &
+ClangTidyDiagnosticConsumer::getHeaderFilterLocationFilter() {
+  if (!HeaderFilterLocation)
+    HeaderFilterLocation = std::make_unique<HeaderFilterLocationFilter>(
+        Context.getOptions().HeaderFilterRegex.value_or(""),
         Context.getOptions().ExcludeHeaderFilterRegex.value_or(""));
-  return ExcludeHeaderFilter.get();
+  return *HeaderFilterLocation;
 }
 
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 8de5778dfefb0..241e70f915677 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -12,12 +12,12 @@
 #include "ClangTidyOptions.h"
 #include "ClangTidyProfiling.h"
 #include "FileExtensionsSet.h"
+#include "HeaderFilterHelpers.h"
 #include "NoLintDirectiveHandler.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Tooling/Core/Diagnostic.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Regex.h"
 #include <optional>
 #include <utility>
 
@@ -310,13 +310,9 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
   void removeIncompatibleErrors();
   void removeDuplicatedDiagnosticsOfAliasCheckers();
 
-  /// Returns the \c HeaderFilter constructed for the options set in the
-  /// context.
-  llvm::Regex *getHeaderFilter();
-
-  /// Returns the \c ExcludeHeaderFilter constructed for the options set in the
-  /// context.
-  llvm::Regex *getExcludeHeaderFilter();
+  /// Returns the cached header-filter evaluator for the current translation
+  /// unit.
+  HeaderFilterLocationFilter &getHeaderFilterLocationFilter();
 
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
@@ -331,8 +327,7 @@ class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
   bool GetFixesFromNotes;
   bool EnableNolintBlocks;
   std::vector<ClangTidyError> Errors;
-  std::unique_ptr<llvm::Regex> HeaderFilter;
-  std::unique_ptr<llvm::Regex> ExcludeHeaderFilter;
+  std::unique_ptr<HeaderFilterLocationFilter> HeaderFilterLocation;
   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 0a0f392346f6d..fb4ae7f472547 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -242,6 +242,8 @@ template <> struct MappingTraits<ClangTidyOptions> {
     IO.mapOptional("InheritParentConfig", Options.InheritParentConfig);
     IO.mapOptional("UseColor", Options.UseColor);
     IO.mapOptional("SystemHeaders", Options.SystemHeaders);
+    IO.mapOptional("ExperimentalHeaderFilterScope",
+                   Options.ExperimentalHeaderFilterScope);
     IO.mapOptional("CustomChecks", Options.CustomChecks);
   }
 };
@@ -259,6 +261,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFilterRegex = ".*";
   Options.ExcludeHeaderFilterRegex = "";
   Options.SystemHeaders = false;
+  Options.ExperimentalHeaderFilterScope = false;
   Options.FormatStyle = "none";
   Options.User = std::nullopt;
   Options.RemovedArgs = std::nullopt;
@@ -300,6 +303,8 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
   overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex);
   overrideValue(ExcludeHeaderFilterRegex, Other.ExcludeHeaderFilterRegex);
   overrideValue(SystemHeaders, Other.SystemHeaders);
+  overrideValue(ExperimentalHeaderFilterScope,
+                Other.ExperimentalHeaderFilterScope);
   overrideValue(FormatStyle, Other.FormatStyle);
   overrideValue(User, Other.User);
   overrideValue(UseColor, Other.UseColor);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
index 73fdbabd5bdba..4dcf9c10444d5 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -92,6 +92,12 @@ struct ClangTidyOptions {
   /// Output warnings from system headers matching \c HeaderFilterRegex.
   std::optional<bool> SystemHeaders;
 
+  /// When set, clang-tidy experimentally skips AST matching for declarations
+  /// in headers that do not match \c HeaderFilterRegex or that match
+  /// \c ExcludeHeaderFilterRegex. Checks that rely on declarations outside the
+  /// filtered headers can produce false negatives.
+  std::optional<bool> ExperimentalHeaderFilterScope;
+
   /// Format code around applied fixes with clang-format using this
   /// style.
   ///
diff --git a/clang-tools-extra/clang-tidy/HeaderFilterHelpers.h b/clang-tools-extra/clang-tidy/HeaderFilterHelpers.h
new file mode 100644
index 0000000000000..23fad8b9533ad
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/HeaderFilterHelpers.h
@@ -0,0 +1,64 @@
+//===--- HeaderFilterHelpers.h - clang-tidy header filtering ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HEADERFILTERHELPERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HEADERFILTERHELPERS_H
+
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
+
+namespace clang::tidy {
+
+/// Evaluates clang-tidy's header filters for source locations and caches the
+/// per-file results for a translation unit.
+class HeaderFilterLocationFilter {
+public:
+  HeaderFilterLocationFilter(llvm::StringRef HeaderFilterRegex,
+                             llvm::StringRef ExcludeHeaderFilterRegex)
+      : HeaderFilter(HeaderFilterRegex),
+        ExcludeHeaderFilter(ExcludeHeaderFilterRegex) {}
+
+  /// Returns true when the location should be treated as in scope for
+  /// clang-tidy's header filters.
+  ///
+  /// Main-file locations are always in scope. Invalid locations and locations
+  /// without a FileEntry (such as command-line buffers) are also treated as in
+  /// scope to match clang-tidy's diagnostic filtering behavior.
+  bool shouldInclude(SourceLocation Location, const SourceManager &Sources) {
+    if (!Location.isValid())
+      return true;
+
+    if (Sources.isInMainFile(Location))
+      return true;
+
+    const FileID FID = Sources.getDecomposedExpansionLoc(Location).first;
+    if (const auto It = Cache.find(FID); It != Cache.end())
+      return It->second;
+
+    bool Result = true;
+    if (const OptionalFileEntryRef File = Sources.getFileEntryRefForID(FID)) {
+      const llvm::StringRef FileName = File->getName();
+      Result =
+          HeaderFilter.match(FileName) && !ExcludeHeaderFilter.match(FileName);
+    }
+
+    Cache[FID] = Result;
+    return Result;
+  }
+
+private:
+  llvm::Regex HeaderFilter;
+  llvm::Regex ExcludeHeaderFilter;
+  llvm::DenseMap<FileID, bool> Cache;
+};
+
+} // namespace clang::tidy
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_HEADERFILTERHELPERS_H
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index f61e2f40ed03b..5ed56e30ccdfc 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -63,6 +63,9 @@ Configuration files:
   CustomChecks                 - Array of user defined checks based on
                                  Clang-Query syntax.
   ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
+  ExperimentalHeaderFilterScope
+                               - Same as
+                                 '--experimental-header-filter-scope'.
   ExtraArgs                    - Same as '--extra-arg'.
   ExtraArgsBefore              - Same as '--extra-arg-before'.
   FormatStyle                  - Same as '--format-style'.
@@ -95,6 +98,7 @@ Configuration files:
     HeaderFileExtensions:         ['', 'h','hh','hpp','hxx']
     ImplementationFileExtensions: ['c','cc','cpp','cxx']
     HeaderFilterRegex:            '.*'
+    ExperimentalHeaderFilterScope: false
     FormatStyle:                  none
     InheritParentConfig:          true
     User:                         user
@@ -158,6 +162,24 @@ option in .clang-tidy file, if any.
                                                 cl::init(""),
                                                 cl::cat(ClangTidyCategory));
 
+static cl::opt<bool>
+    ExperimentalHeaderFilterScope("experimental-header-filter-scope",
+                                  desc(R"(
+When enabled, clang-tidy experimentally skips
+AST matching for declarations in headers that
+do not match -header-filter or that match
+-exclude-header-filter.
+This can improve performance for narrow
+header-filter runs, but checks that rely on
+declarations outside the filtered headers can
+produce false negatives.
+This option overrides the
+'ExperimentalHeaderFilterScope' option in
+.clang-tidy file, if any.
+)"),
+                                  cl::init(false),
+                                  cl::cat(ClangTidyCategory));
+
 static cl::opt<bool> SystemHeaders("system-headers", desc(R"(
 Display the errors from system headers.
 This option overrides the 'SystemHeaders' option
@@ -412,6 +434,7 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
   DefaultOptions.HeaderFilterRegex = HeaderFilter;
   DefaultOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
   DefaultOptions.SystemHeaders = SystemHeaders;
+  DefaultOptions.ExperimentalHeaderFilterScope = ExperimentalHeaderFilterScope;
   DefaultOptions.FormatStyle = FormatStyle;
   DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
   // USERNAME is used on Windows.
@@ -429,6 +452,9 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) {
     OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
   if (SystemHeaders.getNumOccurrences() > 0)
     OverrideOptions.SystemHeaders = SystemHeaders;
+  if (ExperimentalHeaderFilterScope.getNumOccurrences() > 0)
+    OverrideOptions.ExperimentalHeaderFilterScope =
+        ExperimentalHeaderFilterScope;
   if (FormatStyle.getNumOccurrences() > 0)
     OverrideOptions.FormatStyle = FormatStyle;
   if (UseColor.getNumOccurrences() > 0)
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 f827ef492f01c..b9a387bf4b8ba 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -94,6 +94,7 @@ def get_tidy_invocation(
     tmpdir: Optional[str],
     build_path: str,
     header_filter: Optional[str],
+    experimental_header_filter_scope: Optional[bool],
     allow_enabling_alpha_checkers: bool,
     extra_arg: List[str],
     extra_arg_before: List[str],
@@ -117,6 +118,11 @@ def get_tidy_invocation(
         start.append(f"--exclude-header-filter={exclude_header_filter}")
     if header_filter is not None:
         start.append(f"-header-filter={header_filter}")
+    if experimental_header_filter_scope is not None:
+        if experimental_header_filter_scope:
+            start.append("--experimental-header-filter-scope")
+        else:
+            start.append("--experimental-header-filter-scope=false")
     if line_filter is not None:
         start.append(f"-line-filter={line_filter}")
     if use_color is not None:
@@ -378,6 +384,7 @@ async def run_tidy(
         tmpdir,
         build_path,
         args.header_filter,
+        args.experimental_header_filter_scope,
         args.allow_enabling_alpha_checkers,
         args.extra_arg,
         args.extra_arg_before,
@@ -478,6 +485,16 @@ async def main() -> None:
         "the main file of each translation unit are always "
         "displayed.",
     )
+    parser.add_argument(
+        "-experimental-header-filter-scope",
+        type=strtobool,
+        nargs="?",
+        const=True,
+        default=None,
+        help="Enable experimental AST scoping to headers that "
+        "match -header-filter and do not match "
+        "-exclude-header-filter.",
+    )
     parser.add_argument(
         "-source-filter",
         default=None,
@@ -647,6 +664,7 @@ async def main() -> None:
             None,
             build_path,
             args.header_filter,
+            args.experimental_header_filter_scope,
             args.allow_enabling_alpha_checkers,
             args.extra_arg,
             args.extra_arg_before,
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c0956a29895ee..8c4ee6da63005 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -111,6 +111,13 @@ Improvements to clang-tidy
 - Improved :program:`clang-tidy` ``-store-check-profile`` by generating valid
   JSON when the source file path contains characters that require JSON escaping.
 
+- Added an experimental :program:`clang-tidy`
+  ``-experimental-header-filter-scope`` option that skips AST matching for
+  declarations in headers that do not match ``-header-filter`` (or that match
+  ``-exclude-header-filter``). This can improve performance for narrow
+  header-filter runs, but checks that need AST visibility outside the filtered
+  headers can produce false negatives.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst
index db7f2deade9ca..7dbb8142ed69e 100644
--- a/clang-tools-extra/docs/clang-tidy/index.rst
+++ b/clang-tools-extra/docs/clang-tidy/index.rst
@@ -185,6 +185,18 @@ An overview of all the command-line options:
                                        Can be used together with -line-filter.
                                        This option overrides the 'ExcludeHeaderFilterRegex'
                                        option in .clang-tidy file, if any.
+    --experimental-header-filter-scope
+                                     - When enabled, clang-tidy experimentally
+                                       skips AST matching for declarations in
+                                       headers that do not match -header-filter
+                                       or that match -exclude-header-filter.
+                                       This can improve performance for narrow
+                                       header-filter runs, but checks that rely
+                                       on declarations outside the filtered
+                                       headers can produce false negatives.
+                                       This option overrides the
+                                       'ExperimentalHeaderFilterScope' option in
+                                       .clang-tidy file, if any.
     --experimental-custom-checks     - Enable experimental clang-query based
                                        custom checks.
                                        see https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChecks.html.
@@ -320,6 +332,9 @@ An overview of all the command-line options:
     CustomChecks                 - Array of user defined checks based on
                                    Clang-Query syntax.
     ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
+    ExperimentalHeaderFilterScope
+                                 - Same as
+                                   '--experimental-header-filter-scope'.
     ExtraArgs                    - Same as '--extra-arg'.
     ExtraArgsBefore              - Same as '--extra-arg-before'.
     FormatStyle                  - Same as '--format-style'.
@@ -352,6 +367,7 @@ An overview of all the command-line options:
       HeaderFileExtensions:         ['', 'h','hh','hpp','hxx']
       ImplementationFileExtensions: ['c','cc','cpp','cxx']
       HeaderFilterRegex:            '.*'
+      ExperimentalHeaderFilterScope: false
       FormatStyle:                  none
       InheritParentConfig:          true
       User:                         user
@@ -414,9 +430,9 @@ can be generated by build systems like CMake (using
 ``-DCMAKE_EXPORT_COMPILE_COMMANDS=ON``) or by tools like `Bear`_.
 
 The script supports most of the same options as :program:`clang-tidy` itself,
-including ``-checks=``, ``-fix``, ``-header-filter=``, and configuration
-options. Run ``run-clang-tidy.py --help`` for a complete list of available
-options.
+including ``-checks=``, ``-fix``, ``-header-filter=``,
+``-experimental-header-filter-scope``, and configuration options. Run
+``run-clang-tidy.py --help`` for a complete list of available options.
 
 Example invocations:
 
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 83605c85dd92c..64da72adc342e 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,3 +1,4 @@
 Checks: 'from-parent'
 HeaderFilterRegex: 'parent'
 ExcludeHeaderFilterRegex: 'exc-parent'
+ExperimentalHeaderFilterScope: true
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 c37f16bc2d7d2..1991cd343e076 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,3 +1,4 @@
 Checks: 'from-child1'
 HeaderFilterRegex: 'child1'
 ExcludeHeaderFilterRegex: 'exc-child1'
+ExperimentalHeaderFilterScope: false
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 9365108255bd8..39831e357b09e 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
@@ -2,3 +2,4 @@ InheritParentConfig: true
 Checks: 'from-child3'
 HeaderFilterRegex: 'child3'
 ExcludeHeaderFilterRegex: 'exc-child3'
+ExperimentalHeaderFilterScope: false
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/experimental-header-filter-scope/confusable_header.h b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/experimental-header-filter-scope/confusable_header.h
new file mode 100644
index 0000000000000..659f2a3879880
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/experimental-header-filter-scope/confusable_header.h
@@ -0,0 +1 @@
+int l0 = 0;
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 44d43ebbf8d20..f17d6cf138371 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp
@@ -2,22 +2,27 @@
 // CHECK-BASE: Checks: {{.*}}from-parent
 // CHECK-BASE: HeaderFilterRegex: parent
 // CHECK-BASE: ExcludeHeaderFilterRegex: exc-parent
+// CHECK-BASE: ExperimentalHeaderFilterScope: true
 // 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
+// CHECK-CHILD1: ExperimentalHeaderFilterScope: false
 // 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
+// CHECK-CHILD2: ExperimentalHeaderFilterScope: true
 // 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
 // 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-CHILD3: ExperimentalHeaderFilterScope: false
+// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' -exclude-header-filter='from_command_line' -experimental-header-filter-scope=false %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
+// CHECK-COMMAND-LINE: ExperimentalHeaderFilterScope: false
 
 // 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
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index a9d140bc9318e..b31f57fed9eab 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -1,4 +1,5 @@
 // RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' -header-filter='' -experimental-header-filter-scope %s.nonexistent.cpp -- | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
@@ -6,6 +7,7 @@
 //
 // Now repeat the tests and ensure no other errors appear on stderr:
 // RUN: not clang-tidy -checks='-*,modernize-use-override' %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: not clang-tidy -checks='-*,modernize-use-override' -header-filter='' -experimental-header-filter-scope %s.nonexistent.cpp -- 2>&1 | FileCheck -check-prefix=CHECK1 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: not clang-tidy -checks='-*,clang-diagnostic-*,google-explicit-constructor' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK2 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: not clang-tidy -checks='-*,google-explicit-constructor,clang-diagnostic-literal-conversion' %s -- -fan-unknown-option 2>&1 | FileCheck -check-prefix=CHECK3 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE 2>&1 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/dump-config-filtering.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/dump-config-filtering.cpp
index f22ec7edb1775..5f88968a3d163 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/dump-config-filtering.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/dump-config-filtering.cpp
@@ -5,8 +5,10 @@
 // CHECK-NEXT:   misc-unused-parameters.IgnoreVirtual: 'false'
 // CHECK-NEXT:   misc-unused-parameters.StrictMode: 'false'
 // CHECK-NEXT: SystemHeaders:   false
+// CHECK-NEXT: ExperimentalHeaderFilterScope: false
 
 // CHECK-DISABLED: CheckOptions:    {}
 // CHECK-DISABLED-NEXT: SystemHeaders:   false
+// CHECK-DISABLED-NEXT: ExperimentalHeaderFilterScope: false
 
 int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/experimental-header-filter-scope.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/experimental-header-filter-scope.cpp
new file mode 100644
index 0000000000000..efac1950302ee
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/experimental-header-filter-scope.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='does-not-match' %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-DEFAULT
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='does-not-match' -experimental-header-filter-scope %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-CLI --allow-empty
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='.*' -exclude-header-filter='confusable_header\.h' %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-EXCLUDE
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='.*' -exclude-header-filter='confusable_header\.h' -config='{ExperimentalHeaderFilterScope: true}' %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-CONFIG --allow-empty
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='does-not-match' -line-filter='[{"name":"experimental-header-filter-scope.cpp","lines":[[1,20]]}]' %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-LINE-FILTER
+// RUN: clang-tidy -checks='-*,misc-confusable-identifiers' -header-filter='does-not-match' -line-filter='[{"name":"experimental-header-filter-scope.cpp","lines":[[1,20]]}]' -experimental-header-filter-scope %s -- -I %S/Inputs/experimental-header-filter-scope 2>&1 | FileCheck %s --check-prefix=CHECK-LINE-FILTER-SCOPED --allow-empty
+
+#include "confusable_header.h"
+
+int lO = 1;
+// CHECK-DEFAULT: :[[@LINE-1]]:5: warning: 'lO' is confusable with 'l0' [misc-confusable-identifiers]
+// CHECK-CLI-NOT: warning:
+// CHECK-EXCLUDE: :[[@LINE-3]]:5: warning: 'lO' is confusable with 'l0' [misc-confusable-identifiers]
+// CHECK-CONFIG-NOT: warning:
+// CHECK-LINE-FILTER: :[[@LINE-5]]:5: warning: 'lO' is confusable with 'l0' [misc-confusable-identifiers]
+// CHECK-LINE-FILTER-SCOPED-NOT: warning:
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
index 6337686c58518..31b71a331a7ff 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/run-clang-tidy.cpp
@@ -14,6 +14,21 @@
 // RUN: not %run_clang_tidy -j 1 "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-J1
 // CHECK-J1: Running clang-tidy in 1 threads for
 
+// RUN: rm -rf %t-scope
+// RUN: mkdir -p %t-scope/include
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t-scope/test.cpp -I%/t-scope/include\",\"file\":\"%/t-scope/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t-scope/compile_commands.json
+// RUN: echo "Checks: '-*,misc-confusable-identifiers'" > %t-scope/.clang-tidy
+// RUN: echo "WarningsAsErrors: '*'" >> %t-scope/.clang-tidy
+// RUN: echo "int l0 = 0;" > %t-scope/include/confusable_header.h
+// RUN: echo '#include "confusable_header.h"' > %t-scope/test.cpp
+// RUN: echo 'int lO = 1;' >> %t-scope/test.cpp
+// RUN: cd "%t-scope"
+// RUN: not %run_clang_tidy -j 1 -header-filter=does-not-match "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-SCOPE-OFF
+// RUN: %run_clang_tidy -j 1 -header-filter=does-not-match -experimental-header-filter-scope=true "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-SCOPE-ON
+// CHECK-SCOPE-OFF: 'lO' is confusable with 'l0'
+// CHECK-SCOPE-ON: Running clang-tidy in 1 threads for 1 files out of 1 in compilation database
+// CHECK-SCOPE-ON-NOT: 'lO' is confusable with 'l0'
+
 int main()
 {
   int* x = new int();
diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
index b0ccbf22a4269..43ba90062be70 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -44,6 +44,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Timer.h"
+#include <functional>
 #include <optional>
 
 namespace clang {
@@ -145,6 +146,13 @@ class MatchFinder {
     /// Avoids matching declarations in system headers.
     bool IgnoreSystemHeaders{false};
 
+    /// Skips matching and traversal for declarations based on location.
+    ///
+    /// When set and the callback returns true, the declaration subtree is
+    /// skipped entirely. The callback is consulted after system-header
+    /// filtering and only for declarations with a valid source location.
+    std::function<bool(SourceLocation)> ShouldSkipLocation;
+
     bool SkipDeclsInModules{false};
   };
 
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 004a02c279099..107347b459ec5 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1366,10 +1366,19 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
     return SM.isInSystemHeader(Loc);
   }
 
-  template <typename T> bool shouldSkipNode(T &Node) {
-    if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
+  bool shouldSkipNode(Decl &Node) {
+    if (shouldSkipSystemHeaders(Node))
       return true;
-    return false;
+
+    if (!Options.ShouldSkipLocation)
+      return false;
+
+    SourceLocation Loc = getNodeLocation(Node);
+    return Loc.isValid() && Options.ShouldSkipLocation(Loc);
+  }
+
+  template <typename T> bool shouldSkipNode(T &Node) {
+    return shouldSkipSystemHeaders(Node);
   }
 
   template <typename T> bool shouldSkipNode(T *Node) {
@@ -1380,6 +1389,12 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
 
   bool shouldSkipNode(NestedNameSpecifier &) { return false; }
 
+  template <typename T> bool shouldSkipSystemHeaders(T &Node) {
+    if (Options.IgnoreSystemHeaders && isInSystemHeader(getNodeLocation(Node)))
+      return true;
+    return false;
+  }
+
   /// Bucket to record map.
   ///
   /// Used to get the appropriate bucket for each matcher.
diff --git a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
index 3fa71804710ac..9e13302005572 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -345,6 +345,56 @@ TEST(IsInlineMatcher, IsInline) {
 // Windows.
 #ifndef _WIN32
 
+TEST(MatchFinder, HonorsShouldSkipLocation) {
+  FileContentMappings M;
+  M.emplace_back("/other.h", "class HeaderDecl {};");
+  auto AST = tooling::buildASTFromCodeWithArgs(
+      "#include \"other.h\"\n"
+      "class MainDecl {};\n",
+      {"-std=gnu++11", "-target", "i386-unknown-unknown", "-I/"},
+      "input.cc", "clang-tool", std::make_shared<PCHContainerOperations>(),
+      tooling::getClangStripDependencyFileAdjuster(), M);
+  ASSERT_TRUE(AST);
+
+  auto matchRecordDecls = [&](MatchFinder::MatchFinderOptions Options) {
+    struct RecordCallback : MatchFinder::MatchCallback {
+      explicit RecordCallback(std::vector<std::string> &Names) : Names(Names) {}
+
+      void run(const MatchFinder::MatchResult &Result) override {
+        const auto *Record = Result.Nodes.getNodeAs<CXXRecordDecl>("record");
+        ASSERT_NE(nullptr, Record);
+        Names.push_back(std::string(Record->getName()));
+      }
+
+      std::vector<std::string> &Names;
+    };
+
+    std::vector<std::string> Names;
+    RecordCallback Callback(Names);
+    MatchFinder Finder(std::move(Options));
+    Finder.addMatcher(cxxRecordDecl(isDefinition(), unless(isImplicit()))
+                          .bind("record"),
+                      &Callback);
+    Finder.matchAST(AST->getASTContext());
+    llvm::sort(Names);
+    return Names;
+  };
+
+  const auto AllMatches = matchRecordDecls({});
+  ASSERT_EQ(2u, AllMatches.size());
+  EXPECT_EQ("HeaderDecl", AllMatches[0]);
+  EXPECT_EQ("MainDecl", AllMatches[1]);
+
+  MatchFinder::MatchFinderOptions ScopedOptions;
+  SourceManager &SM = AST->getSourceManager();
+  ScopedOptions.ShouldSkipLocation = [&SM](SourceLocation Location) {
+    return !SM.isInMainFile(Location);
+  };
+  const auto ScopedMatches = matchRecordDecls(std::move(ScopedOptions));
+  ASSERT_EQ(1u, ScopedMatches.size());
+  EXPECT_EQ("MainDecl", ScopedMatches[0]);
+}
+
 TEST(Matcher, IsExpansionInMainFileMatcher) {
   EXPECT_TRUE(matches("class X {};",
                       recordDecl(hasName("X"), isExpansionInMainFile())));

>From 1c1f26c310f92526179556a3b0b1708d5e97d3aa Mon Sep 17 00:00:00 2001
From: Vladimir Makaev <vmakaev at gmail.com>
Date: Mon, 27 Apr 2026 13:49:57 +0000
Subject: [PATCH 2/2] [clang-tidy] Fix formatting

---
 clang-tools-extra/clang-tidy/ClangTidy.cpp             |  8 ++++----
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp         |  6 +++---
 clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp    |  6 ++----
 .../unittests/ASTMatchers/ASTMatchersInternalTest.cpp  | 10 +++++-----
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index 3292dc44b3539..e2a9d41600736 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -453,10 +453,10 @@ ClangTidyASTConsumerFactory::createASTConsumer(CompilerInstance &Compiler,
     auto LocationFilter = std::make_shared<HeaderFilterLocationFilter>(
         Context.getOptions().HeaderFilterRegex.value_or(""),
         Context.getOptions().ExcludeHeaderFilterRegex.value_or(""));
-    FinderOptions.ShouldSkipLocation =
-        [LocationFilter, SM](SourceLocation Location) {
-          return !LocationFilter->shouldInclude(Location, *SM);
-        };
+    FinderOptions.ShouldSkipLocation = [LocationFilter,
+                                        SM](SourceLocation Location) {
+      return !LocationFilter->shouldInclude(Location, *SM);
+    };
   }
 
   auto Finder =
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index 6b3569f7cad9e..d35cd954e1fd7 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -580,9 +580,9 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
       (Sources.isInSystemHeader(Location) || Sources.isInSystemMacro(Location)))
     return;
 
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-                               getHeaderFilterLocationFilter().shouldInclude(
-                                   Location, Sources);
+  LastErrorRelatesToUserCode =
+      LastErrorRelatesToUserCode ||
+      getHeaderFilterLocationFilter().shouldInclude(Location, Sources);
 
   // FIXME: We start with a conservative approach here, but the actual type of
   // location needed depends on the check (in particular, where this check wants
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 5ed56e30ccdfc..e5757528eef38 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -163,8 +163,7 @@ option in .clang-tidy file, if any.
                                                 cl::cat(ClangTidyCategory));
 
 static cl::opt<bool>
-    ExperimentalHeaderFilterScope("experimental-header-filter-scope",
-                                  desc(R"(
+    ExperimentalHeaderFilterScope("experimental-header-filter-scope", desc(R"(
 When enabled, clang-tidy experimentally skips
 AST matching for declarations in headers that
 do not match -header-filter or that match
@@ -177,8 +176,7 @@ This option overrides the
 'ExperimentalHeaderFilterScope' option in
 .clang-tidy file, if any.
 )"),
-                                  cl::init(false),
-                                  cl::cat(ClangTidyCategory));
+                                  cl::init(false), cl::cat(ClangTidyCategory));
 
 static cl::opt<bool> SystemHeaders("system-headers", desc(R"(
 Display the errors from system headers.
diff --git a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
index 9e13302005572..1fc184fd6de48 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -351,8 +351,8 @@ TEST(MatchFinder, HonorsShouldSkipLocation) {
   auto AST = tooling::buildASTFromCodeWithArgs(
       "#include \"other.h\"\n"
       "class MainDecl {};\n",
-      {"-std=gnu++11", "-target", "i386-unknown-unknown", "-I/"},
-      "input.cc", "clang-tool", std::make_shared<PCHContainerOperations>(),
+      {"-std=gnu++11", "-target", "i386-unknown-unknown", "-I/"}, "input.cc",
+      "clang-tool", std::make_shared<PCHContainerOperations>(),
       tooling::getClangStripDependencyFileAdjuster(), M);
   ASSERT_TRUE(AST);
 
@@ -372,9 +372,9 @@ TEST(MatchFinder, HonorsShouldSkipLocation) {
     std::vector<std::string> Names;
     RecordCallback Callback(Names);
     MatchFinder Finder(std::move(Options));
-    Finder.addMatcher(cxxRecordDecl(isDefinition(), unless(isImplicit()))
-                          .bind("record"),
-                      &Callback);
+    Finder.addMatcher(
+        cxxRecordDecl(isDefinition(), unless(isImplicit())).bind("record"),
+        &Callback);
     Finder.matchAST(AST->getASTContext());
     llvm::sort(Names);
     return Names;



More information about the cfe-commits mailing list