ASTMatcher unexpected result

Hi everyone,

I’m trying to use AST Matchers in clang-query to find single-depth for-loops,
i.e. for-loops that are neither contained in any other for-loop nor contain for-loops themselves.

Approach:
forStmt( unless(hasAncestor(forStmt())), unless(hasDescendant(forStmt())) )

In the following code, I want it to match only the loop in foo1, but unfortunately it also matches the loop in foo2.

void foo1(){ int n = 10; for(int i1=0; i1<n; i1++){ // dosomething(); } } void foo2(){ int n = 10; for(int i21=0; i21<n; i21++){ for(int i22=0; i22<n; i22++){ // dosomething(); } } }

Match #1:
~/cq.cpp:4:5: note: “root” binds here
for(int i1=0; i1<n; i1++){
^~~~~~~~~~~~~~~~~~~~~~~~~~

Match #2:
~/cq.cpp:11:5: note: “root” binds here
for(int i21=0; i21<n; i21++){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 matches.

When I interchange “hasAncestor” and “hasDescendant” in the matcher, the second match changes:

Match #1:
~/cq.cpp:4:5: note: “root” binds here
for(int i1=0; i1<n; i1++){
^~~~~~~~~~~~~~~~~~~~~~~~~~

Match #2:
~/cq.cpp:11:5: note: “root” binds here
for(int i22=0; i21<n; i22++){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 matches.

To me, it doesn’t make sense why the result changes (implicit allOf() matcher’s argument order shouldn’t matter), but I don’t understand why the matcher returns a loop from foo2 in the first place.

Best regards,
Siegfried Hartogs

Hi Siegfried,

I believe this bug was fixed in ⚙ D80025 [ASTMatcher] Correct memoization bug ignoring direction (descendants or ancestors). A
quick check against trunk clang-query shows correct behaviour no matter
which order the submatchers appear.

match forStmt(unless(hasAncestor(forStmt())),

unless(hasDescendant(forStmt())))

Match #1:

<source>:3:3: note: "root" binds here

for (int i1 = 0; i1 < n; i1++) { // dosomething();

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1 match.

match forStmt(unless(hasDescendant(forStmt())),

unless(hasAncestor(forStmt())))

Match #1:

<source>:3:3: note: "root" binds here

for (int i1 = 0; i1 < n; i1++) { // dosomething();

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1 match.

Can you please check against trunk(or latest release
candidate(currently RC5) on your end. The patch was landed before the
11 branch was created so it should be good there.

~Nathan

Hi Nathan, thanks for your swift answer.

the binary works nicely on 11.0.0-rc5 on Apple.

Best, Siegfried