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) {",