VitaNuo created this revision. Herald added a subscriber: kadircet. Herald added a project: All. VitaNuo requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141271 Files: clang-tools-extra/include-cleaner/lib/Record.cpp clang-tools-extra/include-cleaner/unittests/RecordTest.cpp Index: clang-tools-extra/include-cleaner/unittests/RecordTest.cpp =================================================================== --- clang-tools-extra/include-cleaner/unittests/RecordTest.cpp +++ clang-tools-extra/include-cleaner/unittests/RecordTest.cpp @@ -101,6 +101,28 @@ EXPECT_THAT(Recorded.Roots, testing::ElementsAre(named("x"))); } +// Decl from template instantiation is filtered out from roots. +TEST_F(RecordASTTest, TemplateInstantiations) { + 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::Not(testing::ElementsAre(named("get")))); +} + class RecordPPTest : public ::testing::Test { protected: TestInputs Inputs; Index: clang-tools-extra/include-cleaner/lib/Record.cpp =================================================================== --- clang-tools-extra/include-cleaner/lib/Record.cpp +++ 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,15 @@ return IWYUPublic.find(FE->getUniqueID()) != IWYUPublic.end(); } +namespace { +template <typename T> +bool isImplicitTemplateSpecialization(const NamedDecl *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,11 +374,21 @@ for (Decl *D : DG) { if (!SM.isWrittenInMainFile(SM.getExpansionLoc(D->getLocation()))) continue; - // FIXME: Filter out certain Obj-C and template-related decls. + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (isImplicitTemplateInstantiation(ND)) + continue; + // FIXME: Filter out certain Obj-C as well. Out->Roots.push_back(D); } return ASTConsumer::HandleTopLevelDecl(DG); } + + private: + bool isImplicitTemplateInstantiation(const NamedDecl *D) { + return isImplicitTemplateSpecialization<FunctionDecl>(D) || + isImplicitTemplateSpecialization<CXXRecordDecl>(D) || + isImplicitTemplateSpecialization<VarDecl>(D); + } }; return std::make_unique<Recorder>(this);
Index: clang-tools-extra/include-cleaner/unittests/RecordTest.cpp =================================================================== --- clang-tools-extra/include-cleaner/unittests/RecordTest.cpp +++ clang-tools-extra/include-cleaner/unittests/RecordTest.cpp @@ -101,6 +101,28 @@ EXPECT_THAT(Recorded.Roots, testing::ElementsAre(named("x"))); } +// Decl from template instantiation is filtered out from roots. +TEST_F(RecordASTTest, TemplateInstantiations) { + 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::Not(testing::ElementsAre(named("get")))); +} + class RecordPPTest : public ::testing::Test { protected: TestInputs Inputs; Index: clang-tools-extra/include-cleaner/lib/Record.cpp =================================================================== --- clang-tools-extra/include-cleaner/lib/Record.cpp +++ 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,15 @@ return IWYUPublic.find(FE->getUniqueID()) != IWYUPublic.end(); } +namespace { +template <typename T> +bool isImplicitTemplateSpecialization(const NamedDecl *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,11 +374,21 @@ for (Decl *D : DG) { if (!SM.isWrittenInMainFile(SM.getExpansionLoc(D->getLocation()))) continue; - // FIXME: Filter out certain Obj-C and template-related decls. + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) + if (isImplicitTemplateInstantiation(ND)) + continue; + // FIXME: Filter out certain Obj-C as well. Out->Roots.push_back(D); } return ASTConsumer::HandleTopLevelDecl(DG); } + + private: + bool isImplicitTemplateInstantiation(const NamedDecl *D) { + return isImplicitTemplateSpecialization<FunctionDecl>(D) || + isImplicitTemplateSpecialization<CXXRecordDecl>(D) || + isImplicitTemplateSpecialization<VarDecl>(D); + } }; return std::make_unique<Recorder>(this);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits