I am using clang to instrument code to print out all assignment statements that are relevant to formal variables.
I implement ASTConsumer and StmtVisitor to visit Stmt, especially Expr. Right now I can get all expressions in a code. What I want to do is to check if the expression contains an assignment operator. If it does, I would like to get LHS and RHS of the expression to see if there is any formal variables in it.
For example: an expression-> x = y + z;
I want to get x and (y+z) , then decompose y+z to y z and +
Well, I have my own class MyConsumer declared as below
class MyConsumer: public ASTConsumer,
public DeclVisitor<MyConsumer> ,
public StmtVisitor<MyConsumer> ,
public TypeLocVisitor<MyConsumer>
Then I modify VisitStmt(Stmt *Node) function. Inside the function I check if
this is an Expr or not. The code look like this:
void VisitExpr(Expr *expr) {
// check if this expression contains a binary operation
if (isa<clang::BinaryOperator>(expr)) {
BinaryOperator* biOp = (BinaryOperator *) expr;
// get the lhs and rhs of the operator
Expr* lhs = biOp->getLHS();
Expr* rhs = biOp->getRHS();
// recursively visit each one
VisitExpr(lhs);
VisitExpr(rhs);
}
.... // check other kinds of expr,
// since my test code is simple, the recursion stops when it find
DeclRefExpr
else if (isa<clang::DeclRefExpr>(expr)) {
DeclRefExpr* declRef = (DeclRefExpr*)expr;
// get a var name
string name =
(declRef->getNameInfo()).getName().getAsString();
cout << name << endl;
}
....
I hope this helps. I am still new to clang (and c++ ) so I am not sure if
this is an efficient way to do but it works for me now
To simplify the code and avoid handwritten recursion, maybe you could
use the RecursiveASTVisitor insted of 3 visitors:
class MyConsumer : public ASTConsumer, public RecursiveASTVisitor<MyConsumer>
{
virtual void HandleTranslationUnit(ASTContext &context)
{
// traverse AST to visit declarations and statements
TraverseDecl(context.getTranslationUnitDecl());
}