Clang IfStmt with shortcut binary operator in condition

为君一笑 提交于 2019-12-08 12:43:12

问题


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
}

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.


回答1:


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

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

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.


来源:https://stackoverflow.com/questions/44814529/clang-ifstmt-with-shortcut-binary-operator-in-condition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!