[clang-tools-extra] b0831c3 - [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (#65431)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 6 02:37:19 PDT 2023
Author: Congcong Cai
Date: 2023-09-06T17:37:14+08:00
New Revision: b0831c3996752038c375796d8ebb4f471f1ea251
URL: https://github.com/llvm/llvm-project/commit/b0831c3996752038c375796d8ebb4f471f1ea251
DIFF: https://github.com/llvm/llvm-project/commit/b0831c3996752038c375796d8ebb4f471f1ea251.diff
LOG: [clang-tidy][misc-include-cleaner]Avoid to insert same include header multiple times (#65431)
`HeaderIncludes` won't update `ExistingIncludes` during inserting.
We need to manage it in tidy check.
Fixed: #65285
Added:
Modified:
clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 2658c4b38702ca8..8d5f400acfef8bc 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -33,6 +33,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
@@ -199,6 +200,8 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
FileStyle->IncludeStyle);
+ // Deduplicate insertions when running in bulk fix mode.
+ llvm::StringSet<> InsertedHeaders{};
for (const auto &Inc : Missing) {
std::string Spelling = include_cleaner::spellHeader(
{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
@@ -209,14 +212,18 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) {
// main file.
if (auto Replacement =
HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
- Angled, tooling::IncludeDirective::Include))
- diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
- "no header providing \"%0\" is directly included")
- << Inc.SymRef.Target.name()
- << FixItHint::CreateInsertion(
- SM->getComposedLoc(SM->getMainFileID(),
- Replacement->getOffset()),
- Replacement->getReplacementText());
+ Angled, tooling::IncludeDirective::Include)) {
+ DiagnosticBuilder DB =
+ diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
+ "no header providing \"%0\" is directly included")
+ << Inc.SymRef.Target.name();
+ if (areDiagsSelfContained() ||
+ InsertedHeaders.insert(Replacement->getReplacementText()).second) {
+ DB << FixItHint::CreateInsertion(
+ SM->getComposedLoc(SM->getMainFileID(), Replacement->getOffset()),
+ Replacement->getReplacementText());
+ }
+ }
}
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5dfda9928aca20b..a2cde526a8c04d9 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -226,6 +226,10 @@ Changes in existing checks
<clang-tidy/checks/misc/include-cleaner>` check by adding option
`DeduplicateFindings` to output one finding per symbol occurrence.
+- Improved :doc:`misc-include-cleaner
+ <clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
+ same include header multiple times.
+
- Improved :doc:`misc-redundant-expression
<clang-tidy/checks/misc/redundant-expression>` check to ignore
false-positives in unevaluated context (e.g., ``decltype``).
diff --git a/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp b/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
index fe3e38958f8985a..f84133b01a3a49f 100644
--- a/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
+++ b/clang-tools-extra/unittests/clang-tidy/IncludeCleanerTest.cpp
@@ -184,6 +184,38 @@ int QuxResult = qux();
)"}}));
}
+
+TEST(IncludeCleanerCheckTest, MultipleTimeMissingInclude) {
+ const char *PreCode = R"(
+#include "bar.h"
+
+int BarResult = bar();
+int BazResult_0 = baz_0();
+int BazResult_1 = baz_1();
+)";
+ const char *PostCode = R"(
+#include "bar.h"
+#include "baz.h"
+
+int BarResult = bar();
+int BazResult_0 = baz_0();
+int BazResult_1 = baz_1();
+)";
+
+ std::vector<ClangTidyError> Errors;
+ EXPECT_EQ(PostCode,
+ runCheckOnCode<IncludeCleanerCheck>(
+ PreCode, &Errors, "file.cpp", std::nullopt, ClangTidyOptions(),
+ {{"bar.h", R"(#pragma once
+ #include "baz.h"
+ int bar();
+ )"},
+ {"baz.h", R"(#pragma once
+ int baz_0();
+ int baz_1();
+ )"}}));
+}
+
TEST(IncludeCleanerCheckTest, SystemMissingIncludes) {
const char *PreCode = R"(
#include <vector>
More information about the cfe-commits
mailing list