条件中带有快捷二元运算符的 Clang IfStmt
Clang IfStmt with shortcut binary operator in condition
我正在尝试检测 if 语句中是否有函数调用作为条件的一部分;如下所示:
if (cmp(a, b)){
\do something
}
I have found I could do this with AST matcher in following manner:
Matcher.addMatcher(ifStmt(hasCondition(callExpr().bind("call_expr")))
.bind("call_if_stmt"),&handleMatch);
但问题是条件可能有像&&、||这样的快捷方式;如下所示:
if(a != b && cmp(a,b) || c == 10){
\ do something
}
现在这个条件有二元运算符 && 和 ||;也有一个调用表达式作为它的一部分。现在我如何检测到这个 if 语句中有一个调用表达式?我绝对不知道会有多少二元运算符作为快捷方式,所以我正在为此寻找一个通用的解决方案,可能使用 clange AST 匹配器。
在第一种情况下,if(cmp(a,b))
,CallExpr 节点是 IfStmt 的直接子节点。在第二种情况下,它是 IfStmt 的后代,但不是子代。相反,它嵌套在两个 BinaryOperator 节点下。 (我通过查看带有 clang-check -ast-dump test.cpp --
的 AST 发现了这一点。)添加一个 hasDescendant
遍历匹配器将找到嵌套更深的 CallExpr。不幸的是,仅此一项无法找到第一个案例。所以我们可以使用 anyOf
将其与原始匹配器结合起来:
ifStmt(
hasCondition(
anyOf(
callExpr().bind("top_level_call_expr"),
hasDescendant(
callExpr().bind("nested_call_expr")
)
)
)
).bind("call_if_stmt")
如果我取test.cpp有如下代码:
bool cmp(int a, int b){return a < b;}
int f(int a, int c){
int b = 42;
if( a != b && cmp(a,b) || c == 10){
return 2;
}
return c;
}
int g(int a, int c){
int b = 42;
if( cmp(a,b)) {
return 2;
}
return c;
}
然后我可以用 clang-query test.cpp --
:
测试一下
clang-query> let m2 ifStmt( hasCondition( anyOf(callExpr().bind("top_level_call_expr"),hasDescendant(callExpr().bind("nested_call_expr"))))).bind("call_if_stmt")
clang-query> m m2
Match #1:
/path/to/test.xpp:5:7: note: "call_if_stmt" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/path/to/test.cpp:5:21: note: "nested_call_expr" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~
/path/to/test.cpp:5:7: note: "root" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Match #2:
/path/to/test.cpp:13:7: note: "call_if_stmt" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:7: note: "root" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:11: note: "top_level_call_expr" binds here
if( cmp(a,b)) {
^~~~~~~~
2 matches.
我正在尝试检测 if 语句中是否有函数调用作为条件的一部分;如下所示:
if (cmp(a, b)){
\do something
}
I have found I could do this with AST matcher in following manner:
Matcher.addMatcher(ifStmt(hasCondition(callExpr().bind("call_expr")))
.bind("call_if_stmt"),&handleMatch);
但问题是条件可能有像&&、||这样的快捷方式;如下所示:
if(a != b && cmp(a,b) || c == 10){
\ do something
}
现在这个条件有二元运算符 && 和 ||;也有一个调用表达式作为它的一部分。现在我如何检测到这个 if 语句中有一个调用表达式?我绝对不知道会有多少二元运算符作为快捷方式,所以我正在为此寻找一个通用的解决方案,可能使用 clange AST 匹配器。
在第一种情况下,if(cmp(a,b))
,CallExpr 节点是 IfStmt 的直接子节点。在第二种情况下,它是 IfStmt 的后代,但不是子代。相反,它嵌套在两个 BinaryOperator 节点下。 (我通过查看带有 clang-check -ast-dump test.cpp --
的 AST 发现了这一点。)添加一个 hasDescendant
遍历匹配器将找到嵌套更深的 CallExpr。不幸的是,仅此一项无法找到第一个案例。所以我们可以使用 anyOf
将其与原始匹配器结合起来:
ifStmt(
hasCondition(
anyOf(
callExpr().bind("top_level_call_expr"),
hasDescendant(
callExpr().bind("nested_call_expr")
)
)
)
).bind("call_if_stmt")
如果我取test.cpp有如下代码:
bool cmp(int a, int b){return a < b;}
int f(int a, int c){
int b = 42;
if( a != b && cmp(a,b) || c == 10){
return 2;
}
return c;
}
int g(int a, int c){
int b = 42;
if( cmp(a,b)) {
return 2;
}
return c;
}
然后我可以用 clang-query test.cpp --
:
clang-query> let m2 ifStmt( hasCondition( anyOf(callExpr().bind("top_level_call_expr"),hasDescendant(callExpr().bind("nested_call_expr"))))).bind("call_if_stmt")
clang-query> m m2
Match #1:
/path/to/test.xpp:5:7: note: "call_if_stmt" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/path/to/test.cpp:5:21: note: "nested_call_expr" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~
/path/to/test.cpp:5:7: note: "root" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Match #2:
/path/to/test.cpp:13:7: note: "call_if_stmt" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:7: note: "root" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:11: note: "top_level_call_expr" binds here
if( cmp(a,b)) {
^~~~~~~~
2 matches.