From: Ted Kremenek Date: Wed, 22 Aug 2007 21:36:54 +0000 (+0000) Subject: Added support for "continue" statements in source-level CFGs X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bf15b278a439d73b605ec00a8d3977ef305712f4;p=clang Added support for "continue" statements in source-level CFGs Cleaned up some code for "for" and "while" loops by making their implementations more symmetrical (and added a few comments). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41298 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/CFG.cpp b/AST/CFG.cpp index 82351370c1..98d9c8f8f8 100644 --- a/AST/CFG.cpp +++ b/AST/CFG.cpp @@ -55,6 +55,7 @@ class CFGBuilder : public StmtVisitor { CFGBlock* Block; CFGBlock* Exit; CFGBlock* Succ; + CFGBlock* ContinueTargetBlock; unsigned NumBlocks; typedef llvm::DenseMap LabelMapTy; @@ -64,7 +65,8 @@ class CFGBuilder : public StmtVisitor { BackpatchBlocksTy BackpatchBlocks; public: - explicit CFGBuilder() : cfg(NULL), Block(NULL), Exit(NULL), Succ(NULL), + explicit CFGBuilder() : cfg(NULL), Block(NULL), Exit(NULL), Succ(NULL), + ContinueTargetBlock(NULL), NumBlocks(0) { // Create an empty CFG. cfg = new CFG(); @@ -320,15 +322,24 @@ public: // We create the initialization block last, as that will be the block // we return for the recursion. - CFGBlock* CondBlock = createBlock(false); - if (Stmt* C = F->getCond()) CondBlock->appendStmt(C); - CondBlock->setTerminator(F); - Succ = CondBlock; + CFGBlock* ConditionBlock = createBlock(false); + if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C); + ConditionBlock->setTerminator(F); + + // The condition block is the implicit successor for the loop body as + // well as any code above the loop. + Succ = ConditionBlock; // Now create the loop body. { assert (F->getBody()); - SaveAndRestore sv(Block); + + // Save the current values for Block, Succ, and ContinueTargetBlock + SaveAndRestore save_Block(Block), save_Succ(Succ), + save_continue(ContinueTargetBlock); + + // All continues within this loop should go to the condition block + ContinueTargetBlock = ConditionBlock; // create a new block to contain the body. Block = createBlock(); @@ -344,15 +355,14 @@ public: FinishBlock(BodyBlock); // This new body block is a successor to our condition block. - CondBlock->addSuccessor(BodyBlock); + ConditionBlock->addSuccessor(BodyBlock); } // Link up the condition block with the code that follows the loop. // (the false branch). - CondBlock->addSuccessor(Block); + ConditionBlock->addSuccessor(Block); // Now create the block to contain the initialization. - Succ = CondBlock; Block = createBlock(); if (Stmt* I = F->getInit()) Block->appendStmt(I); @@ -363,20 +373,31 @@ public: // While is a control-flow statement. Thus we stop processing the // current block. if (Block) FinishBlock(Block); - + + // Create the condition block. CFGBlock* ConditionBlock = createBlock(false); ConditionBlock->setTerminator(W); if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C); + // The condition block is the implicit successor for the loop body as + // well as any code above the loop. + Succ = ConditionBlock; + // Process the loop body. { assert (W->getBody()); - SaveAndRestore sv(Block); - Succ = ConditionBlock; + // Save the current values for Block, Succ, and ContinueTargetBlock + SaveAndRestore save_Block(Block), save_Succ(Succ), + save_continue(ContinueTargetBlock); + + // All continues within this loop should go to the condition block + ContinueTargetBlock = ConditionBlock; + + // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; + CFGBlock* BodyBlock = Visit(W->getBody()); - assert (BodyBlock); ConditionBlock->addSuccessor(BodyBlock); @@ -388,11 +409,26 @@ public: // since we loop back to this block. NULL out Block to force // lazy creation of another block. Block = NULL; - Succ = ConditionBlock; return ConditionBlock; } + CFGBlock* VisitContinueStmt(ContinueStmt* C) { + // While is a control-flow statement. Thus we stop processing the + // current block. + if (Block) FinishBlock(Block); + + // Now create a new block that ends with the continue statement. + Block = createBlock(false); + Block->setTerminator(C); + + // FIXME: We should gracefully handle continues without resolved targets. + assert (ContinueTargetBlock); + + Block->addSuccessor(ContinueTargetBlock); + return Block; + } + }; // BuildCFG - A helper function that builds CFGs from ASTS.