Author: Kadir Cetinkaya Date: 2023-04-13T13:34:12+02:00 New Revision: 3d6d2ae6f490f0698e3d4727ae44db34b30ea33e
URL: https://github.com/llvm/llvm-project/commit/3d6d2ae6f490f0698e3d4727ae44db34b30ea33e DIFF: https://github.com/llvm/llvm-project/commit/3d6d2ae6f490f0698e3d4727ae44db34b30ea33e.diff LOG: [include-cleaner] Handle incomplete template specializations Instantiation pattern is null for incomplete template types and using specializaiton decl results in not seeing re-declarations. Differential Revision: https://reviews.llvm.org/D148158 Added: Modified: clang-tools-extra/include-cleaner/lib/WalkAST.cpp clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index 25afdaa3a75b0..e977bcbb402f7 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -21,6 +21,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/Support/Casting.h" @@ -81,9 +82,10 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> { if (llvm::isa_and_present<UsingShadowDecl, TypeAliasTemplateDecl>(ND)) return ND; // This is the underlying decl used by TemplateSpecializationType, can be - // null when type is dependent if so fallback to primary template. + // null when type is dependent or not resolved to a pattern yet. + // If so, fallback to primary template. CXXRecordDecl *TD = TST->getAsCXXRecordDecl(); - if (!TD) + if (!TD || TD->getTemplateSpecializationKind() == TSK_Undeclared) return ND; // We ignore explicit instantiations. This might imply marking the wrong // declaration as used in specific cases, but seems like the right trade-off diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp index ad5bb0aba3076..2060ffe3bb56c 100644 --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -144,6 +144,9 @@ TEST(WalkAST, ClassTemplates) { ElementsAre(Decl::CXXRecord)); // Implicit instantiations references most relevant template. + EXPECT_THAT( + testWalk("template<typename> struct $explicit^Foo;", "^Foo<int> x();"), + ElementsAre(Decl::Kind::ClassTemplate)); EXPECT_THAT( testWalk("template<typename> struct $explicit^Foo {};", "^Foo<int> x;"), ElementsAre(Decl::CXXRecord)); @@ -154,9 +157,15 @@ TEST(WalkAST, ClassTemplates) { ElementsAre(Decl::ClassTemplateSpecialization)); EXPECT_THAT(testWalk(R"cpp( template<typename> struct Foo {}; - template<typename T> struct $explicit^Foo<T*> { void x(); };)cpp", + template<typename T> struct $explicit^Foo<T*> {};)cpp", "^Foo<int *> x;"), ElementsAre(Decl::ClassTemplatePartialSpecialization)); + // Incomplete instantiations don't have a specific specialization associated. + EXPECT_THAT(testWalk(R"cpp( + template<typename> struct $explicit^Foo; + template<typename T> struct Foo<T*>;)cpp", + "^Foo<int *> x();"), + ElementsAre(Decl::Kind::ClassTemplate)); EXPECT_THAT(testWalk(R"cpp( template<typename> struct $explicit^Foo {}; template struct Foo<int>;)cpp", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits