Extract all true/false combinations from an IfStmt condition in Clang

  abstract-syntax-tree, c++, clang

I am trying to extract the possible true/false combinations from an IfStmt condition to have a separate list of expressions which correspond to testing "Multiple Condition Coverage".

Example: whenever my clang pass encounters an IfStmt such as if (x == 1 && (y+z > 0) || k) then my output should be a list of 2^3 = 8 expressions that look like a truth table of the 3 BinaryOperator expressions in the condition:

( (x==1) &&  (y+z > 0) ||  (k) )
( (x==1) &&  (y+z > 0) || !(k) )
( (x==1) && !(y+z > 0) ||  (k) )
( (x==1) && !(y+z > 0) || !(k) )
(!(x==1) &&  (y+z > 0) ||  (k) )
(!(x==1) &&  (y+z > 0) || !(k) )
(!(x==1) && !(y+z > 0) ||  (k) )
(!(x==1) && !(y+z > 0) || !(k) )

I am using a VisitIfStmt function which calls my custom expr_visitor function:

vector<Expr *> expr_visitor(vector<Expr *> expr_list, Expr *node){

    if(isa<BinaryOperator>(node)){
        BinaryOperator *node_BO = dyn_cast<BinaryOperator>(node);
        if(node_BO->isLogicalOp()){             // case: x || y, x && y
            // visit lhs 
            expr_list = expr_visitor(expr_list, node_BO->getLHS());
            // visit rhs
            expr_list = expr_visitor(expr_list, node_BO->getRHS());
        }
        else{                                   // case: x == 2, x + y, x < 0
            // Create paren expr
            ParenExpr *node_paren = new (context_) ParenExpr(node_BO->getBeginLoc(), node_BO->getEndLoc(), node_BO);    // context_ is an ASTContext 
            expr_list.push_back(node_paren);
        }
    }
    else if(isa<CallExpr>(node)                 // case: foo()      
        ||  isa<IntegerLiteral>(node)           // case: 1
        ||  isa<ImplicitCastExpr>(node)         // case: x
    )
    {       
        expr_list.push_back(node);
    }
    else if(isa<ParenExpr>(node))               // case: (x)
    {
        // Cast to ParenExpr and recursively visit subexpression
        ParenExpr *node_paren = dyn_cast<ParenExpr>(node);
        expr_list = expr_visitor(expr_list, node_paren->getSubExpr());
    }
    
    return expr_list;
} 

bool VisitIfStmt(IfStmt *ifStmt){
    
    // get location
    SourceLocation exprBegin = ifStmt->getBeginLoc();
    // get condition
    Expr *cond = ifStmt->getCond();
    
    vector<Expr *> expr_list = expr_visitor({}, cond);
    
    cout << "nExpr List: " << endl;
    for(Expr *x : expr_list){
        x->dumpColor(); // to print the AST dump
        cout << endl;
    }
    cout << endl;
    return true;
}

My expression visitor only adds the inner expressions to the list, so my output currently (for the example above) is :

Expr List: 
ParenExpr 0x56515259f060 'int'
`-BinaryOperator 0x56515259eb08 'int' '=='
  |-ImplicitCastExpr 0x56515259eaf0 'int' <LValueToRValue>
  | `-DeclRefExpr 0x56515259eab0 'int' lvalue Var 0x56515259c328 'x' 'int'
  `-IntegerLiteral 0x56515259ead0 'int' 1

ParenExpr 0x56515259f080 'int'
`-BinaryOperator 0x56515259ebd8 'int' '>'
  |-BinaryOperator 0x56515259eb98 'int' '+'
  | |-ImplicitCastExpr 0x56515259eb68 'int' <LValueToRValue>
  | | `-DeclRefExpr 0x56515259eb28 'int' lvalue Var 0x56515259c498 'y' 'int'
  | `-ImplicitCastExpr 0x56515259eb80 'int' <LValueToRValue>
  |   `-DeclRefExpr 0x56515259eb48 'int' lvalue Var 0x56515259c3e0 'z' 'int'
  `-IntegerLiteral 0x56515259ebb8 'int' 0

ImplicitCastExpr 0x56515259ec58 'int' <LValueToRValue>
`-DeclRefExpr 0x56515259ec38 'int' lvalue Var 0x56515259c550 'k' 'int'

How would I modify my expression visitor function to store the possible true/false combinations? Should I store the logical operator and then re-create the condition with the extracted expressions?

Source: Windows Questions C++

LEAVE A COMMENT