From 3f64a0e3be2c9408f8256bd3aa9f0ce9e268982c Mon Sep 17 00:00:00 2001 From: Ted Kremenek <kremenek@apple.com> Date: Fri, 21 May 2010 20:30:15 +0000 Subject: [PATCH] Fix crash in CFG construction for 'break' statements appearing in statement expressions within the increment code of a for loop. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104375 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CFG.cpp | 15 ++++++++------- test/Analysis/dead-stores.c | 12 ++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index c7eb53d3613..6f2cb41a6e4 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -985,6 +985,11 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { } else LoopSuccessor = Succ; + // Save the current value for the break targets. + // All breaks should go to the code following the loop. + SaveAndRestore<CFGBlock*> save_break(BreakTargetBlock); + BreakTargetBlock = LoopSuccessor; + // Because of short-circuit evaluation, the condition of the loop can span // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that // evaluate the condition. @@ -1032,10 +1037,9 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { { assert(F->getBody()); - // Save the current values for Block, Succ, and continue and break targets - SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ), - save_continue(ContinueTargetBlock), - save_break(BreakTargetBlock); + // Save the current values for Block, Succ, and continue targets. + SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ), + save_continue(ContinueTargetBlock); // Create a new block to contain the (bottom) of the loop body. Block = NULL; @@ -1065,9 +1069,6 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // 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; - // Now populate the body block, and in the process create new blocks as we // walk the body of the loop. CFGBlock* BodyBlock = addStmt(F->getBody()); diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c index 209ca6531cc..1c600276ba4 100644 --- a/test/Analysis/dead-stores.c +++ b/test/Analysis/dead-stores.c @@ -450,3 +450,15 @@ int f26_nestedblocks() { return y; } +// The FOREACH macro in QT uses 'break' statements within statement expressions +// placed within the increment code of for loops. +void rdar8014335() { + for (int i = 0 ; i != 10 ; ({ break; })) { + for ( ; ; ({ ++i; break; })) ; + // Note that the next value stored to 'i' is never executed + // because the next statement to be executed is the 'break' + // in the increment code of the first loop. + i = i * 3; // expected-warning{{Value stored to 'i' is never read}} + } +} + -- GitLab