[llvm-branch-commits] [clang-tools-extra] [include-cleaner] add fragment header analysis (PR #196764)
https://github.com/unterumarmung edited https://github.com/llvm/llvm-project/pull/196764 ___ 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] add fragment header analysis (PR #196764)
llvmorg-github-actions[bot] wrote:
@llvm/pr-subscribers-clang-tools-extra
Author: Daniil Dudkin (unterumarmung)
Changes
---
Patch is 30.10 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/196764.diff
4 Files Affected:
- (modified)
clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
(+29)
- (modified) clang-tools-extra/include-cleaner/lib/Analysis.cpp (+219-59)
- (modified) clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp (+1-1)
- (modified) clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
(+318-7)
``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 8e4912fa7bd84..1d28d87c025ca 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
@@ -62,24 +62,53 @@ void walkUsed(llvm::ArrayRef ASTRoots,
const PragmaIncludes *PI, const Preprocessor &PP,
UsedSymbolCB CB);
+/// A location kind where a symbol reference is observed.
+enum class SymbolReferenceOrigin {
+ MainFile,
+ Preamble,
+ Fragment,
+};
+
/// A missing include insertion candidate.
struct MissingInclude {
std::string Spelling;
Header Provider;
};
+/// A missing include finding with per-reference provenance.
+struct MissingIncludeRef {
+ SymbolReference Ref;
+ llvm::SmallVector Providers;
+ SymbolReferenceOrigin Origin = SymbolReferenceOrigin::MainFile;
+ /// Null if the fragment file has multiple direct include sites.
+ const Include *FragmentInclude = nullptr;
+};
+
+/// An include kept alive only by fragment usage.
+struct FragmentDependency {
+ const Include *Preserved = nullptr;
+ llvm::SmallVector Fragments;
+};
+
/// The result of include-cleaner analysis for one main file.
struct AnalysisResults {
std::vector Unused;
/// Deduplicated insertion plan, e.g. "" paired with the chosen
/// provider Header.
std::vector MissingIncludes;
+ /// Per-reference provenance for consumers that need richer diagnostics.
+ std::vector MissingRefs;
+ /// Include-preservation provenance for fragment-only uses.
+ std::vector FragmentDependencies;
};
/// Analysis configuration shared by include-cleaner consumers.
struct AnalysisOptions {
/// No analysis will be performed for headers that satisfy the predicate.
std::function HeaderFilter;
+ /// A predicate matched against normalized resolved paths, and normalized
+ /// spelled paths as a fallback, to identify direct include fragments.
+ std::function FragmentHeaderFilter;
};
/// Determine which headers should be inserted or removed from the main file.
diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
index cd0b3396bf418..321b67a5787d3 100644
--- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -8,6 +8,7 @@
#include "clang-include-cleaner/Analysis.h"
#include "AnalysisInternal.h"
+#include "TypesInternal.h"
#include "clang-include-cleaner/IncludeSpeller.h"
#include "clang-include-cleaner/Record.h"
#include "clang-include-cleaner/Types.h"
@@ -22,9 +23,11 @@
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -32,13 +35,91 @@
#include "llvm/Support/ErrorHandling.h"
#include
#include
+#include
#include
namespace clang::include_cleaner {
namespace {
+
+struct ClassifiedReference {
+ SymbolReferenceOrigin Origin;
+ // Null if the fragment file has multiple direct include sites.
+ const Include *FragmentInclude = nullptr;
+};
+
+class FragmentTracker {
+public:
+ FragmentTracker(const Includes &Inc, const SourceManager &SM,
+ const std::function &HeaderFilter)
+ : SM(SM) {
+if (!HeaderFilter)
+ return;
+
+for (const Include &I : Inc.all()) {
+ if (!I.Resolved ||
+ locateInMainFile(I.HashLocation, SM) != MainFileLocation::MainFile) {
+continue;
+ }
+
+ // Match the canonical path first, but fall back to the spelled include
+ // so generated paths can still be configured even when resolution loses
+ // that spelling detail.
+ const llvm::SmallString<128> ResolvedPath =
+ normalizePath(I.Resolved->getName());
+ bool IsFragment = HeaderFilter(ResolvedPath);
+ if (!IsFragment) {
+const llvm::SmallString<128> SpelledPath = normalizePath(I.Spelled);
+if (!SpelledPath.empty()
[llvm-branch-commits] [clang-tools-extra] [include-cleaner] add fragment header analysis (PR #196764)
https://github.com/unterumarmung created
https://github.com/llvm/llvm-project/pull/196764
None
>From ecbd505fe73b43f3a74b89488cb9e4074caa6863 Mon Sep 17 00:00:00 2001
From: Daniil Dudkin
Date: Sun, 10 May 2026 01:03:47 +0300
Subject: [PATCH] [include-cleaner] add fragment header analysis
---
.../include/clang-include-cleaner/Analysis.h | 29 ++
.../include-cleaner/lib/Analysis.cpp | 278 +++
.../include-cleaner/tool/IncludeCleaner.cpp | 2 +-
.../unittests/AnalysisTest.cpp| 325 +-
4 files changed, 567 insertions(+), 67 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 8e4912fa7bd84..1d28d87c025ca 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
@@ -62,24 +62,53 @@ void walkUsed(llvm::ArrayRef ASTRoots,
const PragmaIncludes *PI, const Preprocessor &PP,
UsedSymbolCB CB);
+/// A location kind where a symbol reference is observed.
+enum class SymbolReferenceOrigin {
+ MainFile,
+ Preamble,
+ Fragment,
+};
+
/// A missing include insertion candidate.
struct MissingInclude {
std::string Spelling;
Header Provider;
};
+/// A missing include finding with per-reference provenance.
+struct MissingIncludeRef {
+ SymbolReference Ref;
+ llvm::SmallVector Providers;
+ SymbolReferenceOrigin Origin = SymbolReferenceOrigin::MainFile;
+ /// Null if the fragment file has multiple direct include sites.
+ const Include *FragmentInclude = nullptr;
+};
+
+/// An include kept alive only by fragment usage.
+struct FragmentDependency {
+ const Include *Preserved = nullptr;
+ llvm::SmallVector Fragments;
+};
+
/// The result of include-cleaner analysis for one main file.
struct AnalysisResults {
std::vector Unused;
/// Deduplicated insertion plan, e.g. "" paired with the chosen
/// provider Header.
std::vector MissingIncludes;
+ /// Per-reference provenance for consumers that need richer diagnostics.
+ std::vector MissingRefs;
+ /// Include-preservation provenance for fragment-only uses.
+ std::vector FragmentDependencies;
};
/// Analysis configuration shared by include-cleaner consumers.
struct AnalysisOptions {
/// No analysis will be performed for headers that satisfy the predicate.
std::function HeaderFilter;
+ /// A predicate matched against normalized resolved paths, and normalized
+ /// spelled paths as a fallback, to identify direct include fragments.
+ std::function FragmentHeaderFilter;
};
/// Determine which headers should be inserted or removed from the main file.
diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
index cd0b3396bf418..321b67a5787d3 100644
--- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -8,6 +8,7 @@
#include "clang-include-cleaner/Analysis.h"
#include "AnalysisInternal.h"
+#include "TypesInternal.h"
#include "clang-include-cleaner/IncludeSpeller.h"
#include "clang-include-cleaner/Record.h"
#include "clang-include-cleaner/Types.h"
@@ -22,9 +23,11 @@
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -32,13 +35,91 @@
#include "llvm/Support/ErrorHandling.h"
#include
#include
+#include
#include
namespace clang::include_cleaner {
namespace {
+
+struct ClassifiedReference {
+ SymbolReferenceOrigin Origin;
+ // Null if the fragment file has multiple direct include sites.
+ const Include *FragmentInclude = nullptr;
+};
+
+class FragmentTracker {
+public:
+ FragmentTracker(const Includes &Inc, const SourceManager &SM,
+ const std::function &HeaderFilter)
+ : SM(SM) {
+if (!HeaderFilter)
+ return;
+
+for (const Include &I : Inc.all()) {
+ if (!I.Resolved ||
+ locateInMainFile(I.HashLocation, SM) != MainFileLocation::MainFile) {
+continue;
+ }
+
+ // Match the canonical path first, but fall back to the spelled include
+ // so generated paths can still be configured even when resolution loses
+ // that spelling detail.
+ const llvm::SmallString<128> ResolvedPath =
+ normalizePath(I.Resolved->getName());
+ bool IsFragment = HeaderFilter(ResolvedPath);
+ if (!IsFragment) {
+const llvm::SmallString<128> SpelledPath = normalizePath(I.Spelled);
+if (!SpelledPath.empty())
+ IsFragment
[llvm-branch-commits] [clang-tools-extra] [include-cleaner] add fragment header analysis (PR #196764)
https://github.com/unterumarmung ready_for_review https://github.com/llvm/llvm-project/pull/196764 ___ 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] add fragment header analysis (PR #196764)
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/196764?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"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/196764?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#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"/> * **#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/196764 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
