# HG changeset patch # User mcimadamore # Date 1301413231 -3600 # Node ID 76b505d190260454ef2045c166d484fdf9e1675d # Parent a29adf86aa0c3e8c4e0e6af4514ab927a7e1ffc1 7030606: Project-coin: multi-catch types should be pairwise disjoint Summary: Bring javac in sync with latest Project Coin EDR Reviewed-by: jjg diff -r a29adf86aa0c -r 76b505d19026 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- 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); } diff -r a29adf86aa0c -r 76b505d19026 langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties --- 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'' diff -r a29adf86aa0c -r 76b505d19026 langtools/test/tools/javac/diags/examples/MulticatchTypesMustBeDisjoint.java --- /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) { } + } +} diff -r a29adf86aa0c -r 76b505d19026 langtools/test/tools/javac/multicatch/7030606/DisjunctiveTypeWellFormednessTest.java --- /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 { + + int errorsFound; + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR && + diagnostic.getCode().startsWith("compiler.err.multicatch.types.must.be.disjoint")) { + errorsFound++; + } + } + } +} diff -r a29adf86aa0c -r 76b505d19026 langtools/test/tools/javac/multicatch/7030606/T7030606.java --- /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) { } + } +} diff -r a29adf86aa0c -r 76b505d19026 langtools/test/tools/javac/multicatch/7030606/T7030606.out --- /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