CFG: fixing case fallthrough.
Review at http://gwt-code-reviews.appspot.com/434801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8041 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 8be2b1b..6cd1087 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
@@ -622,6 +622,7 @@
int defaultPos = -1;
List<Exit> breakExits = new ArrayList<Exit>();
+ List<Exit> fallThroughExits = new ArrayList<Exit>();
List<JStatement> statements = x.getBody().getStatements();
@@ -629,6 +630,8 @@
if (s instanceof JCaseStatement) {
if (((JCaseStatement) s).getExpr() != null) {
// case label
+
+ fallThroughExits.addAll(removeExits(Exit.Reason.NORMAL));
if (gotoExit != null) {
// This is first non-default case.
addExit(gotoExit);
@@ -647,6 +650,12 @@
for (Exit e : thenExits) {
addNormalExit(e.getNode(), e.role);
}
+ if (!fallThroughExits.isEmpty()) {
+ for (Exit e : fallThroughExits) {
+ addExit(e);
+ }
+ fallThroughExits.clear();
+ }
}
accept(s);
breakExits.addAll(removeExits(Exit.Reason.BREAK));
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 82c0b37..ffdc7ca 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
@@ -1109,7 +1109,7 @@
"STMT -> [*]",
"COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
"STMT -> [*]",
- "GOTO -> [6]",
+ "GOTO -> [7]",
"1: STMT -> [*]",
"COND (EntryPoint.i == 2) -> [ELSE=*, THEN=2]",
"STMT -> [*]",
@@ -1117,24 +1117,54 @@
"2: STMT -> [*]",
"WRITE(j, 1) -> [*]",
"STMT -> [*]",
- "GOTO -> [6]",
+ "GOTO -> [7]",
"3: STMT -> [*]",
"COND (EntryPoint.i == 4) -> [THEN=*, ELSE=5]",
"STMT -> [*]",
"WRITE(j, 2) -> [*]",
"4: STMT -> [*]",
"STMT -> [*]",
- "WRITE(j, 4) -> [*]",
+ "WRITE(j, 4) -> [6]",
"5: STMT -> [*]",
"COND (EntryPoint.i == 5) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
+ "6: STMT -> [*]",
"WRITE(j, 3) -> [*]",
"STMT -> [*]",
"GOTO -> [*]",
- "6: END"
+ "7: END"
);
}
+ public void testSwitch_FallThrough() throws Exception {
+ assertCfg("void",
+ "switch(i) {",
+ " case 1: ",
+ " j = 1;",
+ " case 2: ",
+ " j = 2;",
+ " case 3: ",
+ " j = 3;",
+ "}"
+ ).is(
+ "BLOCK -> [*]",
+ "STMT -> [*]",
+ "READ(i) -> [*]",
+ "GOTO -> [*]",
+ "STMT -> [*]",
+ "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
+ "STMT -> [*]",
+ "WRITE(j, 1) -> [2]",
+ "1: STMT -> [*]",
+ "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=3]",
+ "2: STMT -> [*]",
+ "WRITE(j, 2) -> [4]",
+ "3: STMT -> [*]",
+ "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=5]",
+ "4: STMT -> [*]",
+ "WRITE(j, 3) -> [*]",
+ "5: END");
+ }
+
public void testSwitch_FirstDefault() throws Exception {
assertCfg("void",
"switch(i) {",