【问题标题】:Writing AST matcher to find all case statements having no break statement编写 AST 匹配器以查找所有没有 break 语句的 case 语句
【发布时间】:2019-08-06 21:13:17
【问题描述】:

我想找到所有没有 break 语句的 case 语句。我使用 clang-query 来构建我的匹配器。我的匹配器在某些测试用例中失败了。

我把简单的匹配器写成

匹配 caseStmt(除非(has(breakStmt())))

它适用于以下测试用例

#include<stdlib.h>

int main(){

int x;
switch(x){

  case 1:
     break;

  case 2:


  default:
     x++;
}
return 0;
}

int main() 
{ 
    int x = 1, y = 2; 

    // Outer Switch 
    switch (x) { 

    // If x == 1 
    case 1: 

        // Nested Switch 

        switch (y) { 

        // If y == 2 
        case 2: 

            //break; 

        // If y == 3 
        case 3: 

            break; 
        } 
        break; 

    // If x == 4 
    case 4: 

        break; 

    // If x == 5 
    case 5: 

        break; 

    default: 

        break; 
    } 
    return 0; 
} 

不适合跟随

#include <iostream> 
using namespace std; 

int main() 
{ 
    int x = 1, y = 2; 

    // Outer Switch 
    switch (x) { 

    // If x == 1 
    case 1: 

        // Nested Switch 

        switch (y) { 

        // If y == 2 
        case 2: 
            cout << "Choice is 2"; 
            //break; 

        // If y == 3 
        case 3: 
            cout << "Choice is 3"; 
            break; 
        } 
        //break; 

    // If x == 4 
    case 4: 
        cout << "Choice is 4"; 
        break; 

    // If x == 5 
    case 5: 
        cout << "Choice is 5"; 
        break; 

    default: 
        cout << "Choice is other than 1, 2 3, 4, or 5"; 
        break; 
    } 
    return 0; 
} 

在上面的案例中,它显示了带有 break 语句的 case 语句以及没有 break 语句的 case 语句。

我做错了什么?请帮助:)我正在关注这个 http://releases.llvm.org/8.0.0/tools/clang/docs/LibASTMatchersTutorial.html

【问题讨论】:

    标签: clang llvm llvm-clang clang-ast-matchers clang-query


    【解决方案1】:

    不幸的是,这行不通:-(

    case 在技术上是一个label,而label 只有一个语句作为它的子语句。如果您打印出 AST,您会看到 casebreak 语句将处于同一级别:

        |   |-CaseStmt 0x5618732e1e30 <line:29:3, line:30:9>
        |   | |-IntegerLiteral 0x5618732e1e10 <line:29:8> 'int' 4
        |   | |-<<<NULL>>>
        |   | `-CallExpr 0x5618732e1f00 <line:30:5, col:9> 'void'
        |   |   `-ImplicitCastExpr 0x5618732e1ee8 <col:5> 'void (*)()' <FunctionToPointerDecay>
        |   |     `-DeclRefExpr 0x5618732e1ec0 <col:5> 'void ()' lvalue Function 0x5618732e16d0 'foo' 'void ()'
        |   |-BreakStmt 0x5618732e1f28 <line:31:5>
        |   |-CaseStmt 0x5618732e1f50 <line:34:3, line:35:9>
        |   | |-IntegerLiteral 0x5618732e1f30 <line:34:8> 'int' 5
        |   | |-<<<NULL>>>
        |   | `-CallExpr 0x5618732e2020 <line:35:5, col:9> 'void'
        |   |   `-ImplicitCastExpr 0x5618732e2008 <col:5> 'void (*)()' <FunctionToPointerDecay>
        |   |     `-DeclRefExpr 0x5618732e1fe0 <col:5> 'void ()' lvalue Function 0x5618732e16d0 'foo' 'void ()'
        |   |-BreakStmt 0x5618732e2048 <line:36:5>
    
    

    在这里您可以看到CallExprCaseStmt 的孩子,而BreakStmt 不是。

    注意:为了让示例更简单,我将 std::cout &lt;&lt; "..." 替换为 foo()

    您必须编写一个非常更复杂的匹配器来获取cases,它们之间没有break 语句和以下cases

    我希望这仍然有帮助。

    【讨论】:

    • 你能帮忙吗...?
    • 我真的不知道如何使用现有的匹配器来做到这一点。我要么把它写成一个 AST 遍历器,它可以找到你需要的东西,要么是一个自定义匹配器(没有关于它的文档,你必须自己研究 ASTMatchersMacros.hASTMatchers.h)。
    • 当它紧跟在 case 语句之后,它就是它的孩子
    猜你喜欢
    • 1970-01-01
    • 2017-02-27
    • 2013-04-13
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多