diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index f1e1dae2d6b7..1b49067f0f9d 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -916,9 +916,8 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration, if (!ClassDecl) continue; if (ClassDecl == Declaration) { - // This can happen for recursive template definitions; if the - // current declaration did not match, we can safely return false. - return false; + // This can happen for recursive template definitions. + continue; } BoundNodesTreeBuilder Result(*Builder); if (Base.matches(*ClassDecl, this, &Result)) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 428879d0695c..05a77580a7ad 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -453,6 +453,20 @@ TEST(DeclarationMatcher, ClassIsDerived) { EXPECT_TRUE(notMatches("class X;", IsDerivedFromX)); EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX)); EXPECT_TRUE(notMatches("", IsDerivedFromX)); + EXPECT_TRUE(matches("class X {}; template class Y : Y, X {};", + IsDerivedFromX)); + EXPECT_TRUE(matches("class X {}; template class Y : X, Y {};", + IsDerivedFromX)); + + DeclarationMatcher IsZDerivedFromX = cxxRecordDecl(hasName("Z"), + isDerivedFrom("X")); + EXPECT_TRUE( + matches( + "class X {};" + "template class Y : Y {};" + "template<> class Y<0> : X {};" + "class Z : Y<1> {};", + IsZDerivedFromX)); DeclarationMatcher IsDirectlyDerivedFromX = cxxRecordDecl(isDirectlyDerivedFrom("X"));