Fixing CFG handling of labelled breaks inside the switch.

Review by: spoon@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8388 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
index 0e2c9a0..6e135c2 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilder.java
@@ -627,7 +627,7 @@
       // We don't want to mess with other case exits here
       List<Exit> oldCaseElseExits = removeExits(Exit.Reason.CASE_ELSE);
       List<Exit> oldCaseThenExits = removeExits(Exit.Reason.CASE_THEN);
-      List<Exit> oldBreakExits = removeExits(Exit.Reason.BREAK);
+      List<Exit> oldBreakExits = removeUnlabeledBreaks();
       switchStatement = x;
 
       // Goto to the first non-default node.
@@ -673,7 +673,7 @@
           }
         }
         accept(s);
-        breakExits.addAll(removeExits(Exit.Reason.BREAK));
+        breakExits.addAll(removeUnlabeledBreaks());
       }
 
       if (gotoExit != null) {
@@ -1106,7 +1106,7 @@
     private List<Exit> removeExits(Exit.Reason reason) {
       return currentExitsByReason.put(reason, new ArrayList<Exit>());
     }
-
+    
     private List<Exit> removeExits(List<Exit> exits, Exit.Reason reason) {
       List<Exit> result = new ArrayList<Exit>();
       for (Iterator<Exit> i = exits.iterator(); i.hasNext();) {
@@ -1148,6 +1148,21 @@
     private List<Exit> removeNormalExits(List<Exit> exits) {
       return removeExits(exits, Exit.Reason.NORMAL);
     }
+
+    private List<Exit> removeUnlabeledBreaks() {
+      List<Exit> breakExits = removeExits(Exit.Reason.BREAK);
+      List<Exit> labeledBreaks = new ArrayList<Exit>();
+      
+      for (Iterator<Exit> i = breakExits.iterator(); i.hasNext();) {
+        Exit exit = i.next();
+        if (exit.getLabel() != null) {
+          i.remove();
+          labeledBreaks.add(exit);
+        }
+      }
+      addExits(labeledBreaks);
+      return breakExits;
+    }
   }
 
   /**
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java
index 60fadff..8e2d5c8 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java
@@ -1429,6 +1429,62 @@
             "3: END");
   }
   
+  public void testBreakLoopAndSwitch() throws Exception {
+    assertCfg("void",
+        "loop: while (b) {",
+        "  switch (i) {",
+        "    case 1: ",
+        "      if (j == 1) {",
+        "        break loop;",
+        "      }",
+        "      break;",
+        "    default: ",
+        "      return;",
+        "    case 2: ",
+        "      break loop;",
+        "    case 3: ",
+        "      break;",
+        "  }",
+        "  i++;",
+        "}",
+        "k++;"
+    ).is(
+        "BLOCK -> [*]",
+        "STMT -> [*]",
+        "1: READ(b) -> [*]",
+        "COND (EntryPoint.b) -> [THEN=*, ELSE=7]",
+        "BLOCK -> [*]",
+        "STMT -> [*]",
+        "READ(i) -> [*]",
+        "GOTO -> [*]",
+        "STMT -> [*]",
+        "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=4]",
+        "STMT -> [*]",
+        "READ(j) -> [*]",
+        "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=2]",
+        "BLOCK -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [7]",
+        "2: STMT -> [*]",
+        "GOTO -> [6]",
+        "3: STMT -> [*]",
+        "STMT -> [*]",
+        "GOTO -> [8]",
+        "4: STMT -> [*]",
+        "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=5]",
+        "STMT -> [*]",
+        "GOTO -> [7]",
+        "5: STMT -> [*]",
+        "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=3]",
+        "STMT -> [*]",
+        "GOTO -> [*]",
+        "6: STMT -> [*]",
+        "READWRITE(i, null) -> [1]",
+        "7: STMT -> [*]",
+        "READWRITE(k, null) -> [*]",
+        "8: END");
+  }
+  
   private CfgBuilderResult assertCfg(String returnType, String ...codeSnippet)
       throws UnableToCompleteException {
     JProgram program = compileSnippet(returnType,