From: Ted Kremenek Date: Wed, 22 Aug 2007 22:35:28 +0000 (+0000) Subject: Fixed bugs in source-level CFG construction for "for" and "while" loops X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=31dcd3c8c4df5a656f58f50ea73afc177c101c67;p=clang Fixed bugs in source-level CFG construction for "for" and "while" loops where break targets weren't being set and restored properly. Also cleaned up CFGBuilder code for "for" and "while" to use less reliance on globals and to have clearer semantics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41302 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/CFG.cpp b/AST/CFG.cpp index eb358281ef..3537a9a878 100644 --- a/AST/CFG.cpp +++ b/AST/CFG.cpp @@ -310,22 +310,21 @@ public: } CFGBlock* VisitForStmt(ForStmt* F) { - // For is a control-flow statement. Thus we stop processing the + // "for" is a control-flow statement. Thus we stop processing the // current block. - if (Block) FinishBlock(Block); - // Besides the loop body, we actually create two new blocks: - // - // The first contains the initialization statement for the loop. - // - // The second block evaluates the loop condition. - // - // We create the initialization block last, as that will be the block - // we return for the recursion. + CFGBlock* LoopSuccessor = NULL; + if (Block) { + FinishBlock(Block); + LoopSuccessor = Block; + } + else LoopSuccessor = Succ; + + // Create the condition block. CFGBlock* ConditionBlock = createBlock(false); - if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C); ConditionBlock->setTerminator(F); + if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C); // The condition block is the implicit successor for the loop body as // well as any code above the loop. @@ -335,18 +334,18 @@ public: { assert (F->getBody()); - // Save the current values for Block, Succ, and ContinueTargetBlock + // Save the current values for Block, Succ, and continue and break targets SaveAndRestore save_Block(Block), save_Succ(Succ), - save_continue(ContinueTargetBlock), - save_break(BreakTargetBlock); - + save_continue(ContinueTargetBlock), + save_break(BreakTargetBlock); + // All continues within this loop should go to the condition block ContinueTargetBlock = ConditionBlock; - // All breaks should go to the code that follows the loop. - BreakTargetBlock = Block; + // All breaks should go to the code following the loop. + BreakTargetBlock = LoopSuccessor; - // create a new block to contain the body. + // Create a new block to contain the (bottom) of the loop body. Block = createBlock(); // If we have increment code, insert it at the end of the body block. @@ -354,35 +353,50 @@ public: // Now populate the body block, and in the process create new blocks // as we walk the body of the loop. - CFGBlock* BodyBlock = Visit(F->getBody()); - + CFGBlock* BodyBlock = Visit(F->getBody()); assert (BodyBlock); FinishBlock(BodyBlock); // This new body block is a successor to our condition block. ConditionBlock->addSuccessor(BodyBlock); } - + // Link up the condition block with the code that follows the loop. // (the false branch). - ConditionBlock->addSuccessor(Block); + ConditionBlock->addSuccessor(LoopSuccessor); - // Now create the block to contain the initialization. - Block = createBlock(); - - if (Stmt* I = F->getInit()) Block->appendStmt(I); - return Block; + // If the loop contains initialization, create a new block for those + // statements. This block can also contain statements that precede + // the loop. + if (Stmt* I = F->getInit()) { + Block = createBlock(); + Block->appendStmt(I); + return Block; + } + else { + // There is no loop initialization. We are thus basically a while + // loop. NULL out Block to force lazy block construction. + Block = NULL; + return ConditionBlock; + } } CFGBlock* VisitWhileStmt(WhileStmt* W) { - // While is a control-flow statement. Thus we stop processing the + // "while" is a control-flow statement. Thus we stop processing the // current block. - if (Block) FinishBlock(Block); + + CFGBlock* LoopSuccessor = NULL; + + if (Block) { + FinishBlock(Block); + LoopSuccessor = Block; + } + else LoopSuccessor = Succ; // Create the condition block. CFGBlock* ConditionBlock = createBlock(false); ConditionBlock->setTerminator(W); - if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C); + 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. @@ -391,36 +405,40 @@ public: // Process the loop body. { assert (W->getBody()); - - // Save the current values for Block, Succ, and ContinueTargetBlock + + // Save the current values for Block, Succ, and continue and break targets SaveAndRestore save_Block(Block), save_Succ(Succ), save_continue(ContinueTargetBlock), save_break(BreakTargetBlock); - + // All continues within this loop should go to the condition block ContinueTargetBlock = ConditionBlock; - // All breaks should go to the code that follows the loop. - BreakTargetBlock = Block; + // All breaks should go to the code following the loop. + BreakTargetBlock = LoopSuccessor; // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; + // Create the body. The returned block is the entry to the loop body. CFGBlock* BodyBlock = Visit(W->getBody()); assert (BodyBlock); + FinishBlock(BodyBlock); + // Add the loop body entry as a successor to the condition. ConditionBlock->addSuccessor(BodyBlock); } // Link up the condition block with the code that follows the loop. // (the false branch). - ConditionBlock->addSuccessor(Block); + ConditionBlock->addSuccessor(LoopSuccessor); // There can be no more statements in the condition block // since we loop back to this block. NULL out Block to force // lazy creation of another block. Block = NULL; + // Return the condition block, which is the dominating block for the loop. return ConditionBlock; }