blob: 7d6d98abc68910f8df3d144c55ed793a38491af6 [file] [log] [blame]
/*
* Copyright (c) 2013, 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 8013357
* @summary javac should correctly enforce binary comparison rules.
* @modules jdk.compiler
*/
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 {
BYTE_PRIM("byte"),
SHORT_PRIM("short"),
CHAR_PRIM("char"),
INTEGER_PRIM("int"),
LONG_PRIM("long"),
FLOAT_PRIM("float"),
DOUBLE_PRIM("double"),
BOOLEAN_PRIM("boolean"),
BYTE("Byte"),
SHORT("Short"),
CHAR("Character"),
INTEGER("Integer"),
LONG("Long"),
FLOAT("Float"),
DOUBLE("Double"),
BOOLEAN("Boolean"),
BYTE_SUPER("List<? super Byte>", true),
SHORT_SUPER("List<? super Short>", true),
CHAR_SUPER("List<? super Character>", true),
INTEGER_SUPER("List<? super Integer>", true),
LONG_SUPER("List<? super Long>", true),
FLOAT_SUPER("List<? super Float>", true),
DOUBLE_SUPER("List<? super Double>", true),
BOOLEAN_SUPER("List<? super Boolean>", true),
OBJECT("Object"),
NUMBER("Number"),
STRING("String");
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);
}
}
// The integers here refer to which subsection of JLS 15.21 is in
// effect. 0 means no comparison is allowed.
private static final int truthtab[][] = {
// byte, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// short, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// char, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// int, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// long, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// float, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// double, comparable to itself, any numeric type, or any boxed
// numeric type.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// boolean, comparable only to itself and Boolean.
{ 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
0, 0, 0, 0, 0, 0, 0, 0, // Captures
0, 0, 0 // Reference types
},
// Byte, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
3, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Short, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 3, 0, 0, 0, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Character, comparable to itself, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 0, 3, 0, 0, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 0, 0 // Reference types
},
// Int, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 0, 0, 3, 0, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Long, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 0, 0, 0, 3, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Float, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 0, 0, 0, 0, 3, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Double, comparable to itself, Number, Object, any numeric primitive,
// and any captures.
{ 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
0, 0, 0, 0, 0, 0, 3, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// Boolean, to itself, any capture, Object, and boolean.
{ 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 0, 0 // Reference types
},
// Byte supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Short supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Character supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Integer supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Long supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Float supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Double supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Boolean supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Object, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 3 // Reference types
},
// Number, comparable to Object, any of its subclasses.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
3, 3, 0, 3, 3, 3, 3, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 3, 0 // Reference types
},
// String supertype wildcard, comparable to any reference type.
// and any captures.
{ 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
0, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
3, 3, 3, 3, 3, 3, 3, 3, // Captures
3, 0, 3 // Reference types
}
};
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()] != 0)
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();
}
}