diff --git a/clang/include/clang/AST/CFG.h b/clang/include/clang/AST/CFG.h index 0b179f9edfef..7a9ee01d4f62 100644 --- a/clang/include/clang/AST/CFG.h +++ b/clang/include/clang/AST/CFG.h @@ -61,12 +61,17 @@ class CFGBlock { /// Label - An (optional) label that prefixes the executable /// statements in the block. When this variable is non-NULL, it is /// either an instance of LabelStmt or SwitchCase. - Stmt* Label; + Stmt *Label; /// Terminator - The terminator for a basic block that /// indicates the type of control-flow that occurs between a block /// and its successors. - Stmt* Terminator; + Stmt *Terminator; + + /// LoopTarget - Some blocks are used to represent the "loop edge" to + /// the start of a loop from within the loop body. This Stmt* will be + /// refer to the loop statement for such blocks (and be null otherwise). + const Stmt *LoopTarget; /// BlockID - A numerical ID assigned to a CFGBlock during construction /// of the CFG. @@ -80,7 +85,7 @@ class CFGBlock { public: explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL), - BlockID(blockid) {} + LoopTarget(NULL), BlockID(blockid) {} ~CFGBlock() {}; // Statement iterators @@ -149,6 +154,7 @@ public: void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); } void setTerminator(Stmt* Statement) { Terminator = Statement; } void setLabel(Stmt* Statement) { Label = Statement; } + void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } Stmt* getTerminator() { return Terminator; } const Stmt* getTerminator() const { return Terminator; } @@ -159,6 +165,8 @@ public: return const_cast(this)->getTerminatorCondition(); } + const Stmt *getLoopTarget() const { return LoopTarget; } + bool hasBinaryBranchTerminator() const; Stmt* getLabel() { return Label; } diff --git a/clang/lib/AST/CFG.cpp b/clang/lib/AST/CFG.cpp index 14c93f398e89..00f5960e11fa 100644 --- a/clang/lib/AST/CFG.cpp +++ b/clang/lib/AST/CFG.cpp @@ -752,21 +752,27 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // Generate increment code in its own basic block. This is the target // of continue statements. Succ = Visit(I); - - // Finish up the increment block if it hasn't been already. - if (Block) { - assert (Block == Succ); - FinishBlock(Block); - Block = 0; - } - - ContinueTargetBlock = Succ; } else { - // No increment code. Continues should go the the entry condition block. - ContinueTargetBlock = EntryConditionBlock; + // No increment code. Create a special, empty, block that is used as + // the target block for "looping back" to the start of the loop. + assert(Succ == EntryConditionBlock); + Succ = createBlock(); } + // Finish up the increment (or empty) block if it hasn't been already. + if (Block) { + assert(Block == Succ); + FinishBlock(Block); + Block = 0; + } + + ContinueTargetBlock = Succ; + + // The starting block for the loop increment is the block that should + // represent the 'loop target' for looping back to the start of the loop. + ContinueTargetBlock->setLoopTarget(F); + // All breaks should go to the code following the loop. BreakTargetBlock = LoopSuccessor;