# HG changeset patch # User mcimadamore # Date 1413284465 -3600 # Node ID 6c718c5086b320fa00d3a64b6e7853fb35bb812e # Parent 5b69a74c224eda19e3f6476a1655d08939e58b2d 8058511: StackOverflowError at com.sun.tools.javac.code.Types.lub Summary: Lub crashes when handling typevar with array bound Reviewed-by: vromero, dlsmith diff -r 5b69a74c224e -r 6c718c5086b3 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Oct 14 12:00:39 2014 +0100 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Tue Oct 14 12:01:05 2014 +0100 @@ -1889,7 +1889,12 @@ * Mapping to take element type of an arraytype */ private Mapping elemTypeFun = new Mapping ("elemTypeFun") { - public Type apply(Type t) { return elemtype(t); } + public Type apply(Type t) { + while (t.hasTag(TYPEVAR)) { + t = t.getUpperBound(); + } + return elemtype(t); + } }; /** @@ -3531,40 +3536,46 @@ } /** - * Return the least upper bound of pair of types. if the lub does + * Return the least upper bound of list of types. if the lub does * not exist return null. */ - public Type lub(Type t1, Type t2) { - return lub(List.of(t1, t2)); + public Type lub(List ts) { + return lub(ts.toArray(new Type[ts.length()])); } /** * Return the least upper bound (lub) of set of types. If the lub * does not exist return the type of null (bottom). */ - public Type lub(List ts) { + public Type lub(Type... ts) { + final int UNKNOWN_BOUND = 0; final int ARRAY_BOUND = 1; final int CLASS_BOUND = 2; - int boundkind = 0; - for (Type t : ts) { + + int[] kinds = new int[ts.length]; + + int boundkind = UNKNOWN_BOUND; + for (int i = 0 ; i < ts.length ; i++) { + Type t = ts[i]; switch (t.getTag()) { case CLASS: - boundkind |= CLASS_BOUND; + boundkind |= kinds[i] = CLASS_BOUND; break; case ARRAY: - boundkind |= ARRAY_BOUND; + boundkind |= kinds[i] = ARRAY_BOUND; break; case TYPEVAR: do { t = t.getUpperBound(); } while (t.hasTag(TYPEVAR)); if (t.hasTag(ARRAY)) { - boundkind |= ARRAY_BOUND; + boundkind |= kinds[i] = ARRAY_BOUND; } else { - boundkind |= CLASS_BOUND; + boundkind |= kinds[i] = CLASS_BOUND; } break; default: + kinds[i] = UNKNOWN_BOUND; if (t.isPrimitive()) return syms.errType; } @@ -3575,15 +3586,16 @@ case ARRAY_BOUND: // calculate lub(A[], B[]) - List elements = Type.map(ts, elemTypeFun); - for (Type t : elements) { - if (t.isPrimitive()) { + Type[] elements = new Type[ts.length]; + for (int i = 0 ; i < ts.length ; i++) { + Type elem = elements[i] = elemTypeFun.apply(ts[i]); + if (elem.isPrimitive()) { // if a primitive type is found, then return // arraySuperType unless all the types are the // same - Type first = ts.head; - for (Type s : ts.tail) { - if (!isSameType(first, s)) { + Type first = ts[0]; + for (int j = 1 ; j < ts.length ; j++) { + if (!isSameType(first, ts[j])) { // lub(int[], B[]) is Cloneable & Serializable return arraySuperType(); } @@ -3598,13 +3610,20 @@ case CLASS_BOUND: // calculate lub(A, B) - while (!ts.head.hasTag(CLASS) && !ts.head.hasTag(TYPEVAR)) { - ts = ts.tail; + int startIdx = 0; + for (int i = 0; i < ts.length ; i++) { + Type t = ts[i]; + if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) { + break; + } else { + startIdx++; + } } - Assert.check(!ts.isEmpty()); + Assert.check(startIdx < ts.length); //step 1 - compute erased candidate set (EC) - List cl = erasedSupertypes(ts.head); - for (Type t : ts.tail) { + List cl = erasedSupertypes(ts[startIdx]); + for (int i = startIdx + 1 ; i < ts.length ; i++) { + Type t = ts[i]; if (t.hasTag(CLASS) || t.hasTag(TYPEVAR)) cl = intersect(cl, erasedSupertypes(t)); } @@ -3613,9 +3632,9 @@ //step 3 - for each element G in MEC, compute lci(Inv(G)) List candidates = List.nil(); for (Type erasedSupertype : mec) { - List lci = List.of(asSuper(ts.head, erasedSupertype.tsym)); - for (Type t : ts) { - lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym))); + List lci = List.of(asSuper(ts[startIdx], erasedSupertype.tsym)); + for (int i = startIdx + 1 ; i < ts.length ; i++) { + lci = intersect(lci, List.of(asSuper(ts[i], erasedSupertype.tsym))); } candidates = candidates.appendList(lci); } @@ -3626,9 +3645,9 @@ default: // calculate lub(A, B[]) List classes = List.of(arraySuperType()); - for (Type t : ts) { - if (!t.hasTag(ARRAY)) // Filter out any arrays - classes = classes.prepend(t); + for (int i = 0 ; i < ts.length ; i++) { + if (kinds[i] != ARRAY_BOUND) // Filter out any arrays + classes = classes.prepend(ts[i]); } // lub(A, B[]) is lub(A, arraySuperType) return lub(classes); diff -r 5b69a74c224e -r 6c718c5086b3 langtools/test/tools/javac/generics/inference/8058511/T8058511a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8058511/T8058511a.java Tue Oct 14 12:01:05 2014 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 8058511 + * @summary StackOverflowError at com.sun.tools.javac.code.Types.lub + * @compile T8058511a.java + */ +class T8058511a { + void choose(Z z1, Z z2) { } + + void test(Class cd, Class cdarr) { + choose(cd, cdarr); + } +} diff -r 5b69a74c224e -r 6c718c5086b3 langtools/test/tools/javac/generics/inference/8058511/T8058511b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8058511/T8058511b.java Tue Oct 14 12:01:05 2014 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 8058511 + * @summary StackOverflowError at com.sun.tools.javac.code.Types.lub + * @compile T8058511b.java + */ +class T8058511b { + void test(Class cd, Class cdarr) { + ((false) ? cd : cdarr).toString(); + } +} diff -r 5b69a74c224e -r 6c718c5086b3 langtools/test/tools/javac/generics/inference/8058511/T8058511c.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8058511/T8058511c.java Tue Oct 14 12:01:05 2014 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 8058511 + * @summary StackOverflowError at com.sun.tools.javac.code.Types.lub + * @compile T8058511c.java + */ +import java.util.List; + +class T8058511c { + void test(List l) { + (true ? l.get(0) : l.get(0)).toString(); + } +}