-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix a bug with the hasAncestor AST matcher when a node has several parents without pointer identity #118511
base: main
Are you sure you want to change the base?
Fix a bug with the hasAncestor AST matcher when a node has several parents without pointer identity #118511
Conversation
|
@llvm/pr-subscribers-clang Author: Loïc Joly (loic-joly-sonarsource) ChangesBefore 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. Full diff: https://github.com/llvm/llvm-project/pull/118511.diff 2 Files Affected:
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 3d01a70395a9bb..a7ef5ae6949537 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..17b058e4783018 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; } }",
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
…rents 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.
ed43bf2 to
8c6882a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general change looks reasonable.
| if (Parent.getMemoizationData() == nullptr || | ||
| Visited.insert(Parent.getMemoizationData()).second) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: Avoid double calls to getMemoizationData (assign to some local variable and use or write), but still call to getMemoizationData should be in theory optimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is simply an if and taking an address, I assumed it would be optimized. But I applied the suggested change.
|
Hi there. I do not have commit access, but this PR had one approval. Could someone with commit access merge it? |
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.