diff options
| author | Ayushman Jain | 2012-05-29 10:04:57 +0000 |
|---|---|---|
| committer | Jayaprakash Arthanareeswaran | 2013-01-02 08:24:32 +0000 |
| commit | 650d34a55f295affa1498bddd4cfe460109baef3 (patch) | |
| tree | c3adb7083943f2162b48ee29850c93d53eb92cc5 | |
| parent | f4f6ce25213802ef8d63ed0a83e5e0e2b60e306f (diff) | |
| download | eclipse.jdt.core-650d34a55f295affa1498bddd4cfe460109baef3.tar.gz eclipse.jdt.core-650d34a55f295affa1498bddd4cfe460109baef3.tar.xz eclipse.jdt.core-650d34a55f295affa1498bddd4cfe460109baef3.zip | |
Fixed bug 380313: Inconsistent stack error when using Java 1.7
4 files changed, 402 insertions, 1 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java index 32b50af3ef..2e6883fda4 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest.java @@ -2360,6 +2360,89 @@ public void testBug338234d() { "The local variable i may not have been initialized\n" + "----------\n"); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=380313 +// Verify that the code runs fine with all compliance levels. +public void testBug380313() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + "public void foo() throws Exception {\n" + + " int i = 1;\n" + + " int j = 2;\n" + + " try {\n" + + " if ((bar() == 1)) {\n" + + " if ((i == 1)) {\n" + + " int n = bar();\n" + + " if (n == 35) {\n" + + " j = 2;\n" + + " } else {\n" + + " if (bar() > 0)\n" + + " return;\n" + + " }\n" + + " } else {\n" + + " throw new Exception();\n" + + " }\n" + + " } else {\n" + + " throw new Exception();\n" + + " }\n" + + " if (bar() == 0)\n" + + " return;\n" + + " } finally {\n" + + " bar();\n" + + " }\n" + + " }\n" + + "\n" + + " private int bar() {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " }\n" + + "}\n" + }, + ""); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=380313 +// try with resources +// Verify that the code runs fine with all compliance levels. +public void testBug380313b() { + if (this.complianceLevel < ClassFileConstants.JDK1_7) + return; + this.runConformTest( + new String[] { + "X.java", + "import java.io.FileInputStream;\n" + + "import java.io.IOException;\n" + + "public class X {\n" + + "public void foo() throws Exception {\n" + + " int i = 1;\n" + + " try {\n" + + " try (FileInputStream fis = new FileInputStream(\"\")) {\n" + + " if (i == 2)" + + " return;\n" + + " }\n" + + " if (i == 35) \n" + + " return;\n" + + " } catch(IOException e) {\n" + + " bar();\n" + + " } finally {\n" + + " bar();\n" + + " }\n" + + " }\n" + + "\n" + + " private int bar() {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " }\n" + + "}\n" + }, + ""); +} public static Class testClass() { return FlowAnalysisTest.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java index 8b83af74d6..f6d4246872 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/StackMapAttributeTest.java @@ -34,7 +34,7 @@ public class StackMapAttributeTest extends AbstractRegressionTest { // All specified tests which does not belong to the class are skipped... static { // TESTS_PREFIX = "testBug95521"; -// TESTS_NAMES = new String[] { "testBug359495" }; +// TESTS_NAMES = new String[] { "testBug380313" }; // TESTS_NUMBERS = new int[] { 53 }; // TESTS_RANGE = new int[] { 23 -1,}; } @@ -7616,4 +7616,300 @@ public class StackMapAttributeTest extends AbstractRegressionTest { }, "SUCCESS"); } + + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380313 + // Verify the generated code does not have same branch target for the 2 return statements + public void testBug380313() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + "public void foo() throws Exception {\n" + + " int i = 1;\n" + + " try {\n" + + " if (i == 1) {\n" + + " int n = bar();\n" + + " if (n == 35)\n" + + " return;\n" + + " } else {\n" + + " throw new Exception();\n" + + " }\n" + + " if (i == 0)\n" + + " return;\n" + + " } finally {\n" + + " bar();\n" + + " }\n" + + " }\n" + + "\n" + + " private int bar() {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"SUCCESS\");\n" + + " }\n" + + "}\n" + }, + "SUCCESS"); + + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X.class")); + String actualOutput = + disassembler.disassemble( + classFileBytes, + "\n", + ClassFileBytesDisassembler.DETAILED); + + String expectedOutput = + " // Method descriptor #6 ()V\n" + + " // Stack: 2, Locals: 4\n" + + " public void foo() throws java.lang.Exception;\n" + + " 0 iconst_1\n" + + " 1 istore_1 [i]\n" + + " 2 iload_1 [i]\n" + + " 3 iconst_1\n" + + " 4 if_icmpne 24\n" + + " 7 aload_0 [this]\n" + + " 8 invokespecial X.bar() : int [18]\n" + + " 11 istore_2 [n]\n" + + " 12 iload_2 [n]\n" + + " 13 bipush 35\n" + + " 15 if_icmpne 32\n" + + " 18 aload_0 [this]\n" + + " 19 invokespecial X.bar() : int [18]\n" + + " 22 pop\n" + + " 23 return\n" + + " 24 new java.lang.Exception [16]\n" + + " 27 dup\n" + + " 28 invokespecial java.lang.Exception() [22]\n" + + " 31 athrow\n" + + " 32 iload_1 [i]\n" + + " 33 ifne 50\n" + + " 36 aload_0 [this]\n" + + " 37 invokespecial X.bar() : int [18]\n" + + " 40 pop\n" + + " 41 return\n" + + " 42 astore_3\n" + + " 43 aload_0 [this]\n" + + " 44 invokespecial X.bar() : int [18]\n" + + " 47 pop\n" + + " 48 aload_3\n" + + " 49 athrow\n" + + " 50 aload_0 [this]\n" + + " 51 invokespecial X.bar() : int [18]\n" + + " 54 pop\n" + + " 55 return\n" + + " Exception Table:\n" + + " [pc: 2, pc: 18] -> 42 when : any\n" + + " [pc: 24, pc: 36] -> 42 when : any\n" + + " Line numbers:\n" + + " [pc: 0, line: 3]\n" + + " [pc: 2, line: 5]\n" + + " [pc: 7, line: 6]\n" + + " [pc: 12, line: 7]\n" + + " [pc: 18, line: 15]\n" + + " [pc: 23, line: 8]\n" + + " [pc: 24, line: 10]\n" + + " [pc: 32, line: 12]\n" + + " [pc: 36, line: 15]\n" + + " [pc: 41, line: 13]\n" + + " [pc: 42, line: 14]\n" + + " [pc: 43, line: 15]\n" + + " [pc: 48, line: 16]\n" + + " [pc: 50, line: 15]\n" + + " [pc: 55, line: 17]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 56] local: this index: 0 type: X\n" + + " [pc: 2, pc: 56] local: i index: 1 type: int\n" + + " [pc: 12, pc: 24] local: n index: 2 type: int\n" + + " Stack map table: number of frames 4\n" + + " [pc: 24, append: {int}]\n" + + " [pc: 32, same]\n" + + " [pc: 42, same_locals_1_stack_item, stack: {java.lang.Throwable}]\n" + + " [pc: 50, same]\n"; + int index = actualOutput.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(actualOutput, 2)); + } + if (index == -1) { + assertEquals("Wrong contents", expectedOutput, actualOutput); + } + } + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380313 + // Verify the generated code does not have same branch target for the 2 return statements + public void testBug380313b() throws Exception { + if (this.complianceLevel < ClassFileConstants.JDK1_7) + return; + this.runConformTest( + new String[] { + "X.java", + "import java.io.FileInputStream;\n" + + "import java.io.IOException;\n" + + "public class X {\n" + + "public void foo() throws Exception {\n" + + " int i = 1;\n" + + " try {\n" + + " try (FileInputStream fis = new FileInputStream(\"\")) {\n" + + " if (i == 2)" + + " return;\n" + + " }\n" + + " if (i == 35) \n" + + " return;\n" + + " } catch(IOException e) {\n" + + " bar();\n" + + " } finally {\n" + + " bar();\n" + + " }\n" + + " }\n" + + "\n" + + " private int bar() {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " public static void main(String[] args) {\n" + + " System.out.println(\"SUCCESS\");\n" + + " }\n" + + "}\n" + }, + "SUCCESS"); + + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X.class")); + String actualOutput = + disassembler.disassemble( + classFileBytes, + "\n", + ClassFileBytesDisassembler.DETAILED); + + String expectedOutput = + " // Method descriptor #6 ()V\n" + + " // Stack: 3, Locals: 6\n" + + " public void foo() throws java.lang.Exception;\n" + + " 0 iconst_1\n" + + " 1 istore_1 [i]\n" + + " 2 aconst_null\n" + + " 3 astore_2\n" + + " 4 aconst_null\n" + + " 5 astore_3\n" + + " 6 new java.io.FileInputStream [18]\n" + + " 9 dup\n" + + " 10 ldc <String \"\"> [20]\n" + + " 12 invokespecial java.io.FileInputStream(java.lang.String) [22]\n" + + " 15 astore 4 [fis]\n" + + " 17 iload_1 [i]\n" + + " 18 iconst_2\n" + + " 19 if_icmpne 38\n" + + " 22 aload 4 [fis]\n" + + " 24 ifnull 32\n" + + " 27 aload 4 [fis]\n" + + " 29 invokevirtual java.io.FileInputStream.close() : void [25]\n" + + " 32 aload_0 [this]\n" + // return 1 + " 33 invokespecial X.bar() : int [28]\n" + + " 36 pop\n" + + " 37 return\n" + + " 38 aload 4 [fis]\n" + + " 40 ifnull 86\n" + + " 43 aload 4 [fis]\n" + + " 45 invokevirtual java.io.FileInputStream.close() : void [25]\n" + + " 48 goto 86\n" + + " 51 astore_2\n" + + " 52 aload 4 [fis]\n" + + " 54 ifnull 62\n" + + " 57 aload 4 [fis]\n" + + " 59 invokevirtual java.io.FileInputStream.close() : void [25]\n" + + " 62 aload_2\n" + + " 63 athrow\n" + + " 64 astore_3\n" + + " 65 aload_2\n" + + " 66 ifnonnull 74\n" + + " 69 aload_3\n" + + " 70 astore_2\n" + + " 71 goto 84\n" + + " 74 aload_2\n" + + " 75 aload_3\n" + + " 76 if_acmpeq 84\n" + + " 79 aload_2\n" + + " 80 aload_3\n" + + " 81 invokevirtual java.lang.Throwable.addSuppressed(java.lang.Throwable) : void [32]\n" + + " 84 aload_2\n" + + " 85 athrow\n" + + " 86 iload_1 [i]\n" + + " 87 bipush 35\n" + + " 89 if_icmpne 122\n" + + " 92 aload_0 [this]\n" + // return 2 + " 93 invokespecial X.bar() : int [28]\n" + + " 96 pop\n" + + " 97 return\n" + + " 98 astore_2 [e]\n" + + " 99 aload_0 [this]\n" + + " 100 invokespecial X.bar() : int [28]\n" + + " 103 pop\n" + + " 104 aload_0 [this]\n" + + " 105 invokespecial X.bar() : int [28]\n" + + " 108 pop\n" + + " 109 goto 127\n" + + " 112 astore 5\n" + + " 114 aload_0 [this]\n" + + " 115 invokespecial X.bar() : int [28]\n" + + " 118 pop\n" + + " 119 aload 5\n" + + " 121 athrow\n" + + " 122 aload_0 [this]\n" + + " 123 invokespecial X.bar() : int [28]\n" + + " 126 pop\n" + + " 127 return\n" + + " Exception Table:\n" + + " [pc: 17, pc: 22] -> 51 when : any\n" + + " [pc: 32, pc: 38] -> 51 when : any\n" + + " [pc: 6, pc: 64] -> 64 when : any\n" + + " [pc: 2, pc: 32] -> 98 when : java.io.IOException\n" + + " [pc: 38, pc: 92] -> 98 when : java.io.IOException\n" + + " [pc: 2, pc: 32] -> 112 when : any\n" + + " [pc: 38, pc: 92] -> 112 when : any\n" + + " [pc: 98, pc: 104] -> 112 when : any\n" + + " Line numbers:\n" + + " [pc: 0, line: 5]\n" + + " [pc: 2, line: 7]\n" + + " [pc: 17, line: 8]\n" + + " [pc: 22, line: 9]\n" + + " [pc: 32, line: 15]\n" + + " [pc: 37, line: 8]\n" + + " [pc: 38, line: 9]\n" + + " [pc: 86, line: 10]\n" + + " [pc: 92, line: 15]\n" + + " [pc: 97, line: 11]\n" + + " [pc: 98, line: 12]\n" + + " [pc: 99, line: 13]\n" + + " [pc: 104, line: 15]\n" + + " [pc: 112, line: 14]\n" + + " [pc: 114, line: 15]\n" + + " [pc: 119, line: 16]\n" + + " [pc: 122, line: 15]\n" + + " [pc: 127, line: 17]\n" + + " Local variable table:\n" + + " [pc: 0, pc: 128] local: this index: 0 type: X\n" + + " [pc: 2, pc: 128] local: i index: 1 type: int\n" + + " [pc: 17, pc: 62] local: fis index: 4 type: java.io.FileInputStream\n" + + " [pc: 99, pc: 104] local: e index: 2 type: java.io.IOException\n" + + " Stack map table: number of frames 12\n" + + " [pc: 32, full, stack: {}, locals: {X, int, java.lang.Throwable, java.lang.Throwable, java.io.FileInputStream}]\n" + + " [pc: 38, same]\n" + + " [pc: 51, same_locals_1_stack_item, stack: {java.lang.Throwable}]\n" + + " [pc: 62, chop 1 local(s)]\n" + + " [pc: 64, same_locals_1_stack_item, stack: {java.lang.Throwable}]\n" + + " [pc: 74, same]\n" + + " [pc: 84, same]\n" + + " [pc: 86, chop 2 local(s)]\n" + + " [pc: 98, same_locals_1_stack_item, stack: {java.io.IOException}]\n" + + " [pc: 112, same_locals_1_stack_item, stack: {java.lang.Throwable}]\n" + + " [pc: 122, same]\n" + + " [pc: 127, same]\n"; + int index = actualOutput.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(actualOutput, 2)); + } + if (index == -1) { + assertEquals("Wrong contents", expectedOutput, actualOutput); + } + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java index cb789a4ad4..68eb561b78 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java @@ -36,6 +36,16 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl flowInfo = stat.analyseCode(this.scope, flowContext, flowInfo); } } + if (this.explicitDeclarations > 0) { + // cleanup assignment info for locals that are scoped to this block: + LocalVariableBinding[] locals = this.scope.locals; + if (locals != null) { + int numLocals = this.scope.localIndex; + for (int i = 0; i < numLocals; i++) { + flowInfo.resetAssignmentInfo(locals[i]); + } + } + } return flowInfo; } /** diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java index a3385251e2..343ca0ea01 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java @@ -148,6 +148,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl } if (resourcesLength > 0) { this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); + // the resources are not in scope after the try block, so remove their assignment info + // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since + // it is used to add or remove assigned resources during code gen + for (int i = 0; i < resourcesLength; i++) { + tryInfo.resetAssignmentInfo(this.resources[i].binding); + } } // check unreachable catch blocks handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); @@ -274,6 +280,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl } if (resourcesLength > 0) { this.postTryInitStateIndex = currentScope.methodScope().recordInitializationStates(tryInfo); + // the resources are not in scope after the try block, so remove their assignment info + // to avoid polluting the state indices. However, do this after the postTryInitStateIndex is calculated since + // it is used to add or remove assigned resources during code gen + for (int i = 0; i < resourcesLength; i++) { + tryInfo.resetAssignmentInfo(this.resources[i].binding); + } } // check unreachable catch blocks handlingContext.complainIfUnusedExceptionHandlers(this.scope, this); |
