[clang] Fix a bug with the hasAncestor AST matcher when a node has several parents without pointer identity (PR #118511)
Loïc Joly via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 3 08:30:30 PST 2024
https://github.com/loic-joly-sonarsource updated https://github.com/llvm/llvm-project/pull/118511
>From 8c6882a360d0f810346dd89f20d8af0ddf0bdfb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFc=20Joly?= <loic.joly at sonarsource.com>
Date: Tue, 3 Dec 2024 17:20:18 +0100
Subject: [PATCH] Fix a bug with the hasAncestor AST matcher when a node has
several parents without pointer identity.
Before the change, getMemoizationData is used as a key to stop visiting the parents, but if a node has no identity, this is nullptr, which means that the visit will stop as soon as a second node with no identity is visited.
---
clang/lib/ASTMatchers/ASTMatchFinder.cpp | 3 ++-
.../ASTMatchers/ASTMatchersTraversalTest.cpp | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 3d01a70395a9bb..78fbbddb6bb9b1 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1237,7 +1237,8 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
// 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)
+ if (Parent.getMemoizationData() == nullptr ||
+ Visited.insert(Parent.getMemoizationData()).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 <int i> class Fact {};
+template <class T> class W {};
+template <class T> struct A
+{
+ static void f() {
+ W<Fact<12>> fact12;
+ }
+};
+void f() {
+ A<int>::f();
+ A<double>::f();
+})cpp",
+ integerLiteral(hasAncestor(functionDecl()))));
+}
+
TEST(HasParent, MatchesOnlyParent) {
EXPECT_TRUE(matches(
"void f() { if (true) { int x = 42; } }",
More information about the cfe-commits
mailing list