# HG changeset patch # User mcimadamore # Date 1300273946 0 # Node ID 5b29f2a850855c05d07967d2b2aafa62f073b594 # Parent 480de7832e2f8e3d9f483026ac32d71edc7ee7bd 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 diff -r 480de7832e2f -r 5b29f2a85085 src/share/classes/com/sun/tools/javac/code/Source.java --- a/src/share/classes/com/sun/tools/javac/code/Source.java Tue Mar 15 14:19:00 2011 -0700 +++ b/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; } diff -r 480de7832e2f -r 5b29f2a85085 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Tue Mar 15 14:19:00 2011 -0700 +++ b/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 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 thrownInTry = thrown; + List 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 thrownInTry, List 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 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); } diff -r 480de7832e2f -r 5b29f2a85085 src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 15 14:19:00 2011 -0700 +++ b/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} diff -r 480de7832e2f -r 5b29f2a85085 test/tools/javac/6558548/T6558548.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 + } +} diff -r 480de7832e2f -r 5b29f2a85085 test/tools/javac/6558548/T6558548_6.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 diff -r 480de7832e2f -r 5b29f2a85085 test/tools/javac/6558548/T6558548_latest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 diff -r 480de7832e2f -r 5b29f2a85085 test/tools/javac/diags/examples/UnreachableCatch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 + } +} diff -r 480de7832e2f -r 5b29f2a85085 test/tools/javac/diags/examples/UnreachableCatch1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 + } +}