8013357: javac accepts erroneous binary comparison operations

Thu, 27 Jun 2013 17:45:56 -0400

author
emc
date
Thu, 27 Jun 2013 17:45:56 -0400
changeset 1869
5c548a8542b8
parent 1868
97e798c06804
child 1870
6101e52ce9e3

8013357: javac accepts erroneous binary comparison operations
Summary: javac does not report type errors on illegal Object == primitive comparisons
Reviewed-by: abuckley, mcimadamore

src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/LambdaConv01.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/LambdaExpr15.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/typeInference/InferenceTest2b.java file | annotate | diff | comparison | revisions
test/tools/javac/types/TestComparisons.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jun 27 12:42:47 2013 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jun 27 17:45:56 2013 -0400
     1.3 @@ -1342,6 +1342,26 @@
     1.4      }
     1.5      // </editor-fold>
     1.6  
     1.7 +    /**
     1.8 +     * Can t and s be compared for equality?  Any primitive ==
     1.9 +     * primitive or primitive == object comparisons here are an error.
    1.10 +     * Unboxing and correct primitive == primitive comparisons are
    1.11 +     * already dealt with in Attr.visitBinary.
    1.12 +     *
    1.13 +     */
    1.14 +    public boolean isEqualityComparable(Type s, Type t, Warner warn) {
    1.15 +        if (t.isNumeric() && s.isNumeric())
    1.16 +            return true;
    1.17 +
    1.18 +        boolean tPrimitive = t.isPrimitive();
    1.19 +        boolean sPrimitive = s.isPrimitive();
    1.20 +        if (!tPrimitive && !sPrimitive) {
    1.21 +            return isCastable(s, t, warn) || isCastable(t, s, warn);
    1.22 +        } else {
    1.23 +            return false;
    1.24 +        }
    1.25 +    }
    1.26 +
    1.27      // <editor-fold defaultstate="collapsed" desc="isCastable">
    1.28      public boolean isCastable(Type t, Type s) {
    1.29          return isCastable(t, s, noWarnings);
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 27 12:42:47 2013 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 27 17:45:56 2013 -0400
     2.3 @@ -3010,6 +3010,8 @@
     2.4                  !left.isErroneous() &&
     2.5                  !right.isErroneous()) {
     2.6              owntype = operator.type.getReturnType();
     2.7 +            // This will figure out when unboxing can happen and
     2.8 +            // choose the right comparison operator.
     2.9              int opc = chk.checkOperator(tree.lhs.pos(),
    2.10                                          (OperatorSymbol)operator,
    2.11                                          tree.getTag(),
    2.12 @@ -3037,9 +3039,11 @@
    2.13              }
    2.14  
    2.15              // Check that argument types of a reference ==, != are
    2.16 -            // castable to each other, (JLS???).
    2.17 +            // castable to each other, (JLS 15.21).  Note: unboxing
    2.18 +            // comparisons will not have an acmp* opc at this point.
    2.19              if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) {
    2.20 -                if (!types.isCastable(left, right, new Warner(tree.pos()))) {
    2.21 +                if (!types.isEqualityComparable(left, right,
    2.22 +                                                new Warner(tree.pos()))) {
    2.23                      log.error(tree.pos(), "incomparable.types", left, right);
    2.24                  }
    2.25              }
     3.1 --- a/test/tools/javac/lambda/LambdaConv01.java	Thu Jun 27 12:42:47 2013 -0700
     3.2 +++ b/test/tools/javac/lambda/LambdaConv01.java	Thu Jun 27 17:45:56 2013 -0400
     3.3 @@ -67,7 +67,7 @@
     3.4          assertTrue(3 == f1.foo());
     3.5          //Covariant returns:
     3.6          TU<Number, Integer> f2 = (Integer x) -> x;
     3.7 -        assertTrue(3 == f2.foo(3));
     3.8 +        assertTrue(3 == f2.foo(3).intValue());
     3.9          //Method resolution with boxing:
    3.10          int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
    3.11          assertTrue(3 == res);
    3.12 @@ -86,7 +86,7 @@
    3.13          assertTrue(3 == f1.foo());
    3.14          //Covariant returns:
    3.15          TU<Number, Integer> f2 = (Integer x) -> x;
    3.16 -        assertTrue(3 == f2.foo(3));
    3.17 +        assertTrue(3 == f2.foo(3).intValue());
    3.18          //Method resolution with boxing:
    3.19          int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
    3.20          assertTrue(3 == res);
    3.21 @@ -105,7 +105,7 @@
    3.22          assertTrue(3 == f1.foo());
    3.23          //Covariant returns:
    3.24          TU<Number, Integer> f2 = (Integer x) -> x;
    3.25 -        assertTrue(3 == f2.foo(3));
    3.26 +        assertTrue(3 == f2.foo(3).intValue());
    3.27          //Method resolution with boxing:
    3.28          int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
    3.29          assertTrue(3 == res);
    3.30 @@ -124,7 +124,7 @@
    3.31          assertTrue(3 == f1.foo());
    3.32          //Covariant returns:
    3.33          TU<Number, Integer> f2 = (Integer x) -> x;
    3.34 -        assertTrue(3 == f2.foo(3));
    3.35 +        assertTrue(3 == f2.foo(3).intValue());
    3.36          //Method resolution with boxing:
    3.37          int res = LambdaConv01.<Integer,Integer>exec((Integer x) -> x, 3);
    3.38          assertTrue(3 == res);
     4.1 --- a/test/tools/javac/lambda/LambdaExpr15.java	Thu Jun 27 12:42:47 2013 -0700
     4.2 +++ b/test/tools/javac/lambda/LambdaExpr15.java	Thu Jun 27 17:45:56 2013 -0400
     4.3 @@ -48,7 +48,7 @@
     4.4              new Object() {
     4.5                  String get() { return ""; }
     4.6              };
     4.7 -            assertTrue(t == 1);
     4.8 +            assertTrue((Integer)t == 1);
     4.9          };
    4.10          ba1.apply(1);
    4.11  
    4.12 @@ -58,7 +58,7 @@
    4.13                  String get() { return ""; }
    4.14              };
    4.15              new A();
    4.16 -            assertTrue(t == 2);
    4.17 +            assertTrue((Integer)t == 2);
    4.18          };
    4.19          ba2.apply(2);
    4.20          assertTrue(assertionCount == 2);
     5.1 --- a/test/tools/javac/lambda/typeInference/InferenceTest2b.java	Thu Jun 27 12:42:47 2013 -0700
     5.2 +++ b/test/tools/javac/lambda/typeInference/InferenceTest2b.java	Thu Jun 27 17:45:56 2013 -0400
     5.3 @@ -64,7 +64,7 @@
     5.4  
     5.5      void m2(SAM6<? super Integer> s) {
     5.6          System.out.println("m2()");
     5.7 -        assertTrue(s.m6(1, 2) == 1);
     5.8 +        assertTrue(s.m6(1, 2).equals(Integer.valueOf(1)));
     5.9      }
    5.10  
    5.11      void m3(SAM6<? super Calendar> s) {
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/tools/javac/types/TestComparisons.java	Thu Jun 27 17:45:56 2013 -0400
     6.3 @@ -0,0 +1,362 @@
     6.4 +/*
     6.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.
    6.11 + *
    6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.15 + * version 2 for more details (a copy is included in the LICENSE file that
    6.16 + * accompanied this code).
    6.17 + *
    6.18 + * You should have received a copy of the GNU General Public License version
    6.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.21 + *
    6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.23 + * or visit www.oracle.com if you need additional information or have any
    6.24 + * questions.
    6.25 + */
    6.26 +
    6.27 +/*
    6.28 + * @test
    6.29 + * @bug 8013357
    6.30 + * @summary javac should correctly enforce binary comparison rules.
    6.31 + */
    6.32 +import com.sun.tools.javac.code.Type;
    6.33 +import com.sun.tools.javac.code.Type.*;
    6.34 +import com.sun.tools.javac.code.Symbol.*;
    6.35 +import java.io.*;
    6.36 +import java.lang.reflect.Array;
    6.37 +import java.util.EnumSet;
    6.38 +
    6.39 +public class TestComparisons {
    6.40 +
    6.41 +    private int errors = 0;
    6.42 +    private int testnum = 0;
    6.43 +
    6.44 +    static final File testdir = new File("8013357");
    6.45 +
    6.46 +    private enum CompareType {
    6.47 +        BYTE_PRIM("byte"),
    6.48 +        SHORT_PRIM("short"),
    6.49 +        CHAR_PRIM("char"),
    6.50 +        INTEGER_PRIM("int"),
    6.51 +        LONG_PRIM("long"),
    6.52 +        FLOAT_PRIM("float"),
    6.53 +        DOUBLE_PRIM("double"),
    6.54 +        BOOLEAN_PRIM("boolean"),
    6.55 +
    6.56 +        BYTE("Byte"),
    6.57 +        SHORT("Short"),
    6.58 +        CHAR("Character"),
    6.59 +        INTEGER("Integer"),
    6.60 +        LONG("Long"),
    6.61 +        FLOAT("Float"),
    6.62 +        DOUBLE("Double"),
    6.63 +        BOOLEAN("Boolean"),
    6.64 +
    6.65 +        BYTE_SUPER("List<? super Byte>", true),
    6.66 +        SHORT_SUPER("List<? super Short>", true),
    6.67 +        CHAR_SUPER("List<? super Character>", true),
    6.68 +        INTEGER_SUPER("List<? super Integer>", true),
    6.69 +        LONG_SUPER("List<? super Long>", true),
    6.70 +        FLOAT_SUPER("List<? super Float>", true),
    6.71 +        DOUBLE_SUPER("List<? super Double>", true),
    6.72 +        BOOLEAN_SUPER("List<? super Boolean>", true),
    6.73 +
    6.74 +        OBJECT("Object"),
    6.75 +        NUMBER("Number"),
    6.76 +        STRING("String");
    6.77 +
    6.78 +        public final boolean isList;
    6.79 +        public final String name;
    6.80 +
    6.81 +        private CompareType(final String name, final boolean isList) {
    6.82 +            this.isList = isList;
    6.83 +            this.name = name;
    6.84 +        }
    6.85 +
    6.86 +        private CompareType(final String name) {
    6.87 +            this(name, false);
    6.88 +        }
    6.89 +    }
    6.90 +
    6.91 +    // The integers here refer to which subsection of JLS 15.21 is in
    6.92 +    // effect.  0 means no comparison is allowed.
    6.93 +    private static final int truthtab[][] = {
    6.94 +        // byte, comparable to itself, any numeric type, or any boxed
    6.95 +        // numeric type.
    6.96 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
    6.97 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
    6.98 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
    6.99 +          0, 0, 0                 // Reference types
   6.100 +        },
   6.101 +        // short, comparable to itself, any numeric type, or any boxed
   6.102 +        // numeric type.
   6.103 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.104 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.105 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.106 +          0, 0, 0                 // Reference types
   6.107 +        },
   6.108 +        // char, comparable to itself, any numeric type, or any boxed
   6.109 +        // numeric type.
   6.110 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.111 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.112 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.113 +          0, 0, 0                 // Reference types
   6.114 +        },
   6.115 +        // int, comparable to itself, any numeric type, or any boxed
   6.116 +        // numeric type.
   6.117 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.118 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.119 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.120 +          0, 0, 0                 // Reference types
   6.121 +        },
   6.122 +        // long, comparable to itself, any numeric type, or any boxed
   6.123 +        // numeric type.
   6.124 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.125 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.126 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.127 +          0, 0, 0                 // Reference types
   6.128 +        },
   6.129 +        // float, comparable to itself, any numeric type, or any boxed
   6.130 +        // numeric type.
   6.131 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.132 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.133 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.134 +          0, 0, 0                 // Reference types
   6.135 +        },
   6.136 +        // double, comparable to itself, any numeric type, or any boxed
   6.137 +        // numeric type.
   6.138 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.139 +          1, 1, 1, 1, 1, 1, 1, 0, // Boxed primitives
   6.140 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.141 +          0, 0, 0                 // Reference types
   6.142 +        },
   6.143 +        // boolean, comparable only to itself and Boolean.
   6.144 +        { 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
   6.145 +          0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
   6.146 +          0, 0, 0, 0, 0, 0, 0, 0, // Captures
   6.147 +          0, 0, 0                 // Reference types
   6.148 +        },
   6.149 +        // Byte, comparable to itself, Number, Object, any numeric primitive,
   6.150 +        // and any captures.
   6.151 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.152 +          3, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
   6.153 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.154 +          3, 3, 0                 // Reference types
   6.155 +        },
   6.156 +        // Short, comparable to itself, Number, Object, any numeric primitive,
   6.157 +        // and any captures.
   6.158 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.159 +          0, 3, 0, 0, 0, 0, 0, 0, // Boxed primitives
   6.160 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.161 +          3, 3, 0                 // Reference types
   6.162 +        },
   6.163 +        // Character, comparable to itself, Object, any numeric primitive,
   6.164 +        // and any captures.
   6.165 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.166 +          0, 0, 3, 0, 0, 0, 0, 0, // Boxed primitives
   6.167 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.168 +          3, 0, 0                 // Reference types
   6.169 +        },
   6.170 +        // Int, comparable to itself, Number, Object, any numeric primitive,
   6.171 +        // and any captures.
   6.172 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.173 +          0, 0, 0, 3, 0, 0, 0, 0, // Boxed primitives
   6.174 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.175 +          3, 3, 0                 // Reference types
   6.176 +        },
   6.177 +        // Long, comparable to itself, Number, Object, any numeric primitive,
   6.178 +        // and any captures.
   6.179 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.180 +          0, 0, 0, 0, 3, 0, 0, 0, // Boxed primitives
   6.181 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.182 +          3, 3, 0                 // Reference types
   6.183 +        },
   6.184 +        // Float, comparable to itself, Number, Object, any numeric primitive,
   6.185 +        // and any captures.
   6.186 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.187 +          0, 0, 0, 0, 0, 3, 0, 0, // Boxed primitives
   6.188 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.189 +          3, 3, 0                 // Reference types
   6.190 +        },
   6.191 +        // Double, comparable to itself, Number, Object, any numeric primitive,
   6.192 +        // and any captures.
   6.193 +        { 1, 1, 1, 1, 1, 1, 1, 0, // Primitives
   6.194 +          0, 0, 0, 0, 0, 0, 3, 0, // Boxed primitives
   6.195 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.196 +          3, 3, 0                 // Reference types
   6.197 +        },
   6.198 +        // Boolean, to itself, any capture, Object, and boolean.
   6.199 +        { 0, 0, 0, 0, 0, 0, 0, 2, // Primitives
   6.200 +          0, 0, 0, 0, 0, 0, 0, 2, // Boxed primitives
   6.201 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.202 +          3, 0, 0                 // Reference types
   6.203 +        },
   6.204 +        // Byte supertype wildcard, comparable to any reference type.
   6.205 +        // and any captures.
   6.206 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.207 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.208 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.209 +          3, 3, 3                 // Reference types
   6.210 +        },
   6.211 +        // Short supertype wildcard, comparable to any reference type.
   6.212 +        // and any captures.
   6.213 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.214 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.215 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.216 +          3, 3, 3                 // Reference types
   6.217 +        },
   6.218 +        // Character supertype wildcard, comparable to any reference type.
   6.219 +        // and any captures.
   6.220 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.221 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.222 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.223 +          3, 3, 3                 // Reference types
   6.224 +        },
   6.225 +        // Integer supertype wildcard, comparable to any reference type.
   6.226 +        // and any captures.
   6.227 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.228 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.229 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.230 +          3, 3, 3                 // Reference types
   6.231 +        },
   6.232 +        // Long supertype wildcard, comparable to any reference type.
   6.233 +        // and any captures.
   6.234 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.235 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.236 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.237 +          3, 3, 3                 // Reference types
   6.238 +        },
   6.239 +        // Float supertype wildcard, comparable to any reference type.
   6.240 +        // and any captures.
   6.241 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.242 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.243 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.244 +          3, 3, 3                 // Reference types
   6.245 +        },
   6.246 +        // Double supertype wildcard, comparable to any reference type.
   6.247 +        // and any captures.
   6.248 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.249 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.250 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.251 +          3, 3, 3                 // Reference types
   6.252 +        },
   6.253 +        // Boolean supertype wildcard, comparable to any reference type.
   6.254 +        // and any captures.
   6.255 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.256 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.257 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.258 +          3, 3, 3                 // Reference types
   6.259 +        },
   6.260 +        // Object, comparable to any reference type.
   6.261 +        // and any captures.
   6.262 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.263 +          3, 3, 3, 3, 3, 3, 3, 3, // Boxed primitives
   6.264 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.265 +          3, 3, 3                 // Reference types
   6.266 +        },
   6.267 +        // Number, comparable to Object, any of its subclasses.
   6.268 +        // and any captures.
   6.269 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.270 +          3, 3, 0, 3, 3, 3, 3, 0, // Boxed primitives
   6.271 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.272 +          3, 3, 0                 // Reference types
   6.273 +        },
   6.274 +        // String supertype wildcard, comparable to any reference type.
   6.275 +        // and any captures.
   6.276 +        { 0, 0, 0, 0, 0, 0, 0, 0, // Primitives
   6.277 +          0, 0, 0, 0, 0, 0, 0, 0, // Boxed primitives
   6.278 +          3, 3, 3, 3, 3, 3, 3, 3, // Captures
   6.279 +          3, 0, 3                 // Reference types
   6.280 +        }
   6.281 +    };
   6.282 +
   6.283 +    private void assert_compile_fail(final File file, final String body) {
   6.284 +        final String filename = file.getPath();
   6.285 +        final String[] args = { filename };
   6.286 +        final StringWriter sw = new StringWriter();
   6.287 +        final PrintWriter pw = new PrintWriter(sw);
   6.288 +        final int rc = com.sun.tools.javac.Main.compile(args, pw);
   6.289 +        pw.close();
   6.290 +        if (rc == 0) {
   6.291 +            System.err.println("Compilation of " + file.getName() +
   6.292 +                               " didn't fail as expected.\nFile:\n" +
   6.293 +                               body + "\nOutput:\n" + sw.toString());
   6.294 +            errors++;
   6.295 +        }
   6.296 +    }
   6.297 +
   6.298 +    private void assert_compile_succeed(final File file, final String body) {
   6.299 +        final String filename = file.getPath();
   6.300 +        final String[] args = { filename };
   6.301 +        final StringWriter sw = new StringWriter();
   6.302 +        final PrintWriter pw = new PrintWriter(sw);
   6.303 +        final int rc = com.sun.tools.javac.Main.compile(args, pw);
   6.304 +        pw.close();
   6.305 +        if (rc != 0) {
   6.306 +            System.err.println("Compilation of " + file.getName() +
   6.307 +                               " didn't succeed as expected.\nFile:\n" +
   6.308 +                               body + "\nOutput:\n" +
   6.309 +                               sw.toString());
   6.310 +            errors++;
   6.311 +        }
   6.312 +    }
   6.313 +
   6.314 +    private String makeBody(final int num,
   6.315 +                            final CompareType left,
   6.316 +                            final CompareType right) {
   6.317 +        return "import java.util.List;\n" +
   6.318 +            "public class Test" + num + " {\n" +
   6.319 +            "    public boolean test(" + left.name +
   6.320 +            " left, " + right.name + " right) {\n" +
   6.321 +            "        return left" + (left.isList ? ".get(0)" : "") +
   6.322 +            " == right" + (right.isList ? ".get(0)" : "") + ";\n" +
   6.323 +            "    }\n" +
   6.324 +            "}\n";
   6.325 +    }
   6.326 +
   6.327 +    private File writeFile(final String filename,
   6.328 +                           final String body)
   6.329 +        throws IOException {
   6.330 +        final File f = new File(testdir, filename);
   6.331 +        f.getParentFile().mkdirs();
   6.332 +        final FileWriter out = new FileWriter(f);
   6.333 +        out.write(body);
   6.334 +        out.close();
   6.335 +        return f;
   6.336 +    }
   6.337 +
   6.338 +    private void test(final CompareType left, final CompareType right)
   6.339 +        throws IOException {
   6.340 +        final int num = testnum++;
   6.341 +        final String filename = "Test" + num + ".java";
   6.342 +        final String body = makeBody(num, left, right);
   6.343 +        final File file = writeFile(filename, body);
   6.344 +        if (truthtab[left.ordinal()][right.ordinal()] != 0)
   6.345 +            assert_compile_succeed(file, body);
   6.346 +        else
   6.347 +            assert_compile_fail(file, body);
   6.348 +    }
   6.349 +
   6.350 +    void run() throws Exception {
   6.351 +        testdir.mkdir();
   6.352 +
   6.353 +        for(CompareType left : CompareType.values())
   6.354 +            for(CompareType right : CompareType.values())
   6.355 +                test(left, right);
   6.356 +
   6.357 +        if (errors != 0)
   6.358 +            throw new Exception("ObjectZeroCompare test failed with " +
   6.359 +                                errors + " errors.");
   6.360 +    }
   6.361 +
   6.362 +    public static void main(String... args) throws Exception {
   6.363 +        new TestComparisons().run();
   6.364 +    }
   6.365 +}

mercurial