提交 69e2dab4 编写于 作者: M mcimadamore

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
上级 a669738f
...@@ -131,6 +131,12 @@ public enum Source { ...@@ -131,6 +131,12 @@ public enum Source {
public boolean allowMulticatch() { public boolean allowMulticatch() {
return compareTo(JDK1_7) >= 0; return compareTo(JDK1_7) >= 0;
} }
public boolean allowImprovedRethrowAnalysis() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowImprovedCatchAnalysis() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowEnums() { public boolean allowEnums() {
return compareTo(JDK1_5) >= 0; return compareTo(JDK1_5) >= 0;
} }
......
...@@ -190,7 +190,8 @@ public class Flow extends TreeScanner { ...@@ -190,7 +190,8 @@ public class Flow extends TreeScanner {
private final Resolve rs; private final Resolve rs;
private Env<AttrContext> attrEnv; private Env<AttrContext> attrEnv;
private Lint lint; private Lint lint;
private final boolean allowRethrowAnalysis; private final boolean allowImprovedRethrowAnalysis;
private final boolean allowImprovedCatchAnalysis;
public static Flow instance(Context context) { public static Flow instance(Context context) {
Flow instance = context.get(flowKey); Flow instance = context.get(flowKey);
...@@ -209,7 +210,8 @@ public class Flow extends TreeScanner { ...@@ -209,7 +210,8 @@ public class Flow extends TreeScanner {
lint = Lint.instance(context); lint = Lint.instance(context);
rs = Resolve.instance(context); rs = Resolve.instance(context);
Source source = Source.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 /** A flag that indicates whether the last statement could
...@@ -1046,7 +1048,9 @@ public class Flow extends TreeScanner { ...@@ -1046,7 +1048,9 @@ public class Flow extends TreeScanner {
} }
} }
scanStat(tree.body); scanStat(tree.body);
List<Type> thrownInTry = thrown; List<Type> thrownInTry = allowImprovedCatchAnalysis ?
chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) :
thrown;
thrown = thrownPrev; thrown = thrownPrev;
caught = caughtPrev; caught = caughtPrev;
boolean aliveEnd = alive; boolean aliveEnd = alive;
...@@ -1081,16 +1085,7 @@ public class Flow extends TreeScanner { ...@@ -1081,16 +1085,7 @@ public class Flow extends TreeScanner {
ctypes = ctypes.append(exc); ctypes = ctypes.append(exc);
if (types.isSameType(exc, syms.objectType)) if (types.isSameType(exc, syms.objectType))
continue; continue;
if (chk.subset(exc, caughtInTry)) { checkCaughtType(l.head.pos(), exc, thrownInTry, 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);
}
caughtInTry = chk.incl(exc, caughtInTry); caughtInTry = chk.incl(exc, caughtInTry);
} }
} }
...@@ -1154,6 +1149,29 @@ public class Flow extends TreeScanner { ...@@ -1154,6 +1149,29 @@ public class Flow extends TreeScanner {
uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 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) { public void visitConditional(JCConditional tree) {
scanCond(tree.cond); scanCond(tree.cond);
Bits initsBeforeElse = initsWhenFalse; Bits initsBeforeElse = initsWhenFalse;
...@@ -1238,7 +1256,7 @@ public class Flow extends TreeScanner { ...@@ -1238,7 +1256,7 @@ public class Flow extends TreeScanner {
sym.kind == VAR && sym.kind == VAR &&
(sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 && (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
preciseRethrowTypes.get(sym) != null && preciseRethrowTypes.get(sym) != null &&
allowRethrowAnalysis) { allowImprovedRethrowAnalysis) {
for (Type t : preciseRethrowTypes.get(sym)) { for (Type t : preciseRethrowTypes.get(sym)) {
markThrown(tree, t); markThrown(tree, t);
} }
......
...@@ -1102,6 +1102,16 @@ compiler.warn.inexact.non-varargs.call=\ ...@@ -1102,6 +1102,16 @@ compiler.warn.inexact.non-varargs.call=\
cast to {0} for a varargs call\n\ cast to {0} for a varargs call\n\
cast to {1} for a non-varargs call and to suppress this warning 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 # 0: symbol
compiler.warn.long.SVUID=\ compiler.warn.long.SVUID=\
serialVersionUID must be of type long in class {0} serialVersionUID must be of type long in class {0}
......
/*
* @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
}
}
- 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
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
/*
* 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
}
}
/*
* 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
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册