[cfe-users] AST Recursive Visitor- Statements (Stmt *)

Richard Trieu via cfe-users cfe-users at lists.llvm.org
Thu Aug 1 20:14:01 PDT 2019

Adding back the mailing list.  Please reply all to keep the discussion on
the mailing list.

On Thu, Aug 1, 2019 at 2:47 PM Ayush Mittal <bellavistaghome at gmail.com>

> Thanks Richard for the explanation. Really appreciate it.
> One quick question, Within VisitStmt (BinaryOperator) how could I get an
> access to DeclRefExpr class.

You should be defining a VisitBinaryOperator(BinaryOperator*) function.
VisitStmt(BinaryOperator) won't be called because the base visitor class
doesn't know about it.

> For example,
> *-IfStmt* 0x88b5698 <line:13:3, line:16:12>
>     | |-<<<NULL>>>
>     | |-<<<NULL>>>
>     | |-BinaryOperator 0x88b54a0 <line:13:7, col:13> 'int' '=='
>     | | |-ImplicitCastExpr 0x88b5420 <col:7> 'int' <LValueToRValue>
>     | | | `-*DeclRefExpr* 0x88b5358 <col:7> 'int' lvalue ParmVar
> 0x88604b0 'argc' 'int'
> BinaryOperator has two methods, getLHS() and getRHS() which get the
left-hand side and right-hand side expressions.  Given your BinaryOperator,
getLHS() will return the ImplicitCastExpr.  The Expr class has several
methods to remove nodes in the AST.  Expr::IgnoreImpCasts() is probably
what you want here*.   Then you need to check the final Expr if it is
DeclRefExpr and use that.

BinaryOperator *BO = ...;
Expr *E = BO->getLHS();
E = E->IgnoreImpCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
  // Do your stuff here.

or just:

BinaryOperator *BO = ...;
if (DeclRefExpr *DRE =
dyn_cast<DeclRefExpr>(E->getLHS()->IgnoreImpCasts())) {
  // Do your stuff here.

* There's several Expr::Ignore* functions that recursively strips aways
different AST nodes from Expr's.  In your examples, IgnoreImpCasts will
strip away the LValue to RValue cast, but if there was something like
integral cast between different int types, that would stripped away too.
If you need more fine-grained control, you'll need to do the AST traversal

> Thanks and Regards.
> On Tue, Jul 30, 2019 at 9:11 PM Richard Trieu <rtrieu at google.com> wrote:
>> Hi Ayush,
>> First, you need to know the classes associated with each of your
>> target AST nodes.  These are IfStmt, WhileStmt, ForStmt, BinaryOperator,
>> and UnaryOperator.  Each of these are sub-classes of Stmt.  IfStmt,
>> WhileStmt, ForStmt and direct sub-classes while BinaryOperator and
>> UnaryOperator are sub-classes of Expr, which is a sub-class of ValueStmt,
>> which is a sub-class of Stmt.  There's also two other related classes,
>> CXXForRangeStmt and DoStmt, which represent ranged-based for-loops and
>> do/while loops.
>> Second, pointers can be changed between classes with the cast and
>> dyn_cast functions and Stmt::getStmtClass() will tell the type of the
>> Stmt.  They are used as follows:
>> void VisitStmt(Stmt *S) {
>>   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
>>     // Process BinaryOperator here
>>   } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(S)) {
>>     ...
>>   } // other checks here
>> }
>> void VisitStmt(Stmt *S) {
>>   switch (S->getStmtClass()) {
>>   case Stmt::BinaryOperatorClass: {
>>     BinaryOperator *BO = cast<BinaryOperator>(S);
>>     // Process BinaryOperator here
>>   }
>>   case Stmt::UnaryOperatorClass: {
>>     UnaryOperator *UO = cast<UnaryOperator>(S);
>>   }
>>   // Other cases here
>>   }
>> }
>> The difference between cast and dyn_cast is that cast expects the pointer
>> is the correct type without checking while dyn_cast does check the target
>> type and returns a null pointer on a type mismatch.  Chains of dyn_cast's
>> are used if the list of nodes is short while using a switch on
>> Stmt::getStmtClass() is used when checking a lot of node types.
>> There's also a third way.  Since you are already using a visitor, the
>> visitor will have a visit function for each AST node.  Instead of writing
>> just VisitStmt, you will write a VisitBinaryOperator(BinaryOperator *),
>> VisitUnaryOperator(UnaryOperator *), and so on for each one you're
>> interested in.  Hope this is enough to get you started.
>> On Tue, Jul 30, 2019 at 4:25 PM Ayush Mittal via cfe-users <
>> cfe-users at lists.llvm.org> wrote:
>>> Hello Clangers,
>>> I'm new to clang. I'm writing an AST Consumer plug-in to visit the
>>> statements node and record the data in one of my table with line numbers.
>>> I've this function callback ready: *VisitStmt(Stmt *S)*. My question is
>>> how could I traverse If, while, for loop, boolean and Unary Operators-
>>> inside this function.
>>> Thanks and Regards.
>>> _______________________________________________
>>> cfe-users mailing list
>>> cfe-users at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20190801/d8b40850/attachment.html>

More information about the cfe-users mailing list