[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
https://github.com/unterumarmung edited https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
https://github.com/unterumarmung edited https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options
insertion/removal for all headers under the directory `foo`. Default is an
empty string, no headers will be ignored.
+.. option:: FragmentHeaders
+
+ A semicolon-separated list of regular expressions that match against
+ normalized resolved include paths (POSIX-style separators). Direct includes
+ of the main file that match are treated as fragments of the main file for
+ usage scanning. This is intended for non-self-contained generated
+ ``.inc``/``.def`` files or other include fragments. Only direct includes are
+ considered; includes inside fragments are not treated as fragments. Default
+ is ``""``.
+
+ Diagnostics remain anchored to the main file, but symbol uses inside
+ fragments can keep prerequisite includes in the main file from being
+ removed or marked missing. Note that include-cleaner does not support
+ ``// IWYU pragma: associated``.
+
+ Example configuration:
+
+ .. code-block:: yaml
+
+ CheckOptions:
+- key: misc-include-cleaner.FragmentHeaders
+ value: 'gen-out/;generated/;\\.(inc|def)$'
+
+.. option:: FragmentDependencyCommentFormat
+
+ A trailing comment format to add to includes that are kept only because they
+ are used from fragment headers matched by :option:`FragmentHeaders`. The
+ value should not include the leading ``//``. An empty string disables these
+ diagnostics and fix-its. Default is ``""``.
+
+ Use ``{0}`` to substitute the comma-separated direct fragment include
+ spellings that keep the include alive.
+
+ Example configuration:
+
+ .. code-block:: yaml
EugeneZelenko wrote:
Ditto.
https://github.com/llvm/llvm-project/pull/196767
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -403,6 +402,12 @@ Changes in existing checks - Fixed false positives when pointers were later passed or bound through ``const``-qualified pointer references. +- Improved :doc:`misc-include-cleaner + ` check by adding the + ``FragmentHeaders`` option for fragment-aware usage scanning and the + ``FragmentDependencyCommentFormat`` option for annotating includes kept only EugeneZelenko wrote: ```suggestion `FragmentHeaders` option for fragment-aware usage scanning and the `FragmentDependencyCommentFormat` option for annotating includes kept only ``` https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options
insertion/removal for all headers under the directory `foo`. Default is an
empty string, no headers will be ignored.
+.. option:: FragmentHeaders
+
+ A semicolon-separated list of regular expressions that match against
+ normalized resolved include paths (POSIX-style separators). Direct includes
+ of the main file that match are treated as fragments of the main file for
+ usage scanning. This is intended for non-self-contained generated
+ ``.inc``/``.def`` files or other include fragments. Only direct includes are
+ considered; includes inside fragments are not treated as fragments. Default
+ is ``""``.
+
+ Diagnostics remain anchored to the main file, but symbol uses inside
+ fragments can keep prerequisite includes in the main file from being
+ removed or marked missing. Note that include-cleaner does not support
+ ``// IWYU pragma: associated``.
+
+ Example configuration:
+
+ .. code-block:: yaml
+
+ CheckOptions:
+- key: misc-include-cleaner.FragmentHeaders
+ value: 'gen-out/;generated/;\\.(inc|def)$'
+
+.. option:: FragmentDependencyCommentFormat
+
+ A trailing comment format to add to includes that are kept only because they
+ are used from fragment headers matched by :option:`FragmentHeaders`. The
+ value should not include the leading ``//``. An empty string disables these
+ diagnostics and fix-its. Default is ``""``.
+
+ Use ``{0}`` to substitute the comma-separated direct fragment include
EugeneZelenko wrote:
```suggestion
Use `{0}` to substitute the comma-separated direct fragment include
```
https://github.com/llvm/llvm-project/pull/196767
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -393,7 +393,6 @@ Changes in existing checks - Added support for analyzing function parameters with the `AnalyzeParameters` option. - EugeneZelenko wrote: Unintended change? https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options insertion/removal for all headers under the directory `foo`. Default is an empty string, no headers will be ignored. +.. option:: FragmentHeaders + + A semicolon-separated list of regular expressions that match against + normalized resolved include paths (POSIX-style separators). Direct includes + of the main file that match are treated as fragments of the main file for + usage scanning. This is intended for non-self-contained generated + ``.inc``/``.def`` files or other include fragments. Only direct includes are EugeneZelenko wrote: ```suggestion `.inc`/`.def` files or other include fragments. Only direct includes are ``` https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options insertion/removal for all headers under the directory `foo`. Default is an empty string, no headers will be ignored. +.. option:: FragmentHeaders + + A semicolon-separated list of regular expressions that match against + normalized resolved include paths (POSIX-style separators). Direct includes + of the main file that match are treated as fragments of the main file for + usage scanning. This is intended for non-self-contained generated + ``.inc``/``.def`` files or other include fragments. Only direct includes are + considered; includes inside fragments are not treated as fragments. Default + is ``""``. EugeneZelenko wrote: ```suggestion is `""`. ``` https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options insertion/removal for all headers under the directory `foo`. Default is an empty string, no headers will be ignored. +.. option:: FragmentHeaders + + A semicolon-separated list of regular expressions that match against + normalized resolved include paths (POSIX-style separators). Direct includes + of the main file that match are treated as fragments of the main file for + usage scanning. This is intended for non-self-contained generated + ``.inc``/``.def`` files or other include fragments. Only direct includes are + considered; includes inside fragments are not treated as fragments. Default + is ``""``. + + Diagnostics remain anchored to the main file, but symbol uses inside + fragments can keep prerequisite includes in the main file from being + removed or marked missing. Note that include-cleaner does not support + ``// IWYU pragma: associated``. + + Example configuration: + + .. code-block:: yaml EugeneZelenko wrote: I don't think that options need specific YAML examples. https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
@@ -34,6 +35,50 @@ Options insertion/removal for all headers under the directory `foo`. Default is an empty string, no headers will be ignored. +.. option:: FragmentHeaders + + A semicolon-separated list of regular expressions that match against + normalized resolved include paths (POSIX-style separators). Direct includes + of the main file that match are treated as fragments of the main file for + usage scanning. This is intended for non-self-contained generated + ``.inc``/``.def`` files or other include fragments. Only direct includes are + considered; includes inside fragments are not treated as fragments. Default + is ``""``. + + Diagnostics remain anchored to the main file, but symbol uses inside + fragments can keep prerequisite includes in the main file from being + removed or marked missing. Note that include-cleaner does not support + ``// IWYU pragma: associated``. + + Example configuration: + + .. code-block:: yaml + + CheckOptions: +- key: misc-include-cleaner.FragmentHeaders + value: 'gen-out/;generated/;\\.(inc|def)$' + +.. option:: FragmentDependencyCommentFormat + + A trailing comment format to add to includes that are kept only because they + are used from fragment headers matched by :option:`FragmentHeaders`. The + value should not include the leading ``//``. An empty string disables these + diagnostics and fix-its. Default is ``""``. EugeneZelenko wrote: ```suggestion value should not include the leading `//`. An empty string disables these diagnostics and fix-its. Default is `""`. ``` https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
https://github.com/unterumarmung created
https://github.com/llvm/llvm-project/pull/196767
None
>From f87e11e18a5358928246dac0630f787b4bbda42e Mon Sep 17 00:00:00 2001
From: Daniil Dudkin
Date: Sun, 10 May 2026 01:32:01 +0300
Subject: [PATCH] [clang-tidy] add fragment support to `misc-include-cleaner`
---
.../clang-tidy/misc/IncludeCleanerCheck.cpp | 182 +-
.../clang-tidy/misc/IncludeCleanerCheck.h | 7 +-
clang-tools-extra/docs/ReleaseNotes.rst | 7 +-
.../checks/misc/include-cleaner.rst | 47 ++-
.../clang-tidy/IncludeCleanerTest.cpp | 323 ++
5 files changed, 478 insertions(+), 88 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 0097ea54ba548..28e51add92a38 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -38,6 +38,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
+#include
#include
#include
#include
@@ -46,18 +47,21 @@ using namespace clang::ast_matchers;
namespace clang::tidy::misc {
-namespace {
-struct MissingIncludeInfo {
- include_cleaner::SymbolReference SymRef;
- include_cleaner::Header Missing;
-};
-} // namespace
+static bool matchesAnyRegex(llvm::ArrayRef Regexes,
+llvm::StringRef Path) {
+ return llvm::any_of(Regexes,
+ [&](const llvm::Regex &R) { return R.match(Path); });
+}
IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IgnoreHeaders(
utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
+ FragmentHeaderPatterns(
+ utils::options::parseStringList(Options.get("FragmentHeaders", ""))),
+ FragmentDependencyCommentFormat(
+ Options.get("FragmentDependencyCommentFormat", "")),
DeduplicateFindings(Options.get("DeduplicateFindings", true)),
UnusedIncludes(Options.get("UnusedIncludes", true)),
MissingIncludes(Options.get("MissingIncludes", true)) {
@@ -69,6 +73,16 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
HeaderSuffix += '$';
IgnoreHeadersRegex.emplace_back(HeaderSuffix);
}
+ for (const StringRef Pattern : FragmentHeaderPatterns) {
+llvm::Regex CompiledRegex(Pattern);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+ configurationDiag("Invalid fragment headers regular expression '%0': %1")
+ << Pattern << RegexError;
+ continue;
+}
+FragmentHeaderRegexes.push_back(std::move(CompiledRegex));
+ }
if (UnusedIncludes == false && MissingIncludes == false)
this->configurationDiag("The check 'misc-include-cleaner' will not "
@@ -79,6 +93,10 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreHeaders",
utils::options::serializeStringList(IgnoreHeaders));
+ Options.store(Opts, "FragmentHeaders",
+utils::options::serializeStringList(FragmentHeaderPatterns));
+ Options.store(Opts, "FragmentDependencyCommentFormat",
+FragmentDependencyCommentFormat);
Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
Options.store(Opts, "UnusedIncludes", UnusedIncludes);
Options.store(Opts, "MissingIncludes", MissingIncludes);
@@ -121,84 +139,23 @@ bool IncludeCleanerCheck::shouldIgnore(const
include_cleaner::Header &H) {
void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager *SM = Result.SourceManager;
const FileEntry *MainFile = SM->getFileEntryForID(SM->getMainFileID());
- llvm::DenseSet Used;
- std::vector Missing;
- SmallVector MainFileDecls;
+ llvm::SmallVector RootDecls;
for (Decl *D : Result.Nodes.getNodeAs("top")->decls()) {
-if (!SM->isWrittenInMainFile(SM->getExpansionLoc(D->getLocation(
- continue;
// FIXME: Filter out implicit template specializations.
-MainFileDecls.push_back(D);
+RootDecls.push_back(D);
}
- llvm::DenseSet SeenSymbols;
- OptionalDirectoryEntryRef ResourceDir =
- PP->getHeaderSearchInfo().getModuleMap().getBuiltinDir();
- // FIXME: Find a way to have less code duplication between include-cleaner
- // analysis implementation and the below code.
- walkUsed(MainFileDecls, RecordedPreprocessor.MacroReferences, &RecordedPI,
- *PP,
- [&](const include_cleaner::SymbolReference &Ref,
- llvm::ArrayRef Providers) {
- // Process each symbol once to reduce noise in the findings.
- // Tidy checks are used in two different workflows:
- // - Ones that show all the findings for a given file.
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
llvmorg-github-actions[bot] wrote:
@llvm/pr-subscribers-clang-tools-extra
@llvm/pr-subscribers-clang-tidy
Author: Daniil Dudkin (unterumarmung)
Changes
---
Patch is 27.07 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/196767.diff
5 Files Affected:
- (modified) clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp (+97-85)
- (modified) clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h (+6-1)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6-1)
- (modified) clang-tools-extra/docs/clang-tidy/checks/misc/include-cleaner.rst
(+46-1)
- (modified) clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
(+323)
``diff
diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 0097ea54ba548..28e51add92a38 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -38,6 +38,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
+#include
#include
#include
#include
@@ -46,18 +47,21 @@ using namespace clang::ast_matchers;
namespace clang::tidy::misc {
-namespace {
-struct MissingIncludeInfo {
- include_cleaner::SymbolReference SymRef;
- include_cleaner::Header Missing;
-};
-} // namespace
+static bool matchesAnyRegex(llvm::ArrayRef Regexes,
+llvm::StringRef Path) {
+ return llvm::any_of(Regexes,
+ [&](const llvm::Regex &R) { return R.match(Path); });
+}
IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IgnoreHeaders(
utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
+ FragmentHeaderPatterns(
+ utils::options::parseStringList(Options.get("FragmentHeaders", ""))),
+ FragmentDependencyCommentFormat(
+ Options.get("FragmentDependencyCommentFormat", "")),
DeduplicateFindings(Options.get("DeduplicateFindings", true)),
UnusedIncludes(Options.get("UnusedIncludes", true)),
MissingIncludes(Options.get("MissingIncludes", true)) {
@@ -69,6 +73,16 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
HeaderSuffix += '$';
IgnoreHeadersRegex.emplace_back(HeaderSuffix);
}
+ for (const StringRef Pattern : FragmentHeaderPatterns) {
+llvm::Regex CompiledRegex(Pattern);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+ configurationDiag("Invalid fragment headers regular expression '%0': %1")
+ << Pattern << RegexError;
+ continue;
+}
+FragmentHeaderRegexes.push_back(std::move(CompiledRegex));
+ }
if (UnusedIncludes == false && MissingIncludes == false)
this->configurationDiag("The check 'misc-include-cleaner' will not "
@@ -79,6 +93,10 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IgnoreHeaders",
utils::options::serializeStringList(IgnoreHeaders));
+ Options.store(Opts, "FragmentHeaders",
+utils::options::serializeStringList(FragmentHeaderPatterns));
+ Options.store(Opts, "FragmentDependencyCommentFormat",
+FragmentDependencyCommentFormat);
Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
Options.store(Opts, "UnusedIncludes", UnusedIncludes);
Options.store(Opts, "MissingIncludes", MissingIncludes);
@@ -121,84 +139,23 @@ bool IncludeCleanerCheck::shouldIgnore(const
include_cleaner::Header &H) {
void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager *SM = Result.SourceManager;
const FileEntry *MainFile = SM->getFileEntryForID(SM->getMainFileID());
- llvm::DenseSet Used;
- std::vector Missing;
- SmallVector MainFileDecls;
+ llvm::SmallVector RootDecls;
for (Decl *D : Result.Nodes.getNodeAs("top")->decls()) {
-if (!SM->isWrittenInMainFile(SM->getExpansionLoc(D->getLocation(
- continue;
// FIXME: Filter out implicit template specializations.
-MainFileDecls.push_back(D);
+RootDecls.push_back(D);
}
- llvm::DenseSet SeenSymbols;
- OptionalDirectoryEntryRef ResourceDir =
- PP->getHeaderSearchInfo().getModuleMap().getBuiltinDir();
- // FIXME: Find a way to have less code duplication between include-cleaner
- // analysis implementation and the below code.
- walkUsed(MainFileDecls, RecordedPreprocessor.MacroReferences, &RecordedPI,
- *PP,
- [&](const include_cleaner::SymbolReference &Ref,
- llvm::ArrayRef Providers) {
- // Process each symbol once to reduce noise in the findings.
- // Tidy checks are used in two different workflows:
- // - Ones
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
https://github.com/unterumarmung ready_for_review https://github.com/llvm/llvm-project/pull/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-tidy] add fragment support to `misc-include-cleaner` (PR #196767)
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/196767?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"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/196767?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * **#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"/> * **#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/196767 ___ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
