简体   繁体   中英

Writing AST matcher to find all case statements having no break statement

I want to find all the case statement having no break statement. I using clang-query to build my matcher. My matcher is failing in some of the test cases.

I wrote simple matcher as

match caseStmt(unless(has(breakStmt())))

it works with follwing test case

#include<stdlib.h>

int main(){

int x;
switch(x){

  case 1:
     break;

  case 2:


  default:
     x++;
}
return 0;
}

在此处输入图片说明 and

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

在此处输入图片说明 does not work well with following

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

在此处输入图片说明 In above case it shows case statement that are having break statement along with case statement with no break statement.

what wrong i am doing ? please help :) I am following this http://releases.llvm.org/8.0.0/tools/clang/docs/LibASTMatchersTutorial.html

Unfortunately this is not going to work :-(

case is technically a label , and label has only one statement as its child. If you print out AST you'll see that case and break statements will be at the same level:

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

Here you can see that CallExpr is a child of CaseStmt while BreakStmt is not.

NOTE: to make example a bit easier I replaced std::cout << "..." with foo() .

You'll have to write a much more complex matcher that fetches for cases that don't have break statements between them and the following cases .

I hope this is still helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM