From 74f6de685922bc68b8ed16a5ffac7c15eab4f4f2 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Mon, 2 Feb 2015 18:52:16 +0530 Subject: [PATCH] 8069265: ClassCastException when compiled with JDK 9b08+, JDK8 compiles OK Alternate fix for 8015499 to eliminate extra checkcast (by working around a limitation in Types#asSuper) without the side effect that results in 8069265 Reviewed-by: mcimadamore, jjg --- .../com/sun/tools/javac/code/Types.java | 7 +- .../com/sun/tools/javac/comp/TransTypes.java | 6 +- .../classes/com/sun/tools/javac/jvm/Gen.java | 3 +- .../javac/CheckNoClassCastException.java | 69 +++++++++++++++++++ .../tools/javac/T7053059/DoubleCastTest.java | 3 +- 5 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 langtools/test/tools/javac/CheckNoClassCastException.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index fd71de9498f..4e18e017534 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -1931,6 +1931,11 @@ public class Types { * Return the (most specific) base type of t that starts with the * given symbol. If none exists, return null. * + * Caveat Emptor: Since javac represents the class of all arrays with a singleton + * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant, + * this method could yield surprising answers when invoked on arrays. For example when + * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null. + * * @param t a type * @param sym a symbol */ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java index 23b712ef759..933c64e9a82 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -720,7 +720,7 @@ public class TransTypes extends TreeTranslator { public void visitParens(JCParens tree) { tree.expr = translate(tree.expr, pt); - tree.type = erasure(tree.type); + tree.type = erasure(tree.expr.type); result = tree; } @@ -755,7 +755,7 @@ public class TransTypes extends TreeTranslator { tree.clazz = translate(tree.clazz, null); Type originalTarget = tree.type; tree.type = erasure(tree.type); - JCExpression newExpression = translate(tree.expr, erasure(tree.expr.type)); + JCExpression newExpression = translate(tree.expr, tree.type); if (newExpression != tree.expr) { JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) ? (JCTypeCast) newExpression diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index df229409a1f..d971bdb9db4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -2145,7 +2145,8 @@ public class Gen extends JCTree.Visitor { // For basic types, the coerce(...) in genExpr(...) will do // the conversion. if (!tree.clazz.type.isPrimitive() && - types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) { + !types.isSameType(tree.expr.type, tree.clazz.type) && + types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) { code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type)); } } diff --git a/langtools/test/tools/javac/CheckNoClassCastException.java b/langtools/test/tools/javac/CheckNoClassCastException.java new file mode 100644 index 00000000000..cb992d0205c --- /dev/null +++ b/langtools/test/tools/javac/CheckNoClassCastException.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, 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 8069265 + * @summary ClassCastException when compiled with JDK 9b08+, JDK8 compiles OK. + * @run main CheckNoClassCastException + */ +import java.util.*; + +public class CheckNoClassCastException { + static String result = ""; + public static void main(String[] args) { + ListFail.main(null); + MapFail.main(null); + if (!result.equals("ListFailDoneMapFailDone")) + throw new AssertionError("Incorrect result"); + } +} + +class ListFail { + static interface Foo { + } + + public static void main(String[] args) { + List list = new ArrayList<>(); + list.add(new Date()); + + List cList = (List) (List) list; + Date date = (Date) cList.get(0); + CheckNoClassCastException.result += "ListFailDone"; + } +} + + +class MapFail { + static interface Foo { + } + + public static void main(String[] args) { + Map aMap = new HashMap<>(); + aMap.put("test",new Date()); + + Map m = (Map) (Map) aMap; + Date q = (Date) m.get("test"); + CheckNoClassCastException.result += "MapFailDone"; + } +} diff --git a/langtools/test/tools/javac/T7053059/DoubleCastTest.java b/langtools/test/tools/javac/T7053059/DoubleCastTest.java index 6c96bd930d3..2cf65ba6410 100644 --- a/langtools/test/tools/javac/T7053059/DoubleCastTest.java +++ b/langtools/test/tools/javac/T7053059/DoubleCastTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -47,6 +47,7 @@ public class DoubleCastTest { m1((byte[])m()); m1((byte[])os[0]); m1((byte[])this.x); + m1((byte[])((byte []) (o = null))); } }