[clang-tools-extra] de81dc8 - [include-cleaner] Filter template instantiations from AST roots.

Viktoriia Bakalova via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 9 04:58:36 PST 2023


Author: Viktoriia Bakalova
Date: 2023-01-09T12:54:20Z
New Revision: de81dc8fdf2764fb14a3c70e5e845cfd7f3b366c

URL: https://github.com/llvm/llvm-project/commit/de81dc8fdf2764fb14a3c70e5e845cfd7f3b366c
DIFF: https://github.com/llvm/llvm-project/commit/de81dc8fdf2764fb14a3c70e5e845cfd7f3b366c.diff

LOG: [include-cleaner] Filter template instantiations from AST roots.

Fix: https://github.com/llvm/llvm-project/issues/59825
Differential Revision: https://reviews.llvm.org/D141271

Added: 
    

Modified: 
    clang-tools-extra/include-cleaner/lib/Record.cpp
    clang-tools-extra/include-cleaner/unittests/RecordTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp
index ab5a2415cbf9..4df65959011c 100644
--- a/clang-tools-extra/include-cleaner/lib/Record.cpp
+++ b/clang-tools-extra/include-cleaner/lib/Record.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclGroup.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/PPCallbacks.h"
@@ -352,6 +353,14 @@ bool PragmaIncludes::isPrivate(const FileEntry *FE) const {
   return IWYUPublic.find(FE->getUniqueID()) != IWYUPublic.end();
 }
 
+namespace {
+template <typename T> bool isImplicitTemplateSpecialization(const Decl *D) {
+  if (const auto *TD = dyn_cast<T>(D))
+    return TD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
+  return false;
+}
+} // namespace
+
 std::unique_ptr<ASTConsumer> RecordedAST::record() {
   class Recorder : public ASTConsumer {
     RecordedAST *Out;
@@ -364,7 +373,11 @@ std::unique_ptr<ASTConsumer> RecordedAST::record() {
       for (Decl *D : DG) {
         if (!SM.isWrittenInMainFile(SM.getExpansionLoc(D->getLocation())))
           continue;
-        // FIXME: Filter out certain Obj-C and template-related decls.
+        if (isImplicitTemplateSpecialization<FunctionDecl>(D) ||
+            isImplicitTemplateSpecialization<CXXRecordDecl>(D) ||
+            isImplicitTemplateSpecialization<VarDecl>(D))
+          continue;
+        // FIXME: Filter out certain Obj-C as well.
         Out->Roots.push_back(D);
       }
       return ASTConsumer::HandleTopLevelDecl(DG);

diff  --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
index 919d6bdc0d68..cc99146c4419 100644
--- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
@@ -101,6 +101,29 @@ TEST_F(RecordASTTest, Macros) {
   EXPECT_THAT(Recorded.Roots, testing::ElementsAre(named("x")));
 }
 
+// Decl from template instantiation is filtered out from roots.
+TEST_F(RecordASTTest, ImplicitTemplates) {
+  Inputs.ExtraFiles["dispatch.h"] = R"cpp(
+  struct A {
+    static constexpr int value = 1;
+  };
+  template <class Getter>
+  int dispatch() {
+    return Getter::template get<A>();
+  }
+  )cpp";
+  Inputs.Code = R"cpp(
+  #include "dispatch.h"  
+  struct MyGetter {
+    template <class T> static int get() { return T::value; }
+  };
+  int v = dispatch<MyGetter>();
+  )cpp";
+  auto AST = build();
+  EXPECT_THAT(Recorded.Roots,
+              testing::ElementsAre(named("MyGetter"), named("v")));
+}
+
 class RecordPPTest : public ::testing::Test {
 protected:
   TestInputs Inputs;


        


More information about the cfe-commits mailing list