diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
--- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
+++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Record.h
@@ -73,6 +73,10 @@
/// Returns true if the given file is a self-contained file.
bool isSelfContained(const FileEntry *File) const;
+ /// Returns true if the given file is marked with the IWYU private pragma
+ /// without public mapping.
+ bool isPrivate(const FileEntry *File) const;
+
private:
class RecordPragma;
/// 1-based Line numbers for the #include directives of the main file that
@@ -88,6 +92,10 @@
llvm::DenseMap
IWYUPublic;
+ /// Contains all files marked with the IWYU private pragma that
+ /// do not have public header mapping
+ llvm::DenseSet IWYUPrivate;
+
/// A reverse map from the underlying header to its exporter headers.
//
// There's no way to get a FileEntry from a UniqueID, especially when it
diff --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp
--- a/clang-tools-extra/include-cleaner/lib/Record.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Record.cpp
@@ -263,6 +263,8 @@
assert(ExportStack.back().Block);
ExportStack.pop_back();
}
+ } else if (Pragma->startswith("private")) {
+ Out->IWYUPrivate.insert(SM.getFileEntryForID(CommentFID)->getUniqueID());
}
if (InMainFile) {
@@ -346,6 +348,10 @@
return !NonSelfContainedFiles.contains(FE->getUniqueID());
}
+bool PragmaIncludes::isPrivate(const FileEntry *FE) const {
+ return IWYUPrivate.contains(FE->getUniqueID());
+}
+
std::unique_ptr RecordedAST::record() {
class Recorder : public ASTConsumer {
RecordedAST *Out;
diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
--- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
@@ -368,11 +368,18 @@
Inputs.Code = R"cpp(
#include "public.h"
)cpp";
- Inputs.ExtraFiles["public.h"] = "#include \"private.h\"";
+ Inputs.ExtraFiles["public.h"] = R"cpp(
+ #include "private.h";
+ #include "private2.h";
+ )cpp";
Inputs.ExtraFiles["private.h"] = R"cpp(
// IWYU pragma: private, include "public2.h"
class Private {};
)cpp";
+ Inputs.ExtraFiles["private2.h"] = R"cpp(
+ // IWYU pragma: private
+ class Private {};
+ )cpp";
TestAST Processed = build();
auto PrivateFE = Processed.fileManager().getFile("private.h");
assert(PrivateFE);
@@ -380,6 +387,10 @@
auto PublicFE = Processed.fileManager().getFile("public.h");
assert(PublicFE);
EXPECT_EQ(PI.getPublic(PublicFE.get()), ""); // no mapping.
+
+ auto Private2FE = Processed.fileManager().getFile("private2.h");
+ assert(Private2FE);
+ EXPECT_TRUE(PI.isPrivate(Private2FE.get()));
}
TEST_F(PragmaIncludeTest, IWYUExport) {