--- /dev/null 2013-06-10 07:32:35.840590318 -0400 +++ new/test/tools/javac/8013357/TestComparisons.java 2013-06-10 17:32:31.674424228 -0400 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2013, 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 8013357 + * @summary javac should correctly enforce binary comparison rules. + */ +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.Symbol.*; +import java.io.*; +import java.lang.reflect.Array; +import java.util.EnumSet; + +public class TestComparisons { + + private int errors = 0; + private int testnum = 0; + + static final File testdir = new File("8013357"); + + private enum CompareType { + OBJECT("Object"), + NUMBER("Number"), + STRING("String"), + LONG("Long"), + INTEGER("Integer"), + SHORT("Short"), + + BOOLEAN("Boolean"), + DOUBLE("Double"), + FLOAT("Float"), + CHAR("Character"), + LONG_SUPER("List", true), + INTEGER_SUPER("List", true), + + SHORT_SUPER("List", true), + BOOLEAN_SUPER("List", true), + DOUBLE_SUPER("List", true), + FLOAT_SUPER("List", true), + CHAR_SUPER("List", true), + LONG_PRIM("long"), + + INTEGER_PRIM("int"), + SHORT_PRIM("short"), + BOOLEAN_PRIM("boolean"), + DOUBLE_PRIM("double"), + FLOAT_PRIM("float"), + CHAR_PRIM("char"); + + public final boolean isList; + public final String name; + + private CompareType(final String name, final boolean isList) { + this.isList = isList; + this.name = name; + } + + private CompareType(final String name) { + this(name, false); + } + } + + private static final boolean truthtab[][] = { + // Object, comparable to everything but primitives. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Number, any boxed form of a numeric primitive, and any + // captures. + { true, true, false, true, true, true, + false, true, true, false, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // String, comparable only to Object and String. + { true, false, true, false, false, false, + false, false, false, false, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Long, comparable to itself, Number, any numeric primitive, + // and any captures. + { true, true, false, true, false, false, + false, false, false, false, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + // Integer, comparable to itself, Number, any numeric + // primitive, and any captures. + { true, true, false, false, true, false, + false, false, false, false, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + // Short, comparable to itself, Number, any numeric primitive, + // and any captures. + { true, true, false, false, false, true, + false, false, false, false, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + + // Boolean, comparable to itself, boolean, and any captures + { true, false, false, false, false, false, + true, false, false, false, true, true, + true, true, true, true, true, false, + false, false, true, false, false, false }, + // Double, comparable to itself, Number, any numeric + // primitive, and any captures. + { true, true, false, false, false, false, + false, true, false, false, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + // Float, comparable to itself, Number, any numeric primitive, + // and any captures. + { true, true, false, false, false, false, + false, false, true, false, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + // Character, comparable to itself, any numeric primitive, and + // any captures. + { true, false, false, false, false, false, + false, false, false, true, true, true, + true, true, true, true, true, true, + true, true, false, true, true, true }, + // Long supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Integer supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + + // Short supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Boolean supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Double supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Float supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // Character supertype wildcard, comparable to any reference type. + { true, true, true, true, true, true, + true, true, true, true, true, true, + true, true, true, true, true, false, + false, false, false, false, false, false }, + // long, comparable to any numeric or boxed numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true }, + + // int, comparable to itself, any numeric type, or any boxed + // numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true }, + // short, comparable to itself, any numeric type, or any boxed + // numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true }, + // boolean, comparable only to itself and Boolean. + { false, false, false, false, false, false, + true, false, false, false, false, false, + false, false, false, false, false, false, + false, false, true, false, false, false }, + // double, comparable to itself, any numeric type, or any + // boxed numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true }, + // float, comparable to itself, any numeric type, or any boxed + // numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true }, + // char, comparable to itself, any numeric type, or any boxed + // numeric type. + { false, false, false, true, true, true, + false, true, true, true, false, false, + false, false, false, false, false, true, + true, true, false, true, true, true } + }; + + private void assert_compile_fail(final File file, final String body) { + final String filename = file.getPath(); + final String[] args = { filename }; + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + final int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + if (rc == 0) { + System.err.println("Compilation of " + file.getName() + + " didn't fail as expected.\nFile:\n" + + body + "\nOutput:\n" + sw.toString()); + errors++; + } + } + + private void assert_compile_succeed(final File file, final String body) { + final String filename = file.getPath(); + final String[] args = { filename }; + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + final int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + if (rc != 0) { + System.err.println("Compilation of " + file.getName() + + " didn't succeed as expected.\nFile:\n" + + body + "\nOutput:\n" + + sw.toString()); + errors++; + } + } + + private String makeBody(final int num, + final CompareType left, + final CompareType right) { + return "import java.util.List;\n" + + "public class Test" + num + " {\n" + + " public boolean test(" + left.name + + " left, " + right.name + " right) {\n" + + " return left" + (left.isList ? ".get(0)" : "") + + " == right" + (right.isList ? ".get(0)" : "") + ";\n" + + " }\n" + + "}\n"; + } + + private File writeFile(final String filename, + final String body) + throws IOException { + final File f = new File(testdir, filename); + f.getParentFile().mkdirs(); + final FileWriter out = new FileWriter(f); + out.write(body); + out.close(); + return f; + } + + private void test(final CompareType left, final CompareType right) + throws IOException { + final int num = testnum++; + final String filename = "Test" + num + ".java"; + final String body = makeBody(num, left, right); + final File file = writeFile(filename, body); + if (truthtab[left.ordinal()][right.ordinal()]) + assert_compile_succeed(file, body); + else + assert_compile_fail(file, body); + } + + void run() throws Exception { + testdir.mkdir(); + + for(CompareType left : CompareType.values()) + for(CompareType right : CompareType.values()) + test(left, right); + + if (errors != 0) + throw new Exception("ObjectZeroCompare test failed with " + + errors + " errors."); + } + + public static void main(String... args) throws Exception { + new TestComparisons().run(); + } +}