Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp =================================================================== --- clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -916,9 +916,8 @@ 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)) { Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -453,6 +453,11 @@ 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"));