6558548: The compiler needs to be aligned with clarified specification of throws
Summary: Javac should issue unconditional warnings when 'dead' catch clauses are detected
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Tue Mar 15 14:19:00 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Wed Mar 16 11:12:26 2011 +0000
@@ -131,6 +131,12 @@
public boolean allowMulticatch() {
return compareTo(JDK1_7) >= 0;
}
+ public boolean allowImprovedRethrowAnalysis() {
+ return compareTo(JDK1_7) >= 0;
+ }
+ public boolean allowImprovedCatchAnalysis() {
+ return compareTo(JDK1_7) >= 0;
+ }
public boolean allowEnums() {
return compareTo(JDK1_5) >= 0;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Tue Mar 15 14:19:00 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Mar 16 11:12:26 2011 +0000
@@ -190,7 +190,8 @@
private final Resolve rs;
private Env<AttrContext> attrEnv;
private Lint lint;
- private final boolean allowRethrowAnalysis;
+ private final boolean allowImprovedRethrowAnalysis;
+ private final boolean allowImprovedCatchAnalysis;
public static Flow instance(Context context) {
Flow instance = context.get(flowKey);
@@ -209,7 +210,8 @@
lint = Lint.instance(context);
rs = Resolve.instance(context);
Source source = Source.instance(context);
- allowRethrowAnalysis = source.allowMulticatch();
+ allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
+ allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
}
/** A flag that indicates whether the last statement could
@@ -1046,7 +1048,9 @@
}
}
scanStat(tree.body);
- List<Type> thrownInTry = thrown;
+ List<Type> thrownInTry = allowImprovedCatchAnalysis ?
+ chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
+ thrown;
thrown = thrownPrev;
caught = caughtPrev;
boolean aliveEnd = alive;
@@ -1081,16 +1085,7 @@
ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType))
continue;
- if (chk.subset(exc, caughtInTry)) {
- log.error(l.head.pos(),
- "except.already.caught", exc);
- } else if (!chk.isUnchecked(l.head.pos(), exc) &&
- exc.tsym != syms.throwableType.tsym &&
- exc.tsym != syms.exceptionType.tsym &&
- !chk.intersects(exc, thrownInTry)) {
- log.error(l.head.pos(),
- "except.never.thrown.in.try", exc);
- }
+ checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry);
caughtInTry = chk.incl(exc, caughtInTry);
}
}
@@ -1154,6 +1149,29 @@
uninitsTry.andSet(uninitsTryPrev).andSet(uninits);
}
+ void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) {
+ if (chk.subset(exc, caughtInTry)) {
+ log.error(pos, "except.already.caught", exc);
+ } else if (!chk.isUnchecked(pos, exc) &&
+ exc.tsym != syms.throwableType.tsym &&
+ exc.tsym != syms.exceptionType.tsym &&
+ !chk.intersects(exc, thrownInTry)) {
+ log.error(pos, "except.never.thrown.in.try", exc);
+ } else if (allowImprovedCatchAnalysis) {
+ List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry);
+ // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an
+ // unchecked exception, the result list would not be empty, as the augmented
+ // thrown set includes { RuntimeException, Error }; if 'exc' was a checked
+ // exception, that would have been covered in the branch above
+ if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty()) {
+ String key = catchableThrownTypes.length() == 1 ?
+ "unreachable.catch" :
+ "unreachable.catch.1";
+ log.warning(pos, key, catchableThrownTypes);
+ }
+ }
+ }
+
public void visitConditional(JCConditional tree) {
scanCond(tree.cond);
Bits initsBeforeElse = initsWhenFalse;
@@ -1238,7 +1256,7 @@
sym.kind == VAR &&
(sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
preciseRethrowTypes.get(sym) != null &&
- allowRethrowAnalysis) {
+ allowImprovedRethrowAnalysis) {
for (Type t : preciseRethrowTypes.get(sym)) {
markThrown(tree, t);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 15 14:19:00 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 16 11:12:26 2011 +0000
@@ -1102,6 +1102,16 @@
cast to {0} for a varargs call\n\
cast to {1} for a non-varargs call and to suppress this warning
+# 0: list of type
+compiler.warn.unreachable.catch=\
+ unreachable catch clause\n\
+ thrown type {0} has already been caught
+
+# 0: list of type
+compiler.warn.unreachable.catch.1=\
+ unreachable catch clause\n\
+ thrown types {0} have already been caught
+
# 0: symbol
compiler.warn.long.SVUID=\
serialVersionUID must be of type long in class {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/6558548/T6558548.java Wed Mar 16 11:12:26 2011 +0000
@@ -0,0 +1,300 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6558548
+ * @summary The compiler needs to be aligned with clarified specification of throws
+ * @compile/fail/ref=T6558548_latest.out -XDrawDiagnostics T6558548.java
+ * @compile/fail/ref=T6558548_6.out -source 6 -XDrawDiagnostics T6558548.java
+ */
+
+class T6558548 {
+
+ void nothing() {}
+ void checked() throws InterruptedException {}
+ void runtime() throws IllegalArgumentException {}
+
+ void m1() {
+ try {
+ throw new java.io.FileNotFoundException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m1a() {
+ try {
+ throw new java.io.IOException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } //ok
+ }
+
+ void m2() {
+ try {
+ nothing();
+ }
+ catch(Exception exc) { } // ok
+ }
+
+ void m3() {
+ try {
+ checked();
+ }
+ catch(Exception exc) { } //ok
+ }
+
+ void m4() {
+ try {
+ runtime();
+ }
+ catch(Exception exc) { } //ok
+ }
+
+ void m5() {
+ try {
+ nothing();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m6() {
+ try {
+ checked();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m7() {
+ try {
+ runtime();
+ }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m9() {
+ try {
+ checked();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m10() {
+ try {
+ runtime();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m11() {
+ try {
+ nothing();
+ }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m12() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m13() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m14() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Throwable exc) { } // ok
+ }
+
+ void m15() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //ok
+ }
+
+ void m16() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m17() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m18() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { }
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m19() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m20() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Exception exc) { } //6: ok; latest: unreachable
+ }
+
+ void m21() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // ok
+ }
+
+ void m22() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m23() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Exception exc) { } // 6: ok; latest: unreachable
+ }
+
+ void m24() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m25() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m26() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m27() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m28() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m29() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(InterruptedException exc) { } //never thrown in try
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m30() {
+ try {
+ checked();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //ok
+ }
+
+ void m31() {
+ try {
+ runtime();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m32() {
+ try {
+ nothing();
+ }
+ catch(RuntimeException exc) { }
+ catch(Error exc) { }
+ catch(Throwable exc) { } //6: ok; latest: unreachable
+ }
+
+ void m33() {
+ try {
+ checked();
+ }
+ catch(InterruptedException exc) { } //ok
+ }
+
+ void m34() {
+ try {
+ runtime();
+ }
+ catch(InterruptedException exc) { } //never thrown in try
+ }
+
+ void m35() {
+ try {
+ nothing();
+ }
+ catch(InterruptedException exc) { } //never thrown in try
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/6558548/T6558548_6.out Wed Mar 16 11:12:26 2011 +0000
@@ -0,0 +1,9 @@
+- compiler.warn.source.no.bootclasspath: 1.6
+T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+6 errors
+1 warning
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/6558548/T6558548_latest.out Wed Mar 16 11:12:26 2011 +0000
@@ -0,0 +1,23 @@
+T6558548.java:20:9: compiler.warn.unreachable.catch: java.io.FileNotFoundException
+T6558548.java:134:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:142:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:151:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException
+T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:160:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:169:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:185:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:193:9: compiler.warn.unreachable.catch: java.lang.RuntimeException
+T6558548.java:211:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:220:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:230:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException,java.lang.Error
+T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:240:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:250:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:268:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:277:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error
+T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException
+6 errors
+15 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnreachableCatch.java Wed Mar 16 11:12:26 2011 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.warn.unreachable.catch
+
+class UnreachableCatch {
+
+ void test() {
+ try {
+ throw new java.io.FileNotFoundException();
+ }
+ catch(java.io.FileNotFoundException exc) { }
+ catch(java.io.IOException exc) { } //unreachable
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnreachableCatch1.java Wed Mar 16 11:12:26 2011 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.warn.unreachable.catch.1
+
+class UnreachableCatch1 {
+
+ void test() {
+ try {
+ throw new IllegalArgumentException();
+ }
+ catch(Error err) { }
+ catch(RuntimeException rex) { }
+ catch(Throwable t) { } //unreachable
+ }
+}