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,