[cfe-users] AST Recursive Visitor- Statements (Stmt *)
Ayush Mittal via cfe-users
cfe-users at lists.llvm.org
Tue Aug 6 11:56:13 PDT 2019
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/4bfaf81d/attachment.html>
More information about the cfe-users
mailing list