| author | Stephan Herrmann | 2012-09-15 14:47:24 (EDT) |
|---|---|---|
| committer | Jayaprakash Arthanareeswaran | 2012-10-19 00:48:57 (EDT) |
| commit | 468885f284e85bd93211c3e5598f6cfedb939993 (patch) (side-by-side diff) | |
| tree | af96d022cd1692cc77bedbe76ff0d529447263fe | |
| parent | 358064871a7be19bb66d5146eba4dc39b386d385 (diff) | |
| download | eclipse.jdt.core-468885f284e85bd93211c3e5598f6cfedb939993.zip eclipse.jdt.core-468885f284e85bd93211c3e5598f6cfedb939993.tar.gz eclipse.jdt.core-468885f284e85bd93211c3e5598f6cfedb939993.tar.bz2 | |
Bug 387612 - Unreachable catch block...exception is never thrown from
the try
2 files changed, 178 insertions, 4 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java index 3fff7df..bcef02a 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" + * bug 387612 - Unreachable catch block...exception is never thrown from the try *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -25,7 +26,7 @@ import junit.framework.Test; public class TryStatementTest extends AbstractRegressionTest { static { -// TESTS_NAMES = new String[] { "test074" }; +// TESTS_NAMES = new String[] { "testBug387612" }; // TESTS_NUMBERS = new int[] { 74, 75 }; // TESTS_RANGE = new int[] { 11, -1 }; } @@ -5990,6 +5991,141 @@ public void test074() { }); } +// Bug 387612 - Unreachable catch block...exception is never thrown from the try +// redundant exception in throws must not confuse downstream analysis +public void testBug387612() { + String serialUID = "private static final long serialVersionUID=1L;"; + runNegativeTest( + new String[] { + "E.java", + "public class E extends Exception {"+serialUID+"}\n", + "E1.java", + "public class E1 extends E {"+serialUID+"}\n", + "E2.java", + "public class E2 extends E {"+serialUID+"}\n", + "E3.java", + "public class E3 extends E {"+serialUID+"}\n", + "A.java", + "interface A {\n" + + " void foo(String a1, String a2) throws E1, E;\n" + + "}\n", + "B.java", + "interface B extends A {\n" + + " void foo(String a1, String a2) throws E;\n" + + "}\n", + "Client.java", + "public class Client {\n" + + " void test() {\n" + + " B b = new B() {\n" + + " public void foo(String a1, String a2) {}\n" + + " };\n" + + " try {\n" + + " b.foo(null, null);\n" + + " }\n" + + " catch (E1 e) {}\n" + + " catch (E2 e) {}\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in Client.java (at line 7)\n" + + " b.foo(null, null);\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "Unhandled exception type E\n" + + "----------\n"); +} + +// Bug 387612 - Unreachable catch block...exception is never thrown from the try +// - changed order in redundant 'throws' clause. +public void testBug387612b() { + String serialUID = "private static final long serialVersionUID=1L;"; + runNegativeTest( + new String[] { + "E.java", + "public class E extends Exception {"+serialUID+"}\n", + "E1.java", + "public class E1 extends E {"+serialUID+"}\n", + "E2.java", + "public class E2 extends E {"+serialUID+"}\n", + "E3.java", + "public class E3 extends E {"+serialUID+"}\n", + "A.java", + "interface A {\n" + + " void foo(String a1, String a2) throws E, E1;\n" + + "}\n", + "B.java", + "interface B extends A {\n" + + " void foo(String a1, String a2) throws E;\n" + + "}\n", + "Client.java", + "public class Client {\n" + + " void test() {\n" + + " B b = new B() {\n" + + " public void foo(String a1, String a2) {}\n" + + " };\n" + + " try {\n" + + " b.foo(null, null);\n" + + " }\n" + + " catch (E1 e) {}\n" + + " catch (E2 e) {}\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in Client.java (at line 7)\n" + + " b.foo(null, null);\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "Unhandled exception type E\n" + + "----------\n"); +} + +// Bug 387612 - Unreachable catch block...exception is never thrown from the try +// interface with redundant exceptions in throws is read from class file. +public void testBug387612c() { + String serialUID = "private static final long serialVersionUID=1L;"; + runConformTest( + new String[] { + "E.java", + "public class E extends Exception {"+serialUID+"}\n", + "E1.java", + "public class E1 extends E {"+serialUID+"}\n", + "E2.java", + "public class E2 extends E {"+serialUID+"}\n", + "A.java", + "interface A {\n" + + " void foo(String a1, String a2) throws E1, E;\n" + + "}\n", + "B.java", + "interface B extends A {\n" + + " void foo(String a1, String a2) throws E;\n" + + "}\n" + }); + runNegativeTest( + new String[] { + "Client.java", + "public class Client {\n" + + " void test() {\n" + + " B b = new B() {\n" + + " public void foo(String a1, String a2) {}\n" + + " };\n" + + " try {\n" + + " b.foo(null, null);\n" + + " }\n" + + " catch (E1 e) {}\n" + + " catch (E2 e) {}\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in Client.java (at line 7)\n" + + " b.foo(null, null);\n" + + " ^^^^^^^^^^^^^^^^^\n" + + "Unhandled exception type E\n" + + "----------\n", + null, + false/*shouldFlush*/); +} + public static Class testClass() { return TryStatementTest.class; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java index d3f5cbe..3d8930d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java @@ -11,7 +11,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 186342 [compiler][null] Using annotations for null checking + * Stephan Herrmann - Contributions for + * bug 186342 - [compiler][null] Using annotations for null checking + * bug 387612 - Unreachable catch block...exception is never thrown from the try *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -3996,13 +3998,14 @@ public abstract class Scope { mostSpecificExceptions = current.thrownExceptions; } int mostSpecificLength = mostSpecificExceptions.length; - int nextLength = next.thrownExceptions.length; + ReferenceBinding[] nextExceptions = getFilteredExceptions(next); + int nextLength = nextExceptions.length; SimpleSet temp = new SimpleSet(mostSpecificLength); boolean changed = false; nextException : for (int t = 0; t < mostSpecificLength; t++) { ReferenceBinding exception = mostSpecificExceptions[t]; for (int s = 0; s < nextLength; s++) { - ReferenceBinding nextException = next.thrownExceptions[s]; + ReferenceBinding nextException = nextExceptions[s]; if (exception.isCompatibleWith(nextException)) { temp.add(exception); continue nextException; @@ -4035,6 +4038,41 @@ public abstract class Scope { return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous); } + private ReferenceBinding[] getFilteredExceptions(MethodBinding method) { + // http://bugs.eclipse.org/387612 - Unreachable catch block...exception is never thrown from the try + // Need to filter redundant exceptions within the same throws clause. + // In this filtering the *most general* exception wins in order to capture all possible exceptions + // that could be thrown by the given method. + ReferenceBinding[] allExceptions = method.thrownExceptions; + int length = allExceptions.length; + if (length < 2) return allExceptions; + ReferenceBinding[] filteredExceptions = new ReferenceBinding[length]; + int count = 0; + currents: for (int i = 0; i < length; i++) { + ReferenceBinding currentException = allExceptions[i]; + for (int j = 0; j < length; j++) { + if (i == j) continue; + if (currentException == allExceptions[j]) { + // duplicate same exception + if (i < j) + break; // take only the first occurrence + else + continue currents; // skip + } + if (currentException.isCompatibleWith(allExceptions[j])) { + continue currents; // skip + } + } + filteredExceptions[count++] = currentException; + } + if (count != length) { + ReferenceBinding[] tmp = new ReferenceBinding[count]; + System.arraycopy(filteredExceptions, 0, tmp, 0, count); + return tmp; + } + return allExceptions; + } + public final ClassScope outerMostClassScope() { ClassScope lastClassScope = null; Scope scope = this; |

