Clang 编写AST matcher以查找所有没有break语句的case语句

Clang 编写AST matcher以查找所有没有break语句的case语句,clang,llvm,llvm-clang,clang-ast-matchers,clang-query,Clang,Llvm,Llvm Clang,Clang Ast Matchers,Clang Query,我想找到所有case语句都没有break语句。我使用clang查询来构建匹配器。我的matcher在一些测试用例中失败了 我写了一个简单的matcher作为 匹配caseStmt(除非有(breakStmt())) 它适用于以下测试用例 #include<stdlib.h> int main(){ int x; switch(x){ case 1: break; case 2: default: x++; } return 0; } 不

我想找到所有case语句都没有break语句。我使用clang查询来构建匹配器。我的matcher在一些测试用例中失败了

我写了一个简单的matcher作为

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

它适用于以下测试用例

#include<stdlib.h>

int main(){

int x;
switch(x){

  case 1:
     break;

  case 2:


  default:
     x++;
}
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; 
} 
#包括
使用名称空间std;
int main()
{ 
int x=1,y=2;
//外部开关
开关(x){
//如果x==1
案例1:
//嵌套开关
开关(y){
//如果y==2
案例2:

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

case
从技术上讲是一个
label
,并且
label
只有一条语句作为其子语句。如果打印AST,您将看到
case
break
语句将处于同一级别:

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

| |-CaseStmt 0x5618732e1e30
|| |-集成文件0x5618732E10'内部'4
|   | |-
||`-CallExpr 0x5618732e1f00'void'
|| `ImplicitCastExpr 0x5618732e1ee8'无效(*)()'
||`-DeclRefExpr 0x5618732e1ec0'void()'左值函数0x5618732e16d0'foo''void()'
||-BreakStmt 0x5618732e1f28
||-案例STMT 0x5618732e1f50
|| |-集成文件0x5618732e1f30'内部'5
|   | |-
||`-CallExpr 0x5618732e2020'无效'
|| `ImplicitCastExpr 0x5618732e2008'无效(*)()'
||`-DeclRefExpr 0x5618732e1fe0'void()'左值函数0x5618732e16d0'foo''void()'
||-BreakStmt 0x5618732e2048
在这里您可以看到,
CallExpr
CaseStmt
的子级,而
BreakStmt
不是


注意:为了使示例更简单,我替换了
std::cout,你能在这方面提供帮助吗…?我真的不知道如何使用现有的匹配器来实现这一点。我要么将其编写为一个查找所需内容的AST遍历器,要么编写为一个自定义匹配器(没有相关文档,你必须自己学习).当它紧跟在案例陈述之后时,它就是它的“孩子”
    |   |-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>