[llvm-branch-commits] [clang-tools-extra] [include-cleaner][NFC] factor analysis bookkeeping (PR #196763)

2026-06-06 Thread Daniil Dudkin via llvm-branch-commits

https://github.com/unterumarmung edited 
https://github.com/llvm/llvm-project/pull/196763
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] [include-cleaner][NFC] factor analysis bookkeeping (PR #196763)

2026-05-10 Thread Daniil Dudkin via llvm-branch-commits

https://github.com/unterumarmung created 
https://github.com/llvm/llvm-project/pull/196763

None

>From 6e146f087045416aad4ead1c35a38db9392f469d Mon Sep 17 00:00:00 2001
From: Daniil Dudkin 
Date: Sun, 10 May 2026 01:01:20 +0300
Subject: [PATCH] [include-cleaner][NFC] factor analysis bookkeeping

---
 .../include/clang-include-cleaner/Analysis.h  |  35 +++--
 .../include-cleaner/lib/Analysis.cpp  | 130 +-
 .../include-cleaner/tool/IncludeCleaner.cpp   |  32 +++--
 .../unittests/AnalysisTest.cpp|  50 ---
 4 files changed, 164 insertions(+), 83 deletions(-)

diff --git 
a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h 
b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
index c3241763237d1..8e4912fa7bd84 100644
--- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
+++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
@@ -20,8 +20,9 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include 
 #include 
-#include 
+#include 
 
 namespace clang {
 class SourceLocation;
@@ -61,23 +62,33 @@ void walkUsed(llvm::ArrayRef ASTRoots,
   const PragmaIncludes *PI, const Preprocessor &PP,
   UsedSymbolCB CB);
 
+/// A missing include insertion candidate.
+struct MissingInclude {
+  std::string Spelling;
+  Header Provider;
+};
+
+/// The result of include-cleaner analysis for one main file.
 struct AnalysisResults {
   std::vector Unused;
-  // Spellings, like "" paired with the Header that generated it.
-  std::vector> Missing;
+  /// Deduplicated insertion plan, e.g. "" paired with the chosen
+  /// provider Header.
+  std::vector MissingIncludes;
+};
+
+/// Analysis configuration shared by include-cleaner consumers.
+struct AnalysisOptions {
+  /// No analysis will be performed for headers that satisfy the predicate.
+  std::function HeaderFilter;
 };
 
 /// Determine which headers should be inserted or removed from the main file.
 /// This exposes conclusions but not reasons: use lower-level walkUsed for 
that.
-///
-/// The HeaderFilter is a predicate that receives absolute path or spelling
-/// without quotes/brackets, when a phyiscal file doesn't exist.
-/// No analysis will be performed for headers that satisfy the predicate.
-AnalysisResults
-analyze(llvm::ArrayRef ASTRoots,
-llvm::ArrayRef MacroRefs, const Includes &I,
-const PragmaIncludes *PI, const Preprocessor &PP,
-llvm::function_ref HeaderFilter = nullptr);
+AnalysisResults analyze(llvm::ArrayRef ASTRoots,
+llvm::ArrayRef MacroRefs,
+const Includes &I, const PragmaIncludes *PI,
+const Preprocessor &PP,
+const AnalysisOptions &Options = {});
 
 /// Removes unused includes and inserts missing ones in the main file.
 /// Returns the modified main-file code.
diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp 
b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
index e48a380211af0..cd0b3396bf418 100644
--- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -88,18 +88,90 @@ void walkUsed(llvm::ArrayRef ASTRoots,
   }
 }
 
-AnalysisResults
-analyze(llvm::ArrayRef ASTRoots,
-llvm::ArrayRef MacroRefs, const Includes &Inc,
-const PragmaIncludes *PI, const Preprocessor &PP,
-llvm::function_ref HeaderFilter) {
-  auto &SM = PP.getSourceManager();
-  const auto MainFile = *SM.getFileEntryRefForID(SM.getMainFileID());
+namespace {
+
+bool isFilteredInclude(const Include &I,
+   llvm::function_ref HeaderFilter,
+   const Preprocessor &PP) {
+  if (I.Angled) {
+auto Lang = PP.getLangOpts().CPlusPlus ? tooling::stdlib::Lang::CXX
+   : tooling::stdlib::Lang::C;
+if (auto StdHeader = tooling::stdlib::Header::named(I.quote(), Lang);
+StdHeader && HeaderFilter(*StdHeader))
+  return true;
+  }
+  return I.Resolved && HeaderFilter(*I.Resolved);
+}
+
+bool shouldSuppressIncludeDiagnostic(
+const Include &I, FileEntryRef MainFile,
+llvm::function_ref HeaderFilter,
+const PragmaIncludes *PI, const Preprocessor &PP,
+OptionalDirectoryEntryRef ResourceDir) {
+  if (!I.Resolved || I.Resolved->getDir() == ResourceDir ||
+  isFilteredInclude(I, HeaderFilter, PP))
+return true;
+  if (!PI)
+return false;
+  if (PI->shouldKeep(*I.Resolved))
+return true;
+  // Check if main file is the public interface for a private header. If so
+  // we shouldn't diagnose it as unused.
+  if (auto PHeader = PI->getPublic(*I.Resolved); !PHeader.empty()) {
+PHeader = PHeader.trim("<>\"");
+// Since most private -> public mappings happen in a verbatim way, we
+// check textually here. This might go wrong in pre

[llvm-branch-commits] [clang-tools-extra] [include-cleaner][NFC] factor analysis bookkeeping (PR #196763)

2026-05-10 Thread Daniil Dudkin via llvm-branch-commits

https://github.com/unterumarmung ready_for_review 
https://github.com/llvm/llvm-project/pull/196763
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] [include-cleaner][NFC] factor analysis bookkeeping (PR #196763)

2026-05-10 Thread via llvm-branch-commits

llvmorg-github-actions[bot] wrote:




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

Author: Daniil Dudkin (unterumarmung)


Changes



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


4 Files Affected:

- (modified) 
clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h 
(+23-12) 
- (modified) clang-tools-extra/include-cleaner/lib/Analysis.cpp (+93-37) 
- (modified) clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp (+17-15) 
- (modified) clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp 
(+31-19) 


``diff
diff --git 
a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h 
b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
index c3241763237d1..8e4912fa7bd84 100644
--- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
+++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
@@ -20,8 +20,9 @@
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include 
 #include 
-#include 
+#include 
 
 namespace clang {
 class SourceLocation;
@@ -61,23 +62,33 @@ void walkUsed(llvm::ArrayRef ASTRoots,
   const PragmaIncludes *PI, const Preprocessor &PP,
   UsedSymbolCB CB);
 
+/// A missing include insertion candidate.
+struct MissingInclude {
+  std::string Spelling;
+  Header Provider;
+};
+
+/// The result of include-cleaner analysis for one main file.
 struct AnalysisResults {
   std::vector Unused;
-  // Spellings, like "" paired with the Header that generated it.
-  std::vector> Missing;
+  /// Deduplicated insertion plan, e.g. "" paired with the chosen
+  /// provider Header.
+  std::vector MissingIncludes;
+};
+
+/// Analysis configuration shared by include-cleaner consumers.
+struct AnalysisOptions {
+  /// No analysis will be performed for headers that satisfy the predicate.
+  std::function HeaderFilter;
 };
 
 /// Determine which headers should be inserted or removed from the main file.
 /// This exposes conclusions but not reasons: use lower-level walkUsed for 
that.
-///
-/// The HeaderFilter is a predicate that receives absolute path or spelling
-/// without quotes/brackets, when a phyiscal file doesn't exist.
-/// No analysis will be performed for headers that satisfy the predicate.
-AnalysisResults
-analyze(llvm::ArrayRef ASTRoots,
-llvm::ArrayRef MacroRefs, const Includes &I,
-const PragmaIncludes *PI, const Preprocessor &PP,
-llvm::function_ref HeaderFilter = nullptr);
+AnalysisResults analyze(llvm::ArrayRef ASTRoots,
+llvm::ArrayRef MacroRefs,
+const Includes &I, const PragmaIncludes *PI,
+const Preprocessor &PP,
+const AnalysisOptions &Options = {});
 
 /// Removes unused includes and inserts missing ones in the main file.
 /// Returns the modified main-file code.
diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp 
b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
index e48a380211af0..cd0b3396bf418 100644
--- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -88,18 +88,90 @@ void walkUsed(llvm::ArrayRef ASTRoots,
   }
 }
 
-AnalysisResults
-analyze(llvm::ArrayRef ASTRoots,
-llvm::ArrayRef MacroRefs, const Includes &Inc,
-const PragmaIncludes *PI, const Preprocessor &PP,
-llvm::function_ref HeaderFilter) {
-  auto &SM = PP.getSourceManager();
-  const auto MainFile = *SM.getFileEntryRefForID(SM.getMainFileID());
+namespace {
+
+bool isFilteredInclude(const Include &I,
+   llvm::function_ref HeaderFilter,
+   const Preprocessor &PP) {
+  if (I.Angled) {
+auto Lang = PP.getLangOpts().CPlusPlus ? tooling::stdlib::Lang::CXX
+   : tooling::stdlib::Lang::C;
+if (auto StdHeader = tooling::stdlib::Header::named(I.quote(), Lang);
+StdHeader && HeaderFilter(*StdHeader))
+  return true;
+  }
+  return I.Resolved && HeaderFilter(*I.Resolved);
+}
+
+bool shouldSuppressIncludeDiagnostic(
+const Include &I, FileEntryRef MainFile,
+llvm::function_ref HeaderFilter,
+const PragmaIncludes *PI, const Preprocessor &PP,
+OptionalDirectoryEntryRef ResourceDir) {
+  if (!I.Resolved || I.Resolved->getDir() == ResourceDir ||
+  isFilteredInclude(I, HeaderFilter, PP))
+return true;
+  if (!PI)
+return false;
+  if (PI->shouldKeep(*I.Resolved))
+return true;
+  // Check if main file is the public interface for a private header. If so
+  // we shouldn't diagnose it as unused.
+  if (auto PHeader = PI->getPublic(*I.Resolved); !PHeader.empty()) {
+PHeader = PHeader.trim("<>\"");
+// Since most private -> public mappings happen in a verbatim way, we
+// check textually here. This might go wrong in presence of symlinks or
+// h

[llvm-branch-commits] [clang-tools-extra] [include-cleaner][NFC] factor analysis bookkeeping (PR #196763)

2026-05-10 Thread Daniil Dudkin via llvm-branch-commits

unterumarmung wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/196763?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#196767** https://app.graphite.com/github/pr/llvm/llvm-project/196767?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#196766** https://app.graphite.com/github/pr/llvm/llvm-project/196766?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#196765** https://app.graphite.com/github/pr/llvm/llvm-project/196765?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#196764** https://app.graphite.com/github/pr/llvm/llvm-project/196764?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#196763** https://app.graphite.com/github/pr/llvm/llvm-project/196763?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/196763?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#196762** https://app.graphite.com/github/pr/llvm/llvm-project/196762?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#196761** https://app.graphite.com/github/pr/llvm/llvm-project/196761?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/196763
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits