7030606: Project-coin: multi-catch types should be pairwise disjoint
Summary: Bring javac in sync with latest Project Coin EDR
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Mar 29 16:40:07 2011 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Mar 29 16:40:31 2011 +0100
@@ -2901,7 +2901,23 @@
ctype = chk.checkType(typeTree.pos(),
chk.checkClassType(typeTree.pos(), ctype),
syms.throwableType);
- multicatchTypes.append(ctype);
+ if (!ctype.isErroneous()) {
+ //check that alternatives of a disjunctive type are pairwise
+ //unrelated w.r.t. subtyping
+ if (chk.intersects(ctype, multicatchTypes.toList())) {
+ for (Type t : multicatchTypes) {
+ boolean sub = types.isSubtype(ctype, t);
+ boolean sup = types.isSubtype(t, ctype);
+ if (sub || sup) {
+ //assume 'a' <: 'b'
+ Type a = sub ? ctype : t;
+ Type b = sub ? t : ctype;
+ log.error(typeTree.pos(), "multicatch.types.must.be.disjoint", a, b);
+ }
+ }
+ }
+ multicatchTypes.append(ctype);
+ }
}
tree.type = result = check(tree, types.lub(multicatchTypes.toList()), TYP, pkind, pt);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 29 16:40:07 2011 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 29 16:40:31 2011 +0100
@@ -302,6 +302,11 @@
compiler.err.multicatch.parameter.may.not.be.assigned=\
multi-catch parameter {0} may not be assigned
+# 0: type, 1: type
+compiler.err.multicatch.types.must.be.disjoint=\
+ Alternatives in a multi-catch statement cannot be related by subclassing\n\
+ Alternative {0} is a subclass of alternative {1}
+
compiler.err.finally.without.try=\
''finally'' without ''try''
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/MulticatchTypesMustBeDisjoint.java Tue Mar 29 16:40:31 2011 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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.err.multicatch.types.must.be.disjoint
+
+class MulticatchTypesMustBeDisjoint {
+ class E1 extends Exception { }
+ class E2 extends E1 { }
+
+ void e1() throws E1 { }
+ void e2() throws E2 { }
+
+ void m() {
+ try {
+ e1();
+ e2();
+ } catch (E1 | E2 e) { }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java Tue Mar 29 16:40:31 2011 +0100
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7030606
+ * @summary Project-coin: multi-catch types should be pairwise disjoint
+ */
+
+import com.sun.source.util.JavacTask;
+import java.net.URI;
+import java.util.Arrays;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+public class DisjunctiveTypeWellFormednessTest {
+
+ enum Alternative {
+ EXCEPTION("Exception"),
+ RUNTIME_EXCEPTION("RuntimeException"),
+ IO_EXCEPTION("java.io.IOException"),
+ FILE_NOT_FOUND_EXCEPTION("java.io.FileNotFoundException"),
+ ILLEGAL_ARGUMENT_EXCEPTION("IllegalArgumentException");
+
+ String exceptionStr;
+
+ private Alternative(String exceptionStr) {
+ this.exceptionStr = exceptionStr;
+ }
+
+ static String makeDisjunctiveType(Alternative... alternatives) {
+ StringBuilder buf = new StringBuilder();
+ String sep = "";
+ for (Alternative alternative : alternatives) {
+ buf.append(sep);
+ buf.append(alternative.exceptionStr);
+ sep = "|";
+ }
+ return buf.toString();
+ }
+
+ boolean disjoint(Alternative that) {
+ return disjoint[this.ordinal()][that.ordinal()];
+ }
+
+ static boolean[][] disjoint = {
+ // Exception RuntimeException IOException FileNotFoundException IllegalArgumentException
+ /*Exception*/ { false, false, false, false, false },
+ /*RuntimeException*/ { false, false, true, true, false },
+ /*IOException*/ { false, true, false, false, true },
+ /*FileNotFoundException*/ { false, true, false, false, true },
+ /*IllegalArgumentException*/ { false, false, true, true, false }
+ };
+ }
+
+ enum Arity {
+ ONE(1),
+ TWO(2),
+ THREE(3),
+ FOUR(4),
+ FIVE(5);
+
+ int n;
+
+ private Arity(int n) {
+ this.n = n;
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+
+ //create default shared JavaCompiler - reused across multiple compilations
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
+
+ for (Arity arity : Arity.values()) {
+ for (Alternative a1 : Alternative.values()) {
+ if (arity == Arity.ONE) {
+ new DisjunctiveTypeWellFormednessTest(a1).run(comp, fm);
+ continue;
+ }
+ for (Alternative a2 : Alternative.values()) {
+ if (arity == Arity.TWO) {
+ new DisjunctiveTypeWellFormednessTest(a1, a2).run(comp, fm);
+ continue;
+ }
+ for (Alternative a3 : Alternative.values()) {
+ if (arity == Arity.THREE) {
+ new DisjunctiveTypeWellFormednessTest(a1, a2, a3).run(comp, fm);
+ continue;
+ }
+ for (Alternative a4 : Alternative.values()) {
+ if (arity == Arity.FOUR) {
+ new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4).run(comp, fm);
+ continue;
+ }
+ for (Alternative a5 : Alternative.values()) {
+ new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5).run(comp, fm);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Alternative[] alternatives;
+ JavaSource source;
+ DiagnosticChecker diagChecker;
+
+ DisjunctiveTypeWellFormednessTest(Alternative... alternatives) {
+ this.alternatives = alternatives;
+ this.source = new JavaSource();
+ this.diagChecker = new DiagnosticChecker();
+ }
+
+ class JavaSource extends SimpleJavaFileObject {
+
+ String template = "class Test {\n" +
+ "void test() {\n" +
+ "try {} catch (#T e) {}\n" +
+ "}\n" +
+ "}\n";
+
+ String source;
+
+ public JavaSource() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ source = template.replace("#T", Alternative.makeDisjunctiveType(alternatives));
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+ void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
+ JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
+ null, null, Arrays.asList(source));
+ ct.analyze();
+ check();
+ }
+
+ void check() {
+
+ int non_disjoint = 0;
+ int i = 0;
+ for (Alternative a1 : alternatives) {
+ int j = 0;
+ for (Alternative a2 : alternatives) {
+ if (i == j) continue;
+ if (!a1.disjoint(a2)) {
+ non_disjoint++;
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+
+ if (non_disjoint != diagChecker.errorsFound) {
+ throw new Error("invalid diagnostics for source:\n" +
+ source.getCharContent(true) +
+ "\nFound errors: " + diagChecker.errorsFound +
+ "\nExpected errors: " + non_disjoint);
+ }
+ }
+
+ static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+ int errorsFound;
+
+ public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+ if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
+ diagnostic.getCode().startsWith("compiler.err.multicatch.types.must.be.disjoint")) {
+ errorsFound++;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/7030606/T7030606.java Tue Mar 29 16:40:31 2011 +0100
@@ -0,0 +1,57 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 7030606
+ *
+ * @summary Project-coin: multi-catch types should be pairwise disjoint
+ * @compile/fail/ref=T7030606.out -XDrawDiagnostics T7030606.java
+ */
+
+class T7030606 {
+ class E1 extends Exception { }
+ class E2 extends E1 { }
+
+ void e1() throws E1 { }
+ void e2() throws E2 { }
+
+ void m1() {
+ try {
+ e1();
+ e2();
+ } catch (NonExistentType | E2 | E1 e) { }
+ }
+
+ void m2() {
+ try {
+ e1();
+ e2();
+ } catch (NonExistentType | E1 | E2 e) { }
+ }
+
+ void m3() {
+ try {
+ e1();
+ e2();
+ } catch (E2 | NonExistentType | E1 e) { }
+ }
+
+ void m4() {
+ try {
+ e1();
+ e2();
+ } catch (E1 | NonExistentType | E2 e) { }
+ }
+
+ void m5() {
+ try {
+ e1();
+ e2();
+ } catch (E2 | E1 | NonExistentType e) { }
+ }
+
+ void m6() {
+ try {
+ e1();
+ e2();
+ } catch (E1 | E2 | NonExistentType e) { }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/7030606/T7030606.out Tue Mar 29 16:40:31 2011 +0100
@@ -0,0 +1,13 @@
+T7030606.java:20:18: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+T7030606.java:20:41: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:27:18: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+T7030606.java:27:41: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:34:23: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+T7030606.java:34:41: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:41:23: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+T7030606.java:41:41: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:48:23: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:48:28: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+T7030606.java:55:23: compiler.err.multicatch.types.must.be.disjoint: T7030606.E2, T7030606.E1
+T7030606.java:55:28: compiler.err.cant.resolve.location: kindname.class, NonExistentType, , , (compiler.misc.location: kindname.class, T7030606, null)
+12 errors