<div dir="ltr">I ran into exactly this problem last week. I wanted to visit top-level statements (and expressions since expression-statements are just expressions) and recursively work through their ASTs. I just wrote a small pre-pass over the CFG elements that would construct a set of top-level statements by noting which expressions occurred as subexpressions and then extract the statements from there.<div><div><br></div><div>There's probably a better way to do this, but here's what my implementation of that function looks like.<br><div><br></div><div>    void findStatements(CFGBlock *B, llvm::SmallVectorImpl<const Stmt *> &SS) {<br>      llvm::SmallDenseMap<const Stmt*, bool> Map;<br><br>      // Mark subexpressions of each element in the block.<br>      for (auto I = B->begin(); I != B->end(); ++I) {<br>        CFGElement E = *I;<br>        if (auto SE = E.getAs<CFGStmt>()) {<br>          const Stmt *S = SE->getStmt();<br>          for (const Stmt *K : S->children())<br>            Map[K] = true;<br>        }<br>      }<br><br>      // Any expressions not in Map are statements.<br>      for (auto I = B->begin(); I != B->end(); ++I) {<br>        CFGElement E = *I;<br>        if (auto SE = E.getAs<CFGStmt>()) {<br>          const Stmt *S = SE->getStmt();<br>          if (Map.find(S) == Map.end())<br>            SS.push_back(S);<br>        }<br>      }<br>    }<br></div></div></div><div><br></div><div>Andrew Sutton</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 8, 2020 at 9:44 AM Stefan Schulze Frielinghaus via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all,<br>
<br>
I'm trying to iterate over all top-level functions of a C file and perform<br>
control-flow analysis of each function body.  My current approach looks as<br>
follows:<br>
<br>
class MyASTVisitor : public DeclVisitor<MyASTVisitor> {<br>
  ASTContext &Context;<br>
public:<br>
  explicit MyASTVisitor(ASTContext &Context) : Context(Context) { }<br>
<br>
  void VisitFunctionDecl(FunctionDecl *FD) {<br>
    if (!FD->hasBody())<br>
      return;<br>
<br>
    FD->getNameInfo().getName().dump();<br>
<br>
    const CFG::BuildOptions opts;<br>
    auto CFG = CFG::buildCFG(FD, FD->getBody(), &Context, opts);<br>
    CFG->dump(Context.getLangOpts(), true);<br>
    // perform the actual analysis over the CFG<br>
  }<br>
};<br>
<br>
class MyConsumer : public ASTConsumer {<br>
  MyASTVisitor Visitor;<br>
public:<br>
  explicit MyConsumer(ASTContext &Context) : Visitor(Context) { }<br>
<br>
  bool HandleTopLevelDecl(DeclGroupRef DR) override {<br>
    for (auto *I : DR)<br>
      Visitor.Visit(I);<br>
    return true;<br>
  }<br>
};<br>
<br>
What confuses me right now is how the CFG is structured.  Consider the<br>
following C code:<br>
<br>
extern int *pi;<br>
extern unsigned char *pc;<br>
void foo(void) {<br>
    *(pi=(int *)pc, pi) = 42;<br>
}<br>
<br>
The dump of the corresponding CFG looks as follows:<br>
<br>
 [B2 (ENTRY)]<br>
   Succs (1): B1<br>
<br>
 [B1]<br>
   1: pi = (int *)pc<br>
   2: pi (ImplicitCastExpr, LValueToRValue, int *)<br>
   3: ... , [B1.2]<br>
   4: *([B1.3]) = 42<br>
   Preds (1): B2<br>
   Succs (1): B0<br>
<br>
 [B0 (EXIT)]<br>
   Preds (1): B1<br>
<br>
The single statement<br>
  *(pi=(int *)pc, pi) = 42;<br>
is broken up into 4 statements in the CFG.  That means, if I iterate over each<br>
statement of a block like<br>
<br>
for (const CFGBlock *block : *CFG) {<br>
  for (const auto &I : *block) {<br>
    if (Optional<CFGStmt> cs = I.getAs<CFGStmt>())<br>
      TF.Visit(cs->getStmt());<br>
  }<br>
}<br>
<br>
and the transfer functions TF recursively visit each subexpression, I will<br>
visit some of them twice.  My plan was actually to construct transfer functions<br>
of type ConstStmtVisitor in order to examine each statement recursively.  In<br>
the past I ran into a similar problem which was related to wrongly set<br>
CFG::BuildOptions.  However, this does not seem to be the case this time.<br>
<br>
Is it possible to construct a CFG where statements are not split?  Or is there<br>
another approach to walk over all statements of a basic block exactly one time?<br>
<br>
Cheers,<br>
Stefan<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>