/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java
Java | 1397 lines | 1319 code | 75 blank | 3 comment | 4 complexity | d275fb7cc3e80c95a7d4c36334e58b93 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
- package com.google.gwt.dev.jjs.impl.gflow.cfg;
- import com.google.gwt.core.ext.UnableToCompleteException;
- import com.google.gwt.dev.jjs.ast.JMethodBody;
- import com.google.gwt.dev.jjs.ast.JProgram;
- import com.google.gwt.dev.jjs.impl.OptimizerTestBase;
- import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgBuilder;
- import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgEdge;
- import com.google.gwt.dev.jjs.impl.gflow.cfg.Cfg;
- import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgNode;
- import com.google.gwt.dev.util.Strings;
- import java.util.List;
- /**
- * Test class for CfgBuilfer.
- */
- public class CfgBuilderTest extends OptimizerTestBase {
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- addSnippetClassDecl("static boolean b;");
- addSnippetClassDecl("static boolean b1;");
- addSnippetClassDecl("static boolean b2;");
- addSnippetClassDecl("static boolean b3;");
- addSnippetClassDecl("static int i;");
- addSnippetClassDecl("static int j;");
- addSnippetClassDecl("static int k;");
- addSnippetClassDecl("static int l;");
- addSnippetClassDecl("static int m;");
- addSnippetClassDecl("static class CheckedException extends Exception {}");
- addSnippetClassDecl(
- "static class UncheckedException1 extends RuntimeException {}");
- addSnippetClassDecl(
- "static class UncheckedException2 extends RuntimeException {}");
- addSnippetClassDecl("static RuntimeException runtimeException;");
- addSnippetClassDecl("static CheckedException checkedException;");
- addSnippetClassDecl("static UncheckedException1 uncheckedException1;");
- addSnippetClassDecl("static UncheckedException2 uncheckedException2;");
- addSnippetClassDecl("static int[] ii;");
- addSnippetClassDecl("static int[] jj;");
- addSnippetClassDecl("static void throwCheckedException() " +
- "throws CheckedException {}");
- addSnippetClassDecl("static void throwUncheckedException() {}");
- addSnippetClassDecl("static void throwSeveralExceptions() " +
- "throws CheckedException, UncheckedException1 {}");
- addSnippetClassDecl("static class Foo { int i; int j; int k; }");
- addSnippetClassDecl("static Foo createFoo() {return null;}");
- }
-
- public void testConstantAssignment() throws Exception {
- assertCfg("void", "i = 1;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "END");
- }
- public void testReferenceAssignment() throws Exception {
- assertCfg("void", "i = j;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "WRITE(i, EntryPoint.j) -> [*]",
- "END");
- }
- public void testModAssignment() throws Exception {
- assertCfg("void", "i += 1;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "END");
- }
- public void testDeclarationWithInitializer() throws Exception {
- assertCfg("void", "int i = 1;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "END");
- }
- public void testDeclarationWithInitializerRead() throws Exception {
- assertCfg("void", "int i = j + k;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "READ(k) -> [*]",
- "WRITE(i, EntryPoint.j + EntryPoint.k) -> [*]",
- "END");
- }
- public void testDeclarationWithoutInitializer() throws Exception {
- assertCfg("void", "int i;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "END");
- }
- public void testBinopAssignment() throws Exception {
- assertCfg("void", "i = j + k;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "READ(k) -> [*]",
- "WRITE(i, EntryPoint.j + EntryPoint.k) -> [*]",
- "END");
- }
- public void testPostIncrement() throws Exception {
- assertCfg("void", "i++;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "END");
- }
-
- public void testPreIncrement() throws Exception {
- assertCfg("void", "++i;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "END");
- }
- public void testConditional() throws Exception {
- assertCfg("void", "i = b1 ? j : k;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "READ(j) -> [2]",
- "1: READ(k) -> [*]",
- "2: WRITE(i, EntryPoint.b1 ? EntryPoint.j : EntryPoint.k) -> [*]",
- "END");
- }
-
- public void testAnd() throws Exception {
- assertCfg("void", "b3 = b1 && b2;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "READ(b2) -> [*]",
- "1: WRITE(b3, EntryPoint.b1 && EntryPoint.b2) -> [*]",
- "END");
- }
-
- public void testOr() throws Exception {
- assertCfg("void", "b3 = b1 || b2;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [ELSE=*, THEN=1]",
- "READ(b2) -> [*]",
- "1: WRITE(b3, EntryPoint.b1 || EntryPoint.b2) -> [*]",
- "END");
- }
- public void testMultipleExpressionStatements() throws Exception {
- assertCfg("void",
- "i = 1;",
- "j = 2;",
- "m = k = j;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "WRITE(k, EntryPoint.j) -> [*]",
- "WRITE(m, EntryPoint.k = EntryPoint.j) -> [*]",
- "END");
- }
- public void testIfStatement1() throws Exception {
- assertCfg("void",
- "if (i == 1) {",
- " j = 2;",
- "}",
- "k = j;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "1: STMT -> [*]",
- "READ(j) -> [*]",
- "WRITE(k, EntryPoint.j) -> [*]",
- "END");
- }
- public void testIfStatement2() throws Exception {
- assertCfg("void",
- "if ((i = 1) == 2) {",
- " j = 2;",
- "} else {",
- " k = j;",
- "}").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "COND ((EntryPoint.i = 1) == 2) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [2]",
- "1: BLOCK -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "WRITE(k, EntryPoint.j) -> [*]",
- "2: END");
- }
-
- public void testIfStatement3() throws Exception {
- assertCfg("void", "if (b1 || b2) {j = 2;}").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [ELSE=*, THEN=1]",
- "READ(b2) -> [*]",
- "1: COND (EntryPoint.b1 || EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "2: END");
- }
- public void testWhileStatement() throws Exception {
- assertCfg("void", "while (i == 1) {j = 2;} k = j;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(i) -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [1]",
- "2: STMT -> [*]",
- "READ(j) -> [*]",
- "WRITE(k, EntryPoint.j) -> [*]",
- "END");
- }
-
- public void testDoStatement() throws Exception {
- assertCfg("void", "do { j = 2; } while (i == 1);").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "READ(i) -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=1, ELSE=*]",
- "END");
- }
-
- public void testReturn1() throws Exception {
- assertCfg("void", "return;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "END");
- }
-
- public void testReturn2() throws Exception {
- assertCfg("boolean", "i = 1; return i == 2;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "END");
- }
- public void testReturn3() throws Exception {
- assertCfg("boolean",
- "i = 1;",
- "if (i == 1) {",
- " i = 2;",
- " return true;",
- "} else {",
- " i = 3;",
- " return false;",
- "}").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 2) -> [*]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "1: BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 3) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "2: END");
- }
- public void testForStatement() throws Exception {
- assertCfg("int",
- "int j = 0;",
- "for (int i = 0; i < 10; ++i) { j++; }",
- "return j;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(j, 0) -> [*]",
- "STMT -> [*]",
- "STMT -> [*]",
- "WRITE(i, 0) -> [*]",
- "1: READ(i) -> [*]",
- "COND (i < 10) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "2: STMT -> [*]",
- "READ(j) -> [*]",
- "GOTO -> [*]",
- "END");
- }
-
- public void testEmptyForStatement() throws Exception {
- assertCfg("void",
- "for (;;) { j++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [1]",
- "END");
- }
-
- public void testThrowWithoutCatch1() throws Exception {
- assertCfg("void", "throw runtimeException;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(runtimeException) -> [*]",
- "THROW -> [*]",
- "END");
- }
-
- public void testThrowWithoutCatch2() throws Exception {
- assertCfg("void", "if (b1) { throw runtimeException; } b1 = true;").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(runtimeException) -> [*]",
- "THROW -> [2]",
- "1: STMT -> [*]",
- "WRITE(b1, true) -> [*]",
- "2: END"
- );
- }
- public void testWhileContinueNoLabel() throws Exception {
- assertCfg("void", "while (b1) { if (b2) { continue; } i++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [1]",
- "2: STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "3: END");
- }
- public void testWhileContinueWithLabel1() throws Exception {
- assertCfg("void",
- "nextLoop: while(b3)",
- " while (b1) {",
- " if (b2) { continue; }",
- " i++;" +
- " }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b3) -> [*]",
- "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
- "2: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "3: STMT -> [*]",
- "READWRITE(i, null) -> [2]",
- "4: END");
- }
- public void testWhileContinueWithLabel2() throws Exception {
- assertCfg("void",
- "nextLoop: while(b3)",
- " while (b1) {",
- " if (b2) { continue nextLoop; }",
- " i++;",
- " }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b3) -> [*]",
- "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
- "2: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [1]",
- "3: STMT -> [*]",
- "READWRITE(i, null) -> [2]",
- "4: END");
- }
- public void testWhileContinueWithLabel3() throws Exception {
- assertCfg("void",
- "nextLoop: while (b1) {",
- " if (b2) { continue; }",
- " i++;",
- "}").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [1]",
- "2: STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "3: END");
- }
- public void testWhileBreakNoLabel() throws Exception {
- assertCfg("void", "while (b1) { if (b2) { break; } i++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [3]",
- "2: STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "3: END");
- }
- public void testWhileBreakWithLabel1() throws Exception {
- assertCfg("void",
- "nextLoop: while(b3)",
- " while (b1) {",
- " if (b2) { break; }",
- " i++;",
- " }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b3) -> [*]",
- "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
- "2: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [1]",
- "3: STMT -> [*]",
- "READWRITE(i, null) -> [2]",
- "4: END");
- }
- public void testWhileBreakWithLabel2() throws Exception {
- assertCfg("void",
- "nextLoop: while(b3)",
- " while (b1) {",
- " if (b2) { break nextLoop; }",
- " i++;",
- " }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b3) -> [*]",
- "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
- "2: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [4]",
- "3: STMT -> [*]",
- "READWRITE(i, null) -> [2]",
- "4: END");
- }
-
- public void testWhileBreakWithLabel3() throws Exception {
- assertCfg("void",
- "nextLoop: while (b1) { if (b2) { break; } i++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b1) -> [*]",
- "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [3]",
- "2: STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "3: END");
- }
-
- public void testForContinueNoLabel() throws Exception {
- assertCfg("void",
- "for(int i = 0; i < 10; i++) { if (b2) { continue; } i++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "STMT -> [*]",
- "WRITE(i, 0) -> [*]",
- "1: READ(i) -> [*]",
- "COND (i < 10) -> [THEN=*, ELSE=4]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b2) -> [*]",
- "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [3]",
- "2: STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: STMT -> [*]",
- "READWRITE(i, null) -> [1]",
- "4: END");
- }
-
- public void testCatchThrowException1() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw checkedException;",
- " k++;",
- "} catch (CheckedException e) {",
- " i++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(checkedException) -> [*]",
- "THROW -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "END"
- );
- }
- public void testCatchThrowUncatchedException() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw uncheckedException2;",
- " k++;",
- "} catch (UncheckedException1 e) {",
- " i++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(uncheckedException2) -> [*]",
- "THROW -> [3]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "2: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "3: END"
- );
- }
- public void testCatchThrowSupertype() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw runtimeException;",
- " k++;",
- "} catch (UncheckedException1 e) {",
- " i++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(runtimeException) -> [*]",
- "THROW -> [2, 4]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "4: END"
- );
- }
- public void testCatchSupertype() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw uncheckedException1;",
- " k++;",
- "} catch (RuntimeException e) {",
- " i++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(uncheckedException1) -> [*]",
- "THROW -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "END"
- );
- }
- public void testCatchReturn() throws Exception {
- assertCfg("void",
- "try { try {",
- " if (b) return;",
- " k++;",
- "} catch (RuntimeException e) {",
- " i++;",
- "} } catch (UncheckedException1 e) { j++; }").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "2: END"
- );
- }
- public void testRethrow() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw uncheckedException1;",
- " k++;",
- "} catch (UncheckedException1 e) {",
- " i++;",
- " throw e;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(uncheckedException1) -> [*]",
- "THROW -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "STMT -> [*]",
- "READ(e) -> [*]",
- "THROW -> [4]",
- "3: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "4: END"
- );
- }
- public void testCatchMethodCall1() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throwCheckedException();",
- " k++;",
- "} catch (CheckedException e) {",
- " i++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "OPTTHROW(throwCheckedException()) -> [NOTHROW=*, 2, RE=4]",
- "CALL(throwCheckedException) -> [*]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "4: END"
- );
- }
- public void testCatchMethodCall2() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throwCheckedException();",
- " k++;",
- "} catch (CheckedException e) {",
- " i++;",
- "} catch (RuntimeException e) {",
- " l++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "OPTTHROW(throwCheckedException()) -> [NOTHROW=*, 2, RE=3]",
- "CALL(throwCheckedException) -> [*]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [4]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [4]",
- "3: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(l, null) -> [*]",
- "4: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "END"
- );
- }
- public void testCatchMethodCallUnchecked() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throwUncheckedException();",
- " k++;",
- "} catch (UncheckedException1 e) {",
- " i++;",
- "} catch (RuntimeException e) {",
- " l++;",
- "}",
- "j++;").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "OPTTHROW(throwUncheckedException()) -> [NOTHROW=*, RE=2, RE=3]",
- "CALL(throwUncheckedException) -> [*]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [4]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [4]",
- "3: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(l, null) -> [*]",
- "4: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "END"
- );
- }
- public void testFinallyReturn1() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) return;",
- " j++;",
- "} finally {",
- " i++;",
- "}").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "1: STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*, *]",
- "END"
- );
- }
- public void testThrowFromFinally() throws Exception {
- assertCfg("void",
- "try {",
- " return;",
- "} finally {",
- " throw runtimeException;",
- "}").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(runtimeException) -> [*]",
- "THROW -> [*]",
- "END"
- );
- }
- public void testFinallyReturn2() throws Exception {
- assertCfg("void",
- "try {",
- " return;",
- "} finally {",
- " i++;",
- "}").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*, *]",
- "END"
- );
- }
- public void testFinallyReturn3() throws Exception {
- assertCfg("void",
- "try {",
- "try {",
- " if (b) return;",
- " k++;",
- "} finally {",
- " i++;",
- "} m++; } finally {",
- " j++;",
- "}").is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [*]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*, 3]",
- "STMT -> [*]",
- "READWRITE(m, null) -> [*]",
- "3: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [*, *]",
- "END"
- );
- }
- public void testFinallyContinue() throws Exception {
- assertCfg("void",
- "while (b) {",
- "try {",
- " if (b) continue;",
- "} finally {",
- " i++;",
- "} j++; }").is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "1: READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=3]",
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=2]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*, 1]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [1]",
- "3: END"
- );
- }
- public void testCatchFinally() throws Exception {
- assertCfg("void",
- "try {",
- " if (b) throw checkedException;",
- " k++;",
- "} catch (CheckedException e) {",
- " i++;",
- "} finally {",
- " j++;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "TRY -> [*]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "READ(checkedException) -> [*]",
- "THROW -> [2]",
- "1: STMT -> [*]",
- "READWRITE(k, null) -> [3]",
- "2: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(i, null) -> [*]",
- "3: BLOCK -> [*]",
- "STMT -> [*]",
- "READWRITE(j, null) -> [*]",
- "END"
- );
- }
- public void testFieldWrite() throws Exception {
- assertCfg("void",
- "Foo foo = createFoo();",
- "foo.i = 1;"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "OPTTHROW(createFoo()) -> [NOTHROW=*, RE=1]",
- "CALL(createFoo) -> [*]",
- "WRITE(foo, EntryPoint.createFoo()) -> [*]",
- "STMT -> [*]",
- "READ(foo) -> [*]",
- "WRITE(i, 1) -> [*]",
- "1: END"
- );
- }
- public void testFieldUnary() throws Exception {
- assertCfg("void",
- "Foo foo = createFoo();",
- "++foo.i;"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "OPTTHROW(createFoo()) -> [NOTHROW=*, RE=1]",
- "CALL(createFoo) -> [*]",
- "WRITE(foo, EntryPoint.createFoo()) -> [*]",
- "STMT -> [*]",
- "READ(foo) -> [*]",
- "READWRITE(i, null) -> [*]",
- "1: END"
- );
- }
- public void testArrayRead() throws Exception {
- assertCfg("void",
- "i = ii[j];"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(ii) -> [*]",
- "READ(j) -> [*]",
- "WRITE(i, EntryPoint.ii[EntryPoint.j]) -> [*]",
- "END"
- );
- }
- public void testArrayWrite() throws Exception {
- assertCfg("void",
- "ii[i] = j;"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "READ(ii) -> [*]",
- "READ(i) -> [*]",
- "WRITE(EntryPoint.ii[EntryPoint.i], EntryPoint.j) -> [*]",
- "END"
- );
- }
- public void testArrayUnary() throws Exception {
- assertCfg("void",
- "++ii[i];"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(ii) -> [*]",
- "READ(i) -> [*]",
- "READWRITE(EntryPoint.ii[EntryPoint.i], null) -> [*]",
- "END"
- );
- }
- public void testSwitch() throws Exception {
- assertCfg("void",
- "switch(i) {",
- " case 1: ",
- " return;",
- " case 2: ",
- " case 3: ",
- " j = 1;",
- " break;",
- " case 4: ",
- " j = 2;",
- " default:",
- " j = 4;",
- " case 5: ",
- " j = 3;",
- " break;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "GOTO -> [7]",
- "1: STMT -> [*]",
- "COND (EntryPoint.i == 2) -> [ELSE=*, THEN=2]",
- "STMT -> [*]",
- "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=3]",
- "2: STMT -> [*]",
- "WRITE(j, 1) -> [*]",
- "STMT -> [*]",
- "GOTO -> [7]",
- "3: STMT -> [*]",
- "COND (EntryPoint.i == 4) -> [THEN=*, ELSE=5]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "4: STMT -> [*]",
- "STMT -> [*]",
- "WRITE(j, 4) -> [6]",
- "5: STMT -> [*]",
- "COND (EntryPoint.i == 5) -> [THEN=*, ELSE=4]",
- "6: STMT -> [*]",
- "WRITE(j, 3) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "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) {",
- " default: j = 1; return;",
- " case 1: j = 2; return;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [2]",
- "1: STMT -> [*]",
- "STMT -> [*]",
- "WRITE(j, 1) -> [*]",
- "STMT -> [*]",
- "GOTO -> [3]",
- "2: STMT -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "WRITE(j, 2) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "3: END"
- );
- }
-
- public void testSwitch_Empty() throws Exception {
- assertCfg("void",
- "switch(i) {",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "END"
- );
- }
- public void testSwitch_OnlyDefault() throws Exception {
- assertCfg("void",
- "switch(i) {",
- " default: j = 0; return;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "STMT -> [*]",
- "WRITE(j, 0) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "END"
- );
- }
- public void testNestedSwitch() throws Exception {
- assertCfg("void",
- "switch(i) {",
- " case 1: ",
- " switch (j) {",
- " case 0: k = 1; break;",
- " case 1: k = 2; break;",
- " }",
- " break;",
- " case 2: ",
- " switch (j) {",
- " case 0: k = 3; break;",
- " case 1: k = 4; break;",
- " }",
- " break;",
- " case 3: ",
- " switch (j) {",
- " case 0: k = 5; break;",
- " case 1: k = 6; break;",
- " }",
- " break;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=3]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "WRITE(k, 1) -> [*]",
- "STMT -> [*]",
- "GOTO -> [2]",
- "1: STMT -> [*]",
- "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=2]",
- "STMT -> [*]",
- "WRITE(k, 2) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "2: STMT -> [*]",
- "GOTO -> [9]",
- "3: STMT -> [*]",
- "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=6]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=4]",
- "STMT -> [*]",
- "WRITE(k, 3) -> [*]",
- "STMT -> [*]",
- "GOTO -> [5]",
- "4: STMT -> [*]",
- "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=5]",
- "STMT -> [*]",
- "WRITE(k, 4) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "5: STMT -> [*]",
- "GOTO -> [9]",
- "6: STMT -> [*]",
- "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=9]",
- "STMT -> [*]",
- "READ(j) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=7]",
- "STMT -> [*]",
- "WRITE(k, 5) -> [*]",
- "STMT -> [*]",
- "GOTO -> [8]",
- "7: STMT -> [*]",
- "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=8]",
- "STMT -> [*]",
- "WRITE(k, 6) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "8: STMT -> [*]",
- "GOTO -> [*]",
- "9: END"
- );
- }
- public void testSwitchWithLoopAndBreak() throws Exception {
- assertCfg("void",
- "switch(i) {",
- " case 1: ",
- " i = 1;" +
- " break;",
- " case 2: ",
- " while (b) { i = 2; break; }",
- " j = 3;",
- "}"
- ).is(
- "BLOCK -> [*]",
- "STMT -> [*]",
- "READ(i) -> [*]",
- "GOTO -> [*]",
- "STMT -> [*]",
- "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
- "STMT -> [*]",
- "WRITE(i, 1) -> [*]",
- "STMT -> [*]",
- "GOTO -> [3]",
- "1: STMT -> [*]",
- "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=3]",
- "STMT -> [*]",
- "READ(b) -> [*]",
- "COND (EntryPoint.b) -> [THEN=*, ELSE=2]",
- "BLOCK -> [*]",
- "STMT -> [*]",
- "WRITE(i, 2) -> [*]",
- "STMT -> [*]",
- "GOTO -> [*]",
- "2: STMT -> [*]",
- "WRITE(j, 3) -> [*]",
- "3: END"
- );
- }
- private CfgBuilderResult assertCfg(String returnType, String ...codeSnippet)
- throws UnableToCompleteException {
- JProgram program = compileSnippet(returnType,
- Strings.join(codeSnippet, "\n"));
- JMethodBody body = (JMethodBody) findMainMethod(program).getBody();
- Cfg cfgGraph = CfgBuilder.build(program, body.getBlock());
- return new CfgBuilderResult(cfgGraph);
- }
- static class CfgBuilderResult {
- private final Cfg cfg;
- public CfgBuilderResult(Cfg cfgGraph) {
- assertNotNull("Can't build cfg", cfgGraph);
- this.cfg = cfgGraph;
- validateGraph();
- }
- private void validateGraph() {
- for (CfgNode<?> node : cfg.getNodes()) {
- List<CfgEdge> incomingEdges = cfg.getInEdges(node);
- for (CfgEdge e : incomingEdges) {
- CfgNode<?> start = e.getStart();
- if (cfg.getGraphInEdges().contains(e)) {
- assertNull(start);
- continue;
- }
- assertNotNull("No start in edge " + e.getRole() + " to " + node,
- start);
- assertTrue(start + " doesn't have outgoing edge to " + node,
- cfg.getOutEdges(start).contains(e));
- }
- List<CfgEdge> outcomingEdges = cfg.getOutEdges(node);
- for (CfgEdge e : outcomingEdges) {
- CfgNode<?> end = e.getEnd();
- assertNotNull("No end in edge " + e.getRole() + " from " + node, end);
- assertTrue(end + " doesn't have incoming edge from " + node,
- cfg.getInEdges(end).contains(e));
- }
- }
- }
- public void is(String... expected) {
- assertEquals(Strings.join(expected, "\n"), cfg.print());
- }
- }
- }