mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-13 11:55:38 +00:00
6558548: The compiler needs to be aligned with clarified specification of throws
Javac should issue unconditional warnings when 'dead' catch clauses are detected Reviewed-by: jjg
This commit is contained in:
parent
73407fb7a1
commit
eb4e1b86cd
@ -131,6 +131,12 @@ public enum Source {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -190,7 +190,8 @@ public class Flow extends TreeScanner {
|
||||
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 @@ public class Flow extends TreeScanner {
|
||||
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 @@ public class Flow extends TreeScanner {
|
||||
}
|
||||
}
|
||||
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 @@ public class Flow extends TreeScanner {
|
||||
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 @@ public class Flow extends TreeScanner {
|
||||
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 @@ public class Flow extends TreeScanner {
|
||||
sym.kind == VAR &&
|
||||
(sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
|
||||
preciseRethrowTypes.get(sym) != null &&
|
||||
allowRethrowAnalysis) {
|
||||
allowImprovedRethrowAnalysis) {
|
||||
for (Type t : preciseRethrowTypes.get(sym)) {
|
||||
markThrown(tree, t);
|
||||
}
|
||||
|
||||
@ -1102,6 +1102,16 @@ compiler.warn.inexact.non-varargs.call=\
|
||||
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}
|
||||
|
||||
300
langtools/test/tools/javac/6558548/T6558548.java
Normal file
300
langtools/test/tools/javac/6558548/T6558548.java
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
9
langtools/test/tools/javac/6558548/T6558548_6.out
Normal file
9
langtools/test/tools/javac/6558548/T6558548_6.out
Normal file
@ -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
|
||||
23
langtools/test/tools/javac/6558548/T6558548_latest.out
Normal file
23
langtools/test/tools/javac/6558548/T6558548_latest.out
Normal file
@ -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
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user