I have a simple `if-else if` code I'm trying to match but clang-query
or clang itself match nothing.
here's the C code:
void myfunc (void)
{
int a = 0U;
int b = 10U;
if (a == b)
{
a++;
}
else if (a > b )
{
b++;
}
}
and this is my matcher:
ifStmt( allOf( hasDescendant(ifStmt()), hasElse(anything()) ,
unless(hasAncestor(ifStmt())) ) )
clang-query and clang don't match anything. Am i assuming wrong that I
should get one match or I'm misunderstanding something here?
I have a simple `if-else if` code I'm trying to match but clang-query
or clang itself match nothing.
here's the C code:
void myfunc (void)
{
int a = 0U;
int b = 10U;
if (a == b)
{
a++;
}
else if (a > b )
{
b++;
}
}
and this is my matcher:
ifStmt( allOf( hasDescendant(ifStmt()), hasElse(anything()) ,
unless(hasAncestor(ifStmt())) ) )
clang-query and clang don't match anything. Am i assuming wrong that I
should get one match or I'm misunderstanding something here?
I think the matcher you may want is:
clang-query> m ifStmt(hasElse(ifStmt().bind("else if")))
Match #1:
E:\Desktop\test.c:10:14: note: "else if" binds here
else if (a > b )
^~~~~~~~~~~
E:\Desktop\test.c:6:9: note: "root" binds here
if (a == b)
^~~~~~~~~~~
1 match.
However, it depends on what code pattern you're trying to match. This
matcher assumes you're looking for else if statements (which "else if"
binds to, while "root" binds to the if statement that the else
statement matches).
thank you. that actually solves my problem but still doesnt explain
why the matcher i wrote wasnt matching anything at all.
hasDescendant(ifStmt()) is true for the first "if".
hasElse(anything()) is also true and unless(hasAncestor(ifStmt())) is
also true. and theyre all arguments to a "allOf()" so technically the
first "if" should be matched and binded by root. am i mistaken
somewhere?
thank you. that actually solves my problem but still doesnt explain
why the matcher i wrote wasnt matching anything at all.
hasDescendant(ifStmt()) is true for the first "if".
hasElse(anything()) is also true and unless(hasAncestor(ifStmt())) is
also true. and theyre all arguments to a "allOf()" so technically the
first "if" should be matched and binded by root. am i mistaken
somewhere?
I've not checked out the behavior of your matcher in the debugger, but
what I am guessing is:
I think that this does not match the top-level if statement because
hasDescendant(ifStmt()) will not be satisfied -- the top-level if
statement has no sub statements that are also an if statement. It
does, however, have a sub statement that is an else statement. I
notice that the matcher does match the top-level if statement when you
remove the hasDescendant() bit from the query, FWIW.
The AST dump says that the "else if" is treated as an "if" plus an
"else" which are both children of the first "if".
Also another Question. How can I match an ifStmt that has an "else if"
but no "else" at the end?
The AST dump says that the "else if" is treated as an "if" plus an
"else" which are both children of the first "if".
Also another Question. How can I match an ifStmt that has an "else if"
but no "else" at the end?
Roughly, match an if statement that has an else if statement, unless
one of the descendants is an if statement that has an else clause that
is not an else if statement.
clang-query> match ifStmt(hasDescendant(ifStmt()), hasAncestor(ifStmt()))
Match #1:
ifstmt.c:5:3: note: "root" binds here
if (a == b) {
^~~~~~~~~~~~~
1 match.
clang-query> match ifStmt(hasDescendant(ifStmt()),
hasAncestor(ifStmt().bind("ancestor")))
0 matches.
I think that this does not match the top-level if statement because
hasDescendant(ifStmt()) will not be satisfied -- the top-level if
statement has no sub statements that are also an if statement.
hasDescendant != hasChild.
It's the hasAncestor that is behaving strangely:
clang-query> match ifStmt(hasDescendant(ifStmt()), hasAncestor(ifStmt()))
Match #1:
ifstmt.c:5:3: note: "root" binds here
if (a == b) {
^~~~~~~~~~~~~
1 match.
clang-query> match ifStmt(hasDescendant(ifStmt()),
hasAncestor(ifStmt().bind("ancestor")))
0 matches.
Okay, that is really strange. Adding a .bind() should not alter the
matches, as far as I'm aware. Manuel or Samuel, can you shed some
light on this? I think it's a bug.
I'm not sure if this is significant but like Malcolm said the
problem's probably `hasAncestor`.
this is the source code:
void myfunc (void)
{
int a = 0U;
int b = 10U;
if (a == b)
{
a++;
}
else if (a > b )
{
b++;
}
}
this matcher "ifStmt( allOf( hasDescendant(ifStmt()),
hasElse(anything()) ) )" returns:
/home/bloodstalker/devi/hell1/test3.c:6:9: note: "root" binds here
if (a == b)
^~~~~~~~~~~
1 match.
but this matcher "ifStmt( allOf( hasDescendant(ifStmt()),
hasElse(anything()) ,unless(hasAncestor(ifStmt()))))" matches nothing.
clearly the first "if" doesnt have an ifStmt ancestor, so
hasAncestor(ifStmt()) should be true and it should still match the
first "if".