编写AST匹配器以查找所有没有break语句的case语句

时间:2019-08-06 21:13:17

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

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

我写的简单匹配器为

  

match caseStmt(除非(有(breakStmt())))

它与以下测试用例一起使用

#include<stdlib.h>

int main(){

int x;
switch(x){

  case 1:
     break;

  case 2:


  default:
     x++;
}
return 0;
}

enter image description here

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

enter image description here 不能与以下

配合使用
#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; 
} 

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

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

1 个答案:

答案 0 :(得分: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 << "..."替换为foo()

您将必须编写一个很多的更复杂的匹配器,该匹配器可为cases和后面的break之间没有cases语句的/** * Creates an {@link AWTEventListener} that will call the given listener if * the {@link MouseEvent} occurred inside the given component, one of its * children or the children's children etc. (recursive). * * @param component * the component the {@link MouseEvent} has to occur inside * @param listener * the listener to be called if that is the case */ public static void addRecursiveMouseListener(final Component component, final MouseListener listener) { Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { @Override public void eventDispatched(AWTEvent event) { if(event instanceof MouseEvent) { MouseEvent mouseEvent = (MouseEvent) event; if(mouseEvent.getComponent().isShowing() && component.isShowing()){ if (containsScreenLocation(component, mouseEvent.getLocationOnScreen())) { if(event.getID() == MouseEvent.MOUSE_PRESSED) { listener.mousePressed(mouseEvent); } if(event.getID() == MouseEvent.MOUSE_RELEASED) { listener.mouseReleased(mouseEvent); } if(event.getID() == MouseEvent.MOUSE_ENTERED) { listener.mouseEntered(mouseEvent); } if(event.getID() == MouseEvent.MOUSE_EXITED) { listener.mouseExited(mouseEvent); } if(event.getID() == MouseEvent.MOUSE_CLICKED){ listener.mouseClicked(mouseEvent); } } } } } }, AWTEvent.MOUSE_EVENT_MASK); } /** * Checks if the given location (relative to the screen) is inside the given component * @param component the component to check with * @param screenLocation the location, relative to the screen * @return true if it is inside the component, false otherwise */ public static boolean containsScreenLocation(Component component, Point screenLocation){ Point compLocation = component.getLocationOnScreen(); Dimension compSize = component.getSize(); int relativeX = screenLocation.x - compLocation.x; int relativeY = screenLocation.y - compLocation.y; return (relativeX >= 0 && relativeX < compSize.width && relativeY >= 0 && relativeY < compSize.height); } 获取

我希望这还是有帮助的。