diff options
author | Satyam Kandula | 2012-05-23 13:15:35 +0000 |
---|---|---|
committer | Satyam Kandula | 2012-05-23 13:15:35 +0000 |
commit | 90457871ba3051d340feae7220f15bab37c7d551 (patch) | |
tree | 5dec188e20420cc7cd0dca92d80675c8ffa0e825 | |
parent | 7ca9f198dab5ae249453376b5f6d99317f797266 (diff) | |
download | eclipse.jdt.core-90457871ba3051d340feae7220f15bab37c7d551.tar.gz eclipse.jdt.core-90457871ba3051d340feae7220f15bab37c7d551.tar.xz eclipse.jdt.core-90457871ba3051d340feae7220f15bab37c7d551.zip |
Fix for bug 380112: [1.7][compiler] Incorrect unreachable catch blockv20120523-1315
detection in try-with-resources
4 files changed, 160 insertions, 8 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java index e606150ea4..43a7fa40a1 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryWithResourcesStatementTest.java @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; +import java.io.File; import java.util.Map; import junit.framework.Test; @@ -22,7 +23,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; public class TryWithResourcesStatementTest extends AbstractRegressionTest { static { -// TESTS_NAMES = new String[] { "test061m"}; +// TESTS_NAMES = new String[] { "test380112e"}; // TESTS_NUMBERS = new int[] { 50 }; // TESTS_RANGE = new int[] { 11, -1 }; } @@ -4078,6 +4079,119 @@ public void test375326g() { "The local variable a may not have been initialized\n" + "----------\n"); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 +public void test380112a() { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "interface I extends Closeable, Serializable {}\n" + + "public class X {\n"+ + " public static void main(String [] args) {\n" + + " try (I i = getX()) {\n" + + " } catch (IOException x) {\n" + + " }\n"+ + " System.out.println(\"Done\");\n" + + " }\n" + + " public static I getX() { return null;}\n"+ + " public X(){}\n" + + "}\n" + }, + "Done"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 +//variant with finally +public void test380112b() { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "interface I extends Closeable, Serializable {}\n" + + "public class X {\n"+ + " public static void main(String [] args) {\n" + + " try (I i = getX()) {\n" + + " } catch (IOException x) {\n" + + " } finally {\n"+ + " System.out.println(\"Done\");\n" + + " }\n" + + " }\n" + + " public static I getX() { return null;}\n"+ + " public X(){}\n" + + "}\n" + }, + "Done"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 +//variant with two methods throwing different Exceptions (one subtype of other) +//subtype should be the one to be caught +public void test380112c() { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "interface I2 { public void close() throws FileNotFoundException; }\n"+ + "interface I extends Closeable, I2 {}\n" + + "public class X {\n"+ + " public static void main(String [] args) {\n" + + " try (I i = getX()) {\n" + + " } catch (FileNotFoundException x) {\n" + + " }\n"+ + " System.out.println(\"Done\");\n" + + " }\n" + + " public static I getX() { return null;}\n"+ + " public X(){}\n" + + "}\n" + }, + "Done"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 +//test380112c's variant with finally +public void test380112d() { + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "interface I2 { public void close() throws FileNotFoundException; }\n"+ + "interface I extends Closeable, I2 {}\n" + + "public class X {\n"+ + " public static void main(String [] args) {\n" + + " try (I i = getX()) {\n" + + " } catch (FileNotFoundException x) {\n" + + " } finally {\n"+ + " System.out.println(\"Done\");\n" + + " }\n" + + " }\n" + + " public static I getX() { return null;}\n"+ + " public X(){}\n" + + "}\n" + }, + "Done"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 +//test380112a variant moving the Interface into a binary +public void test380112e() { + String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "Test380112.jar"; + String[] defaultLibs = getDefaultClassPaths(); + String[] libs = new String[defaultLibs.length + 1]; + System.arraycopy(defaultLibs, 0, libs, 0, defaultLibs.length); + libs[defaultLibs.length] = path; + this.runConformTest( + new String[] { + "X.java", + "import java.io.*;\n" + + "import pkg380112.I;\n" + + "public class X {\n"+ + " public static void main(String [] args) {\n" + + " try (I i = getX()) {\n" + + " } catch (IOException x) {\n" + + " }\n"+ + " System.out.println(\"Done\");\n" + + " }\n" + + " public static I getX() { return null;}\n"+ + " public X(){}\n" + + "}\n" + }, "Done", libs, true, new String[] {"-cp", path}); +} public static Class testClass() { return TryWithResourcesStatementTest.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/workspace/Test380112.jar b/org.eclipse.jdt.core.tests.compiler/workspace/Test380112.jar Binary files differnew file mode 100644 index 0000000000..856a7110ce --- /dev/null +++ b/org.eclipse.jdt.core.tests.compiler/workspace/Test380112.jar diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html index c0ed8fdb68..a101ce8a16 100644 --- a/org.eclipse.jdt.core/buildnotes_jdt-core.html +++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html @@ -52,7 +52,9 @@ Eclipse SDK 3.8.0 - %date% - 3.8.0 <h2>What's new in this drop</h2> <h3>Problem Reports Fixed</h3> -<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=379726">379726</a> +<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112">380112</a> +[1.7][compiler] Incorrect unreachable catch block detection in try-with-resources +<br><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=379726">379726</a> Include Eclipse-BundleShape in test plugin MANIFEST.MF <a name="v_C55"></a> 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 01291ad0f4..68fa1c1597 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 @@ -129,9 +129,10 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { - tryInfo = this.resources[i].analyseCode(currentScope, handlingContext, tryInfo); + final LocalDeclaration resource = this.resources[i]; + tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); - LocalVariableBinding resourceBinding = this.resources[i].binding; + LocalVariableBinding resourceBinding = resource.binding; resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. if (resourceBinding.closeTracker != null) { // this was false alarm, we don't need to track the resource @@ -142,7 +143,24 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl if (type != null && type.isValidBinding()) { ReferenceBinding binding = (ReferenceBinding) type; MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter - if (closeMethod != null && closeMethod.returnType.id == TypeIds.T_void) { + if(closeMethod == null) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 + // closeMethod could be null if the binding is from an interface + // extending from multiple interfaces. + InvocationSite site = new InvocationSite() { + public TypeBinding[] genericTypeArguments() { return null;} + public boolean isSuperAccess() {return false;} + public boolean isTypeAccess() {return false;} + public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */} + public void setDepth(int depth) {/* empty */ } + public void setFieldIndex(int depth) {/* empty */ } + public int sourceEnd() {return resource.sourceEnd(); } + public int sourceStart() {return resource.sourceStart(); } + public TypeBinding expectedType() { return null; } + }; + closeMethod = this.scope.compilationUnitScope().findMethod(binding, ConstantPool.Close, new TypeBinding[0], site, false); + } + if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[i], tryInfo, currentScope, true); @@ -269,9 +287,10 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl FlowInfo tryInfo = flowInfo.copy(); for (int i = 0; i < resourcesLength; i++) { - tryInfo = this.resources[i].analyseCode(currentScope, handlingContext, tryInfo); + final LocalDeclaration resource = this.resources[i]; + tryInfo = resource.analyseCode(currentScope, handlingContext, tryInfo); this.postResourcesInitStateIndexes[i] = currentScope.methodScope().recordInitializationStates(tryInfo); - LocalVariableBinding resourceBinding = this.resources[i].binding; + LocalVariableBinding resourceBinding = resource.binding; resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways. if (resourceBinding.closeTracker != null) { // this was false alarm, we don't need to track the resource @@ -282,7 +301,24 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl if (type != null && type.isValidBinding()) { ReferenceBinding binding = (ReferenceBinding) type; MethodBinding closeMethod = binding.getExactMethod(ConstantPool.Close, new TypeBinding [0], this.scope.compilationUnitScope()); // scope needs to be tighter - if (closeMethod != null && closeMethod.returnType.id == TypeIds.T_void) { + if(closeMethod == null) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=380112 + // closeMethod could be null if the binding is from an interface + // extending from multiple interfaces. + InvocationSite site = new InvocationSite() { + public TypeBinding[] genericTypeArguments() { return null;} + public boolean isSuperAccess() {return false;} + public boolean isTypeAccess() {return false;} + public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */} + public void setDepth(int depth) {/* empty */ } + public void setFieldIndex(int depth) {/* empty */ } + public int sourceEnd() {return resource.sourceEnd(); } + public int sourceStart() {return resource.sourceStart(); } + public TypeBinding expectedType() { return null; } + }; + closeMethod = this.scope.compilationUnitScope().findMethod(binding, ConstantPool.Close, new TypeBinding[0], site, false); + } + if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) { ReferenceBinding[] thrownExceptions = closeMethod.thrownExceptions; for (int j = 0, length = thrownExceptions.length; j < length; j++) { handlingContext.checkExceptionHandlers(thrownExceptions[j], this.resources[i], tryInfo, currentScope, true); |