JDK-6491592 : Compiler crashes on assignment operator
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-11-09
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b03Fixed
Description
class Test {
    public static void main(String... args) {
        Object o = null;  // o can be any reference type except String
        o += null;
    }
}

java.lang.ArrayIndexOutOfBoundsException: 277
        at com.sun.tools.javac.jvm.Code.mnem(Code.java:1953)
        at com.sun.tools.javac.jvm.Code.emitop0(Code.java:841)
        at com.sun.tools.javac.jvm.Gen.completeBinop(Gen.java:1992)
        at com.sun.tools.javac.jvm.Gen.visitAssignop(Gen.java:1766)
        at com.sun.tools.javac.tree.JCTree$JCAssignOp.accept(JCTree.java:1367)
        at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:813)
        at com.sun.tools.javac.jvm.Gen.visitExec(Gen.java:1570)
        at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1074)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:660)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:695)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:681)
        at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:732)
        at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:985)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:660)
        at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:695)
        at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:918)
        at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:854)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:639)
        at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:660)
        at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2163)
        at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:617)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1289)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1259)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:765)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:730)
        at com.sun.tools.javac.main.Main.compile(Main.java:353)
        at com.sun.tools.javac.main.Main.compile(Main.java:279)
        at com.sun.tools.javac.main.Main.compile(Main.java:270)
        at com.sun.tools.javac.Main.compile(Main.java:69)
        at com.sun.tools.javac.Main.main(Main.java:54)

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6491592 See also attachment 6491592.tar.gz.
09-11-2006

SUGGESTED FIX Index: j2se/src/share/classes/com/sun/tools/javac/comp/Attr.java --- /tmp/geta23225 2006-11-08 20:16:57.000000000 -0800 +++ /tmp/getb23225 2006-11-08 20:16:57.000000000 -0800 @@ -63,7 +63,6 @@ final TreeMaker make; final ConstFold cfolder; final Enter enter; - final TreeInfo treeinfo; final Target target; final Types types; final Annotate annotate; @@ -87,7 +86,6 @@ make = TreeMaker.instance(context); enter = Enter.instance(context); cfolder = ConstFold.instance(context); - treeinfo = TreeInfo.instance(context); target = Target.instance(context); types = Types.instance(context); annotate = Annotate.instance(context); @@ -1558,6 +1556,11 @@ owntype, operand); if (operator.kind == MTH) { + chk.checkOperator(tree.pos(), + (OperatorSymbol)operator, + tree.tag - JCTree.ASGOffset, + owntype, + operand); if (types.isSameType(operator.type.getReturnType(), syms.stringType)) { // String assignment; make sure the lhs is a string chk.checkType(tree.lhs.pos(), @@ -1622,14 +1625,11 @@ Type owntype = syms.errType; if (operator.kind == MTH) { owntype = operator.type.getReturnType(); - int opc = ((OperatorSymbol)operator).opcode; - - if (opc == ByteCodes.error) { - log.error(tree.lhs.pos(), - "operator.cant.be.applied", - treeinfo.operatorName(tree.tag), - left + "," + right); - } + int opc = chk.checkOperator(tree.lhs.pos(), + (OperatorSymbol)operator, + tree.tag, + left, + right); // If both arguments are constants, fold them. if (left.constValue() != null && right.constValue() != null) {
09-11-2006

SUGGESTED FIX Index: j2se/src/share/classes/com/sun/tools/javac/comp/Check.java --- /tmp/geta23218 2006-11-08 20:16:25.000000000 -0800 +++ /tmp/getb23218 2006-11-08 20:16:26.000000000 -0800 @@ -50,6 +50,7 @@ private final Source source; private final Types types; private final boolean skipAnnotations; + private final TreeInfo treeinfo; // The set of lint options currently in effect. It is initialized // from the context, and then is set/reset as needed by Attr as it @@ -75,6 +76,7 @@ target = Target.instance(context); source = Source.instance(context); lint = Lint.instance(context); + treeinfo = TreeInfo.instance(context); Source source = Source.instance(context); allowGenerics = source.allowGenerics(); @@ -1912,6 +1914,30 @@ **************************************************************************/ /** + * Return the opcode of the operator but emit an error if it is an + * error. + * @param pos position for error reporting. + * @param operator an operator + * @param tag a tree tag + * @param left type of left hand side + * @param right type of right hand side + */ + int checkOperator(DiagnosticPosition pos, + OperatorSymbol operator, + int tag, + Type left, + Type right) { + if (operator.opcode == ByteCodes.error) { + log.error(pos, + "operator.cant.be.applied", + treeinfo.operatorName(tag), + left + "," + right); + } + return operator.opcode; + } + + + /** * Check for division by integer constant zero * @param pos Position for error reporting. * @param operator The operator for the expression
09-11-2006

EVALUATION The error will look like this: Test.java:4: operator + cannot be applied to java.lang.Object,<nulltype> o += null; ^ 1 error
09-11-2006

EVALUATION JLS3 15.26.2 Compound Assignment Operators http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.2 "A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once." JLS3 15.18 Additive Operators http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.18 "If the type of either operand of a + operator is String, then the operation is string concatenation. Otherwise, the type of each of the operands of the + operator must be a type that is convertible (��5.1.8) to a primitive numeric type, or a compile-time error occurs." ��5.1.8 is unboxing conversion. *** Since ��15.26.2 states that o += null is equivalent to o = o + null we examine the rules in ��15.18 which clearly states that this is a compile- time error.
09-11-2006