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

Richard Trieu via cfe-users cfe-users at lists.llvm.org
Tue Aug 6 19:41:46 PDT 2019


RecursiveASTVisitor should have an ASTContext available.  ASTContext has a
getParents function, which may be of some use.  Unfortunately, I haven't
used this part of the ASTContext before, so I can't give any more concrete
advice.  As you've seen, it's easier to traverse down the AST than up it.

On Tue, Aug 6, 2019 at 11:56 AM Ayush Mittal <bellavistaghome at gmail.com>
wrote:

> Thanks Richard for the explanation!
>
> |       | | |-IfStmt 0x78b6d90 <line:82:13, line:89:13>
> |       | | | |-<<<NULL>>>
> |       | | | |-<<<NULL>>>
> |       | | | |-BinaryOperator 0x78b5f08 <line:82:17, col:34> 'int' '=='
> |       | | | | |-ImplicitCastExpr 0x78b5eb0 <col:17, col:23> 'int'
> <IntegralCast>
> |       | | | | | `-ImplicitCastExpr 0x78b5e58 <col:17, col:23>
> 'example_tree':'enum example_tree_type_' <LValueToRValue>
> |       | | | | |   `-MemberExpr 0x78b5d78 <col:17, col:23>
> 'example_tree':'enum example_tree_type_' lvalue ->*bal* 0x75a3ab0
> |       | | | | |     `-ImplicitCastExpr 0x78b5d20 <col:17>
> 'example_tree_node *' <LValueToRValue>
> |       | | | | |       `-*DeclRefExpr* 0x78b5cb8 <col:17>
> 'example_tree_node *' lvalue Var 0x78b1d48 'left' 'example_tree_node *'
>
>
> Is there a way to get an access to the MemberExpr and ImplicitCastExpr
> from VisitDeclRefExpr.
>
> Thanks for the help!
>
> Reagrds.
>
> On Thu, Aug 1, 2019 at 8:14 PM Richard Trieu <rtrieu at google.com> wrote:
>
>> 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>
>> wrote:
>>
>>> 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
>> yourself.
>>
>>>
>>> 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/20190806/99d9857c/attachment.html>


More information about the cfe-users mailing list