diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -223,7 +223,7 @@ // headers are likely to be the Standard Library headers. Until we have a // good support for umbrella headers and Standard Library headers, don't warn // about them. - if (Inc.Written.front() == '<') + if (Inc.Written.front() == '<' || Inc.BehindPragmaKeep) return false; // Headers without include guards have side effects and are not // self-contained, skip them. diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -9,6 +9,7 @@ #include "Annotations.h" #include "IncludeCleaner.h" #include "TestTU.h" +#include "llvm/Testing/Support/SupportHelpers.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -17,6 +18,7 @@ namespace { using ::testing::ElementsAre; +using ::testing::IsEmpty; using ::testing::UnorderedElementsAre; std::string guard(llvm::StringRef Code) { @@ -320,7 +322,7 @@ EXPECT_THAT(ReferencedHeaderNames, ElementsAre(testPath("macros.h"))); // Sanity check. - EXPECT_THAT(getUnused(AST, ReferencedHeaders), ::testing::IsEmpty()); + EXPECT_THAT(getUnused(AST, ReferencedHeaders), IsEmpty()); } TEST(IncludeCleaner, DistinctUnguardedInclusions) { @@ -397,6 +399,21 @@ UnorderedElementsAre(testPath("foo.h"))); } +TEST(IncludeCleaner, IWYUPragmas) { + TestTU TU; + TU.Code = R"cpp( + #include "behind_keep.h" // IWYU pragma: keep + )cpp"; + TU.AdditionalFiles["behind_keep.h"] = guard(""); + ParsedAST AST = TU.build(); + + auto ReferencedFiles = + findReferencedFiles(findReferencedLocations(AST), + AST.getIncludeStructure(), AST.getSourceManager()); + EXPECT_TRUE(ReferencedFiles.empty()); + EXPECT_THAT(AST.getDiagnostics(), llvm::ValueIs(IsEmpty())); +} + } // namespace } // namespace clangd } // namespace clang