[clang-tools-extra] [include-cleaner] Record #import directives (PR #212596)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 28 12:49:16 PDT 2026
https://github.com/dmaclach created https://github.com/llvm/llvm-project/pull/212596
Detect #import directives during preprocessing and record them with the IncludeDirective::Import type. This ensures Objective-C imports are correctly classified and tracked by the tool.
Also clean up some includes.
>From 0194946bca6182814387c25821e713d4cd0b23cb Mon Sep 17 00:00:00 2001
From: Dave MacLachlan <dmaclach at gmail.com>
Date: Tue, 28 Jul 2026 12:47:18 -0700
Subject: [PATCH] [include-cleaner] Record #import directives
Detect #import directives during preprocessing and record them with the IncludeDirective::Import type. This ensures Objective-C imports are correctly classified and tracked by the tool.
Also clean up some includes.
---
.../include-cleaner/lib/Record.cpp | 16 ++++---
.../include-cleaner/unittests/RecordTest.cpp | 43 ++++++++++++++++++-
2 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp
index 0284d6842e2d2..b549665629fbc 100644
--- a/clang-tools-extra/include-cleaner/lib/Record.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Record.cpp
@@ -18,30 +18,27 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/Inclusions/HeaderAnalysis.h"
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem/UniqueID.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
-#include <algorithm>
#include <assert.h>
#include <memory>
#include <optional>
-#include <set>
#include <utility>
#include <vector>
@@ -79,6 +76,15 @@ class PPRecorder : public PPCallbacks {
I.Line = SM.getSpellingLineNumber(Hash);
I.Spelled = SpelledFilename;
I.Angled = IsAngled;
+ llvm::StringRef DirectiveName;
+ if (IncludeTok.is(tok::raw_identifier)) {
+ DirectiveName = IncludeTok.getRawIdentifier();
+ } else if (IncludeTok.getIdentifierInfo()) {
+ DirectiveName = IncludeTok.getIdentifierInfo()->getName();
+ }
+ if (DirectiveName == "import") {
+ I.Directive = clang::tooling::IncludeDirective::Import;
+ }
Recorded.Includes.add(I);
}
diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
index cbf7bae23b365..efd692a2ed35b 100644
--- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
@@ -20,6 +20,7 @@
#include "clang/Serialization/PCHContainerOperations.h"
#include "clang/Testing/CommandLineArgs.h"
#include "clang/Testing/TestAST.h"
+#include "clang/Tooling/Inclusions/HeaderIncludes.h"
#include "clang/Tooling/Inclusions/StandardLibrary.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -135,7 +136,7 @@ TEST_F(RecordASTTest, ImplicitTemplates) {
}
)cpp";
Inputs.Code = R"cpp(
- #include "dispatch.h"
+ #include "dispatch.h"
struct MyGetter {
template <class T> static int get() { return T::value; }
};
@@ -204,6 +205,46 @@ TEST_F(RecordPPTest, CapturesIncludes) {
EXPECT_TRUE(M.Angled);
}
+TEST_F(RecordPPTest, CapturesImports) {
+ llvm::Annotations MainFile(R"objc(
+ $H^#import "./header.h"
+ $M^#import <missing.h>
+ )objc");
+ Inputs.Code = MainFile.code();
+ Inputs.ExtraFiles["header.h"] = "";
+ Inputs.ErrorOK = true; // missing header
+ Inputs.ExtraArgs.push_back("-x");
+ Inputs.ExtraArgs.push_back("objective-c");
+ auto AST = build();
+
+ auto Includes = Recorded.Includes.all();
+ ASSERT_EQ(Includes.size(), 2u);
+ EXPECT_THAT(Includes[0], spelled("./header.h"));
+ EXPECT_EQ(Includes[0].Directive, clang::tooling::IncludeDirective::Import);
+ EXPECT_THAT(Includes[1], spelled("missing.h"));
+ EXPECT_EQ(Includes[1].Directive, clang::tooling::IncludeDirective::Import);
+}
+
+TEST_F(RecordPPTest, CapturesMixedDirectives) {
+ llvm::Annotations MainFile(R"objc(
+ $H^#import "./header.h"
+ $I^#include "./header2.h"
+ )objc");
+ Inputs.Code = MainFile.code();
+ Inputs.ExtraFiles["header.h"] = "";
+ Inputs.ExtraFiles["header2.h"] = "";
+ Inputs.ExtraArgs.push_back("-x");
+ Inputs.ExtraArgs.push_back("objective-c");
+ auto AST = build();
+
+ auto Includes = Recorded.Includes.all();
+ ASSERT_EQ(Includes.size(), 2u);
+ EXPECT_THAT(Includes[0], spelled("./header.h"));
+ EXPECT_EQ(Includes[0].Directive, clang::tooling::IncludeDirective::Import);
+ EXPECT_THAT(Includes[1], spelled("./header2.h"));
+ EXPECT_EQ(Includes[1].Directive, clang::tooling::IncludeDirective::Include);
+}
+
TEST_F(RecordPPTest, CapturesMacroRefs) {
llvm::Annotations Header(R"cpp(
#define $def^X 1
More information about the cfe-commits
mailing list