diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 3d01a70395a9bb..121e148a429d8d 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -1237,7 +1237,8 @@ class MatchASTVisitor : public RecursiveASTVisitor, // Make sure we do not visit the same node twice. // Otherwise, we'll visit the common ancestors as often as there // are splits on the way down. - if (Visited.insert(Parent.getMemoizationData()).second) + auto Key = Parent.getMemoizationData(); + if (Key == nullptr || Visited.insert(Key).second) Queue.push_back(Parent); } Queue.pop_front(); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 1d18869a6b8afc..fdef08674d091b 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -5536,6 +5536,24 @@ TEST(HasAncestor, MatchesInImplicitCode) { hasAncestor(recordDecl(hasName("A"))))))))); } +TEST(HasAncestor, MatchesWithMultipleParentsWithoutPointerIdentity) { + EXPECT_TRUE(matches( + R"cpp( +template class Fact {}; +template class W {}; +template struct A +{ + static void f() { + W> fact12; + } +}; +void f() { + A::f(); + A::f(); +})cpp", + integerLiteral(hasAncestor(functionDecl())))); +} + TEST(HasParent, MatchesOnlyParent) { EXPECT_TRUE(matches( "void f() { if (true) { int x = 42; } }",