[cfe-dev] Visiting statements of a CFG one time
Artem Dergachev via cfe-dev
cfe-dev at lists.llvm.org
Tue Sep 8 19:44:52 PDT 2020
Note that the surrounding statement is not necessarily in the same
block. Say, your algorithm would fail to find full statement 'x ? y :
z;' by looking at its sub-expression 'y'.
As far as i'm aware, no existing data flow analyses operate the way you
describe.
On 9/8/20 7:15 AM, Andrew Sutton via cfe-dev wrote:
> 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.
>
> There's probably a better way to do this, but here's what my
> implementation of that function looks like.
>
> void findStatements(CFGBlock *B, llvm::SmallVectorImpl<const Stmt
> *> &SS) {
> llvm::SmallDenseMap<const Stmt*, bool> Map;
>
> // Mark subexpressions of each element in the block.
> for (auto I = B->begin(); I != B->end(); ++I) {
> CFGElement E = *I;
> if (auto SE = E.getAs<CFGStmt>()) {
> const Stmt *S = SE->getStmt();
> for (const Stmt *K : S->children())
> Map[K] = true;
> }
> }
>
> // Any expressions not in Map are statements.
> for (auto I = B->begin(); I != B->end(); ++I) {
> CFGElement E = *I;
> if (auto SE = E.getAs<CFGStmt>()) {
> const Stmt *S = SE->getStmt();
> if (Map.find(S) == Map.end())
> SS.push_back(S);
> }
> }
> }
>
> Andrew Sutton
>
>
> On Tue, Sep 8, 2020 at 9:44 AM Stefan Schulze Frielinghaus via cfe-dev
> <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>
> Hi all,
>
> I'm trying to iterate over all top-level functions of a C file and
> perform
> control-flow analysis of each function body. My current approach
> looks as
> follows:
>
> class MyASTVisitor : public DeclVisitor<MyASTVisitor> {
> ASTContext &Context;
> public:
> explicit MyASTVisitor(ASTContext &Context) : Context(Context) { }
>
> void VisitFunctionDecl(FunctionDecl *FD) {
> if (!FD->hasBody())
> return;
>
> FD->getNameInfo().getName().dump();
>
> const CFG::BuildOptions opts;
> auto CFG = CFG::buildCFG(FD, FD->getBody(), &Context, opts);
> CFG->dump(Context.getLangOpts(), true);
> // perform the actual analysis over the CFG
> }
> };
>
> class MyConsumer : public ASTConsumer {
> MyASTVisitor Visitor;
> public:
> explicit MyConsumer(ASTContext &Context) : Visitor(Context) { }
>
> bool HandleTopLevelDecl(DeclGroupRef DR) override {
> for (auto *I : DR)
> Visitor.Visit(I);
> return true;
> }
> };
>
> What confuses me right now is how the CFG is structured. Consider the
> following C code:
>
> extern int *pi;
> extern unsigned char *pc;
> void foo(void) {
> *(pi=(int *)pc, pi) = 42;
> }
>
> The dump of the corresponding CFG looks as follows:
>
> [B2 (ENTRY)]
> Succs (1): B1
>
> [B1]
> 1: pi = (int *)pc
> 2: pi (ImplicitCastExpr, LValueToRValue, int *)
> 3: ... , [B1.2]
> 4: *([B1.3]) = 42
> Preds (1): B2
> Succs (1): B0
>
> [B0 (EXIT)]
> Preds (1): B1
>
> The single statement
> *(pi=(int *)pc, pi) = 42;
> is broken up into 4 statements in the CFG. That means, if I
> iterate over each
> statement of a block like
>
> for (const CFGBlock *block : *CFG) {
> for (const auto &I : *block) {
> if (Optional<CFGStmt> cs = I.getAs<CFGStmt>())
> TF.Visit(cs->getStmt());
> }
> }
>
> and the transfer functions TF recursively visit each
> subexpression, I will
> visit some of them twice. My plan was actually to construct
> transfer functions
> of type ConstStmtVisitor in order to examine each statement
> recursively. In
> the past I ran into a similar problem which was related to wrongly set
> CFG::BuildOptions. However, this does not seem to be the case
> this time.
>
> Is it possible to construct a CFG where statements are not split?
> Or is there
> another approach to walk over all statements of a basic block
> exactly one time?
>
> Cheers,
> Stefan
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200908/26a1bc7c/attachment.html>
More information about the cfe-dev
mailing list