带有条件二进制快捷方式的Clang IfStmt [英] Clang IfStmt with shortcut binary operator in condition

查看:177
本文介绍了带有条件二进制快捷方式的Clang IfStmt的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测if语句内部是否存在函数调用(作为条件的一部分);如下所示:

I am trying to detect if there is a function call inside an if statement as part of condition; like following:

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);

但是问题在于条件可能具有&&,||;之类的快捷方式.如下所示:

But the problem is condition could have shortcuts like &&, ||; like following:

if(a != b && cmp(a,b) || c == 10){
\\ do something
}

现在此条件具有二进制运算符&&和||;也有一个调用表达式.现在,如何检测该if语句中是否存在调用表达式?绝对我不知道会有多少个二进制运算符作为快捷方式,因此我正在寻找一种通用的解决方案,可能使用clange AST匹配器.

Now this condition has binaryoperator && and ||; also have a call expression as part of it. Now how I could detect that there is a call expression inside this if statement? Definitely I don't know how many binary operator as shortcuts will be there, so I am looking for a generalize solution for this, possibly using clange AST matcher.

推荐答案

在第一种情况下,if(cmp(a,b)),CallExpr节点是IfStmt的直接子级.在第二种情况下,它是IfStmt的后代,但不是孩子.而是将其嵌套在两个BinaryOperator节点下. (我通过使用clang-check -ast-dump test.cpp --查看AST发现了这一点.)添加hasDescendant遍历匹配器将发现嵌套更深的CallExpr.不幸的是,仅此一项将无法找到第一种情况.因此,我们可以使用anyOf将其与原始匹配器结合起来:

In the first case, if(cmp(a,b)), the CallExpr node is a direct child of the IfStmt. In the second case, it is a descendant of the IfStmt, but not a child. Instead, it is nested beneath two BinaryOperator nodes. (I found this out by looking at the AST with clang-check -ast-dump test.cpp --.) Adding a hasDescendant traversal matcher will find the more deeply nested CallExpr. Unfortunately, that alone will not find the first case. So we could use anyOf to combine it with the original matcher:

ifStmt( 
  hasCondition( 
    anyOf(
      callExpr().bind("top_level_call_expr"),
      hasDescendant(
        callExpr().bind("nested_call_expr")
      )
    )
  )
).bind("call_if_stmt")

如果我使test.cpp具有以下代码:

If I take test.cpp to have the following code:

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 --进行测试:

then I can test this with 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.

这篇关于带有条件二进制快捷方式的Clang IfStmt的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆