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