【问题标题】:Clang IfStmt with shortcut binary operator in condition在条件下使用快捷二元运算符 Clang IfStmt
【发布时间】:2017-06-29 00:29:35
【问题描述】:

我试图检测 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 匹配器。

【问题讨论】:

    标签: clang llvm abstract-syntax-tree llvm-clang


    【解决方案1】:

    在第一种情况下,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 语句中有多少调用表达式?
    • 我得到了答案:ifStmt(hasCondition(forEachDescendant(callExpr().bind("call_expression")))).bind("if_stmt_inside_call")
    猜你喜欢
    • 2021-11-04
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2014-12-11
    • 2010-09-18
    • 2010-09-28
    相关资源
    最近更新 更多