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

2019-08-01 Thread Richard Trieu via cfe-users
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 
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 
> | |-<<>>
> | |-<<>>
> | |-BinaryOperator 0x88b54a0  'int' '=='
> | | |-ImplicitCastExpr 0x88b5420  'int' 
> | | | `-*DeclRefExpr* 0x88b5358  '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(E)) {
  // Do your stuff here.
}

or just:

BinaryOperator *BO = ...;
if (DeclRefExpr *DRE =
dyn_cast(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  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(S)) {
>> // Process BinaryOperator here
>>   } else if (UnaryOperator *UO = dyn_cast(S)) {
>> ...
>>   } // other checks here
>> }
>>
>> void VisitStmt(Stmt *S) {
>>   switch (S->getStmtClass()) {
>>   case Stmt::BinaryOperatorClass: {
>> BinaryOperator *BO = cast(S);
>> // Process BinaryOperator here
>>   }
>>   case Stmt::UnaryOperatorClass: {
>> UnaryOperator *UO = cast(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@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@lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
>>>
>>
___
cfe-users mailing list
cfe-users@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users


[cfe-users] clang-format: break before brace in multiline conditionals

2019-08-01 Thread Nikos Chantziaras via cfe-users
Is there a way to make clang-format either add a line break before the 
brace in this case, or at least indent the continuation line by a higher 
amount of spaces than normal?


This is my issue:

  if (auto it = files_by_name_.find(file_name);
  it != files_by_name_.end()) {
  file_name = it->second;
  logWarn("File {} was not found by checksum, but a file with the "
  "same name exists. Will use that instead.",
  file_name);
  }

This is difficult to read, as it's not obvious where the if condition 
ends and where the code begins without taking a closer look first. In 
this example, one might think the if just controls the log message.


I'd either like this instead:

  if (auto it = files_by_name_.find(file_name);
  it != files_by_name_.end())
  {
  file_name = it->second;
  logWarn("File {} was not found by checksum, but a file with the "
  "same name exists. Will use that instead.",
  file_name);
  }

So even though normally I don't want a newline before the opening brace, 
if the initializer and/or condition doesn't fit on one line, then there 
should be a newline before the brace. It seems clang-format only offers 
an all-or-nothing option (BraceWrapping AfterControlStatement) where 
either every brace gets a line break, or none of them do.


If that's not possible, then at least is there a way to get this instead:

  if (auto it = files_by_name_.find(file_name);
  it != files_by_name_.end()) {
  file_name = it->second;
  logWarn("File {} was not found by checksum, but a file with the "
  "same name exists. Will use that instead.",
  file_name);
  }

Meaning, add extra indentation for continuation lines in if conditions.
___
cfe-users mailing list
cfe-users@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users