A newbie question on getting operator in Expr

Hi there

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 +

How could I do that?

Thank you very much.

  • Sirinda

Never mind, I can do it now. Thank you anyway :slight_smile:

Would you be willing to show code? I would like to do that as well.

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

sorry, I forgot to include the following code to check if the stmt is an
expr.

// this code is inside VisitStmt(Stmt* Node)
if (isa<Expr>(Node)) {
  Expr *expr = (Expr*)Node;
        VisitExpr(expr);

Hi,

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

    bool VisitBinaryOperator(BinaryOperator* expr)
    {
         // ... handle expr
         return true;
    }

    bool VisitDeclRefExpr(DeclRefExpr* expr)
    {
          // ... handle expr
          return true;
    }
};

Adrien

I dont want to hijack this thread but how would i start the RecursiveASTVisitor? The problem is, i dont know what to do after i call LoadFromASTFile
My question is in more detail here http://lists.cs.uiuc.edu/pipermail/cfe-dev/2011-June/015613.html

Thank you very much for your suggestion, I will modify my code and use
RecursiveASTVisitor instead :smiley:

Sirinda

sorry, I forgot to include the following code to check if the stmt is an
expr.

// this code is inside VisitStmt(Stmt* Node)
if (isa<Expr>(Node)) {
Expr *expr = (Expr*)Node;
VisitExpr(expr);

For what it's worth,

  if (isa<Type>(object)) {
    Type* typedObject = (Type*)object;
    ...
  }

is usually written as

  if (Type* typedObject = dyn_cast<Type>(object)) {
    ...
  }

in clang's code.

Nico