Wed, 16 Mar 2011 11:12:26 +0000
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
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Source.java Tue Mar 15 14:19:00 2011 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Wed Mar 16 11:12:26 2011 +0000 1.3 @@ -131,6 +131,12 @@ 1.4 public boolean allowMulticatch() { 1.5 return compareTo(JDK1_7) >= 0; 1.6 } 1.7 + public boolean allowImprovedRethrowAnalysis() { 1.8 + return compareTo(JDK1_7) >= 0; 1.9 + } 1.10 + public boolean allowImprovedCatchAnalysis() { 1.11 + return compareTo(JDK1_7) >= 0; 1.12 + } 1.13 public boolean allowEnums() { 1.14 return compareTo(JDK1_5) >= 0; 1.15 }
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Tue Mar 15 14:19:00 2011 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Mar 16 11:12:26 2011 +0000 2.3 @@ -190,7 +190,8 @@ 2.4 private final Resolve rs; 2.5 private Env<AttrContext> attrEnv; 2.6 private Lint lint; 2.7 - private final boolean allowRethrowAnalysis; 2.8 + private final boolean allowImprovedRethrowAnalysis; 2.9 + private final boolean allowImprovedCatchAnalysis; 2.10 2.11 public static Flow instance(Context context) { 2.12 Flow instance = context.get(flowKey); 2.13 @@ -209,7 +210,8 @@ 2.14 lint = Lint.instance(context); 2.15 rs = Resolve.instance(context); 2.16 Source source = Source.instance(context); 2.17 - allowRethrowAnalysis = source.allowMulticatch(); 2.18 + allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis(); 2.19 + allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); 2.20 } 2.21 2.22 /** A flag that indicates whether the last statement could 2.23 @@ -1046,7 +1048,9 @@ 2.24 } 2.25 } 2.26 scanStat(tree.body); 2.27 - List<Type> thrownInTry = thrown; 2.28 + List<Type> thrownInTry = allowImprovedCatchAnalysis ? 2.29 + chk.union(thrown, List.of(syms.runtimeExceptionType, syms.errorType)) : 2.30 + thrown; 2.31 thrown = thrownPrev; 2.32 caught = caughtPrev; 2.33 boolean aliveEnd = alive; 2.34 @@ -1081,16 +1085,7 @@ 2.35 ctypes = ctypes.append(exc); 2.36 if (types.isSameType(exc, syms.objectType)) 2.37 continue; 2.38 - if (chk.subset(exc, caughtInTry)) { 2.39 - log.error(l.head.pos(), 2.40 - "except.already.caught", exc); 2.41 - } else if (!chk.isUnchecked(l.head.pos(), exc) && 2.42 - exc.tsym != syms.throwableType.tsym && 2.43 - exc.tsym != syms.exceptionType.tsym && 2.44 - !chk.intersects(exc, thrownInTry)) { 2.45 - log.error(l.head.pos(), 2.46 - "except.never.thrown.in.try", exc); 2.47 - } 2.48 + checkCaughtType(l.head.pos(), exc, thrownInTry, caughtInTry); 2.49 caughtInTry = chk.incl(exc, caughtInTry); 2.50 } 2.51 } 2.52 @@ -1154,6 +1149,29 @@ 2.53 uninitsTry.andSet(uninitsTryPrev).andSet(uninits); 2.54 } 2.55 2.56 + void checkCaughtType(DiagnosticPosition pos, Type exc, List<Type> thrownInTry, List<Type> caughtInTry) { 2.57 + if (chk.subset(exc, caughtInTry)) { 2.58 + log.error(pos, "except.already.caught", exc); 2.59 + } else if (!chk.isUnchecked(pos, exc) && 2.60 + exc.tsym != syms.throwableType.tsym && 2.61 + exc.tsym != syms.exceptionType.tsym && 2.62 + !chk.intersects(exc, thrownInTry)) { 2.63 + log.error(pos, "except.never.thrown.in.try", exc); 2.64 + } else if (allowImprovedCatchAnalysis) { 2.65 + List<Type> catchableThrownTypes = chk.intersect(List.of(exc), thrownInTry); 2.66 + // 'catchableThrownTypes' cannnot possibly be empty - if 'exc' was an 2.67 + // unchecked exception, the result list would not be empty, as the augmented 2.68 + // thrown set includes { RuntimeException, Error }; if 'exc' was a checked 2.69 + // exception, that would have been covered in the branch above 2.70 + if (chk.diff(catchableThrownTypes, caughtInTry).isEmpty()) { 2.71 + String key = catchableThrownTypes.length() == 1 ? 2.72 + "unreachable.catch" : 2.73 + "unreachable.catch.1"; 2.74 + log.warning(pos, key, catchableThrownTypes); 2.75 + } 2.76 + } 2.77 + } 2.78 + 2.79 public void visitConditional(JCConditional tree) { 2.80 scanCond(tree.cond); 2.81 Bits initsBeforeElse = initsWhenFalse; 2.82 @@ -1238,7 +1256,7 @@ 2.83 sym.kind == VAR && 2.84 (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 && 2.85 preciseRethrowTypes.get(sym) != null && 2.86 - allowRethrowAnalysis) { 2.87 + allowImprovedRethrowAnalysis) { 2.88 for (Type t : preciseRethrowTypes.get(sym)) { 2.89 markThrown(tree, t); 2.90 }
3.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 15 14:19:00 2011 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 16 11:12:26 2011 +0000 3.3 @@ -1102,6 +1102,16 @@ 3.4 cast to {0} for a varargs call\n\ 3.5 cast to {1} for a non-varargs call and to suppress this warning 3.6 3.7 +# 0: list of type 3.8 +compiler.warn.unreachable.catch=\ 3.9 + unreachable catch clause\n\ 3.10 + thrown type {0} has already been caught 3.11 + 3.12 +# 0: list of type 3.13 +compiler.warn.unreachable.catch.1=\ 3.14 + unreachable catch clause\n\ 3.15 + thrown types {0} have already been caught 3.16 + 3.17 # 0: symbol 3.18 compiler.warn.long.SVUID=\ 3.19 serialVersionUID must be of type long in class {0}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/6558548/T6558548.java Wed Mar 16 11:12:26 2011 +0000 4.3 @@ -0,0 +1,300 @@ 4.4 +/* 4.5 + * @test /nodynamiccopyright/ 4.6 + * @bug 6558548 4.7 + * @summary The compiler needs to be aligned with clarified specification of throws 4.8 + * @compile/fail/ref=T6558548_latest.out -XDrawDiagnostics T6558548.java 4.9 + * @compile/fail/ref=T6558548_6.out -source 6 -XDrawDiagnostics T6558548.java 4.10 + */ 4.11 + 4.12 +class T6558548 { 4.13 + 4.14 + void nothing() {} 4.15 + void checked() throws InterruptedException {} 4.16 + void runtime() throws IllegalArgumentException {} 4.17 + 4.18 + void m1() { 4.19 + try { 4.20 + throw new java.io.FileNotFoundException(); 4.21 + } 4.22 + catch(java.io.FileNotFoundException exc) { } 4.23 + catch(java.io.IOException exc) { } // 6: ok; latest: unreachable 4.24 + } 4.25 + 4.26 + void m1a() { 4.27 + try { 4.28 + throw new java.io.IOException(); 4.29 + } 4.30 + catch(java.io.FileNotFoundException exc) { } 4.31 + catch(java.io.IOException exc) { } //ok 4.32 + } 4.33 + 4.34 + void m2() { 4.35 + try { 4.36 + nothing(); 4.37 + } 4.38 + catch(Exception exc) { } // ok 4.39 + } 4.40 + 4.41 + void m3() { 4.42 + try { 4.43 + checked(); 4.44 + } 4.45 + catch(Exception exc) { } //ok 4.46 + } 4.47 + 4.48 + void m4() { 4.49 + try { 4.50 + runtime(); 4.51 + } 4.52 + catch(Exception exc) { } //ok 4.53 + } 4.54 + 4.55 + void m5() { 4.56 + try { 4.57 + nothing(); 4.58 + } 4.59 + catch(Throwable exc) { } //ok 4.60 + } 4.61 + 4.62 + void m6() { 4.63 + try { 4.64 + checked(); 4.65 + } 4.66 + catch(Throwable exc) { } //ok 4.67 + } 4.68 + 4.69 + void m7() { 4.70 + try { 4.71 + runtime(); 4.72 + } 4.73 + catch(Throwable exc) { } //ok 4.74 + } 4.75 + 4.76 + void m9() { 4.77 + try { 4.78 + checked(); 4.79 + } 4.80 + catch(Error exc) { } 4.81 + catch(Throwable exc) { } //ok 4.82 + } 4.83 + 4.84 + void m10() { 4.85 + try { 4.86 + runtime(); 4.87 + } 4.88 + catch(Error exc) { } 4.89 + catch(Throwable exc) { } //ok 4.90 + } 4.91 + 4.92 + void m11() { 4.93 + try { 4.94 + nothing(); 4.95 + } 4.96 + catch(Error exc) { } 4.97 + catch(Throwable exc) { } //ok 4.98 + } 4.99 + 4.100 + void m12() { 4.101 + try { 4.102 + checked(); 4.103 + } 4.104 + catch(RuntimeException exc) { } 4.105 + catch(Throwable exc) { } // ok 4.106 + } 4.107 + 4.108 + void m13() { 4.109 + try { 4.110 + runtime(); 4.111 + } 4.112 + catch(RuntimeException exc) { } 4.113 + catch(Throwable exc) { } // ok 4.114 + } 4.115 + 4.116 + void m14() { 4.117 + try { 4.118 + nothing(); 4.119 + } 4.120 + catch(RuntimeException exc) { } 4.121 + catch(Throwable exc) { } // ok 4.122 + } 4.123 + 4.124 + void m15() { 4.125 + try { 4.126 + checked(); 4.127 + } 4.128 + catch(RuntimeException exc) { } 4.129 + catch(Exception exc) { } //ok 4.130 + } 4.131 + 4.132 + void m16() { 4.133 + try { 4.134 + runtime(); 4.135 + } 4.136 + catch(RuntimeException exc) { } 4.137 + catch(Exception exc) { } //6: ok; latest: unreachable 4.138 + } 4.139 + 4.140 + void m17() { 4.141 + try { 4.142 + nothing(); 4.143 + } 4.144 + catch(RuntimeException exc) { } 4.145 + catch(Exception exc) { } //6: ok; latest: unreachable 4.146 + } 4.147 + 4.148 + void m18() { 4.149 + try { 4.150 + checked(); 4.151 + } 4.152 + catch(RuntimeException exc) { } 4.153 + catch(InterruptedException exc) { } 4.154 + catch(Exception exc) { } //6: ok; latest: unreachable 4.155 + } 4.156 + 4.157 + void m19() { 4.158 + try { 4.159 + runtime(); 4.160 + } 4.161 + catch(RuntimeException exc) { } 4.162 + catch(InterruptedException exc) { } //never thrown in try 4.163 + catch(Exception exc) { } //6: ok; latest: unreachable 4.164 + } 4.165 + 4.166 + void m20() { 4.167 + try { 4.168 + nothing(); 4.169 + } 4.170 + catch(RuntimeException exc) { } 4.171 + catch(InterruptedException exc) { } //never thrown in try 4.172 + catch(Exception exc) { } //6: ok; latest: unreachable 4.173 + } 4.174 + 4.175 + void m21() { 4.176 + try { 4.177 + checked(); 4.178 + } 4.179 + catch(RuntimeException exc) { } 4.180 + catch(Exception exc) { } // ok 4.181 + } 4.182 + 4.183 + void m22() { 4.184 + try { 4.185 + runtime(); 4.186 + } 4.187 + catch(RuntimeException exc) { } 4.188 + catch(Exception exc) { } // 6: ok; latest: unreachable 4.189 + } 4.190 + 4.191 + void m23() { 4.192 + try { 4.193 + nothing(); 4.194 + } 4.195 + catch(RuntimeException exc) { } 4.196 + catch(Exception exc) { } // 6: ok; latest: unreachable 4.197 + } 4.198 + 4.199 + void m24() { 4.200 + try { 4.201 + checked(); 4.202 + } 4.203 + catch(RuntimeException exc) { } 4.204 + catch(Error exc) { } 4.205 + catch(Throwable exc) { } //ok 4.206 + } 4.207 + 4.208 + void m25() { 4.209 + try { 4.210 + runtime(); 4.211 + } 4.212 + catch(RuntimeException exc) { } 4.213 + catch(Error exc) { } 4.214 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.215 + } 4.216 + 4.217 + void m26() { 4.218 + try { 4.219 + nothing(); 4.220 + } 4.221 + catch(RuntimeException exc) { } 4.222 + catch(Error exc) { } 4.223 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.224 + } 4.225 + 4.226 + void m27() { 4.227 + try { 4.228 + checked(); 4.229 + } 4.230 + catch(RuntimeException exc) { } 4.231 + catch(Error exc) { } 4.232 + catch(InterruptedException exc) { } 4.233 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.234 + } 4.235 + 4.236 + void m28() { 4.237 + try { 4.238 + runtime(); 4.239 + } 4.240 + catch(RuntimeException exc) { } 4.241 + catch(Error exc) { } 4.242 + catch(InterruptedException exc) { } //never thrown in try 4.243 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.244 + } 4.245 + 4.246 + void m29() { 4.247 + try { 4.248 + nothing(); 4.249 + } 4.250 + catch(RuntimeException exc) { } 4.251 + catch(Error exc) { } 4.252 + catch(InterruptedException exc) { } //never thrown in try 4.253 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.254 + } 4.255 + 4.256 + void m30() { 4.257 + try { 4.258 + checked(); 4.259 + } 4.260 + catch(RuntimeException exc) { } 4.261 + catch(Error exc) { } 4.262 + catch(Throwable exc) { } //ok 4.263 + } 4.264 + 4.265 + void m31() { 4.266 + try { 4.267 + runtime(); 4.268 + } 4.269 + catch(RuntimeException exc) { } 4.270 + catch(Error exc) { } 4.271 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.272 + } 4.273 + 4.274 + void m32() { 4.275 + try { 4.276 + nothing(); 4.277 + } 4.278 + catch(RuntimeException exc) { } 4.279 + catch(Error exc) { } 4.280 + catch(Throwable exc) { } //6: ok; latest: unreachable 4.281 + } 4.282 + 4.283 + void m33() { 4.284 + try { 4.285 + checked(); 4.286 + } 4.287 + catch(InterruptedException exc) { } //ok 4.288 + } 4.289 + 4.290 + void m34() { 4.291 + try { 4.292 + runtime(); 4.293 + } 4.294 + catch(InterruptedException exc) { } //never thrown in try 4.295 + } 4.296 + 4.297 + void m35() { 4.298 + try { 4.299 + nothing(); 4.300 + } 4.301 + catch(InterruptedException exc) { } //never thrown in try 4.302 + } 4.303 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/6558548/T6558548_6.out Wed Mar 16 11:12:26 2011 +0000 5.3 @@ -0,0 +1,9 @@ 5.4 +- compiler.warn.source.no.bootclasspath: 1.6 5.5 +T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.6 +T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.7 +T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.8 +T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.9 +T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.10 +T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 5.11 +6 errors 5.12 +1 warning
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/6558548/T6558548_latest.out Wed Mar 16 11:12:26 2011 +0000 6.3 @@ -0,0 +1,23 @@ 6.4 +T6558548.java:20:9: compiler.warn.unreachable.catch: java.io.FileNotFoundException 6.5 +T6558548.java:134:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.6 +T6558548.java:142:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.7 +T6558548.java:151:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException 6.8 +T6558548.java:159:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.9 +T6558548.java:160:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.10 +T6558548.java:168:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.11 +T6558548.java:169:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.12 +T6558548.java:185:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.13 +T6558548.java:193:9: compiler.warn.unreachable.catch: java.lang.RuntimeException 6.14 +T6558548.java:211:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.15 +T6558548.java:220:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.16 +T6558548.java:230:9: compiler.warn.unreachable.catch.1: java.lang.InterruptedException,java.lang.RuntimeException,java.lang.Error 6.17 +T6558548.java:239:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.18 +T6558548.java:240:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.19 +T6558548.java:249:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.20 +T6558548.java:250:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.21 +T6558548.java:268:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.22 +T6558548.java:277:9: compiler.warn.unreachable.catch.1: java.lang.RuntimeException,java.lang.Error 6.23 +T6558548.java:291:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.24 +T6558548.java:298:9: compiler.err.except.never.thrown.in.try: java.lang.InterruptedException 6.25 +6 errors 6.26 +15 warnings
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/diags/examples/UnreachableCatch.java Wed Mar 16 11:12:26 2011 +0000 7.3 @@ -0,0 +1,35 @@ 7.4 +/* 7.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +// key: compiler.warn.unreachable.catch 7.28 + 7.29 +class UnreachableCatch { 7.30 + 7.31 + void test() { 7.32 + try { 7.33 + throw new java.io.FileNotFoundException(); 7.34 + } 7.35 + catch(java.io.FileNotFoundException exc) { } 7.36 + catch(java.io.IOException exc) { } //unreachable 7.37 + } 7.38 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/diags/examples/UnreachableCatch1.java Wed Mar 16 11:12:26 2011 +0000 8.3 @@ -0,0 +1,36 @@ 8.4 +/* 8.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 + 8.27 +// key: compiler.warn.unreachable.catch.1 8.28 + 8.29 +class UnreachableCatch1 { 8.30 + 8.31 + void test() { 8.32 + try { 8.33 + throw new IllegalArgumentException(); 8.34 + } 8.35 + catch(Error err) { } 8.36 + catch(RuntimeException rex) { } 8.37 + catch(Throwable t) { } //unreachable 8.38 + } 8.39 +}