### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java,v retrieving revision 1.57.4.1 diff -u -r1.57.4.1 LocalDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 2 Jul 2006 10:11:34 -0000 1.57.4.1 +++ compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java 5 Sep 2006 13:09:29 -0000 @@ -32,11 +32,10 @@ this.declarationEnd = sourceEnd; } -public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, - FlowInfo flowInfo) { +public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { // record variable initialization if any if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { - bits |= IsLocalDeclarationReachable; // only set if actually reached + bits |= ASTNode.IsLocalDeclarationReachable; // only set if actually reached } if (this.initialization == null) { return flowInfo; @@ -46,6 +45,11 @@ this.initialization .analyseCode(currentScope, flowContext, flowInfo) .unconditionalInits(); + if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes + this.bits |= FirstAssignmentToLocal; + } else { + this.bits &= ~FirstAssignmentToLocal; // int i = (i = 0); + } flowInfo.markAsDefinitelyAssigned(binding); if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) { switch(nullStatus) { @@ -89,49 +93,33 @@ return; } int pc = codeStream.position; - Constant inlinedValue; // something to initialize? - if (initialization != null) { - // initialize to constant value? - if ((inlinedValue = initialization.constant) != Constant.NotAConstant) { - // forget initializing unused or final locals set to constant value (final ones are inlined) - if (binding.resolvedPosition != -1) { // may need to preserve variable - int initPC = codeStream.position; - codeStream.generateConstant(inlinedValue, initialization.implicitConversion); - codeStream.recordPositionsFrom(initPC, initialization.sourceStart); - codeStream.store(binding, false); - binding.recordInitializationStartPC(codeStream.position); - // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index - // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index - } - } else { // initializing to non-constant value - initialization.generateCode(currentScope, codeStream, true); + generateInit: { + if (this.initialization == null) + break generateInit; + // forget initializing unused or final locals set to constant value (final ones are inlined) + if (binding.resolvedPosition < 0) { + if (initialization.constant != Constant.NotAConstant) + break generateInit; // if binding unused generate then discard the value - if (binding.resolvedPosition != -1) { - // 26903, need extra cast to store null in array local var - if (binding.type.isArrayType() - && (initialization.resolvedType == TypeBinding.NULL // arrayLoc = null - || ((initialization instanceof CastExpression) // arrayLoc = (type[])null - && (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ - codeStream.checkcast(binding.type); - } - codeStream.store(binding, false); - if (binding.initializationCount == 0) { - /* Variable may have been initialized during the code initializing it - e.g. int i = (i = 1); - */ - binding.recordInitializationStartPC(codeStream.position); - // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index - // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index - } - } else { - if ((binding.type == TypeBinding.LONG) || (binding.type == TypeBinding.DOUBLE)) { - codeStream.pop2(); - } else { - codeStream.pop(); - } - } + initialization.generateCode(currentScope, codeStream, false); + break generateInit; + } + initialization.generateCode(currentScope, codeStream, true); + // 26903, need extra cast to store null in array local var + if (binding.type.isArrayType() + && (initialization.resolvedType == TypeBinding.NULL // arrayLoc = null + || ((initialization instanceof CastExpression) // arrayLoc = (type[])null + && (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ + codeStream.checkcast(binding.type); + } + codeStream.store(binding, false); + if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { + /* Variable may have been initialized during the code initializing it + e.g. int i = (i = 1); + */ + binding.recordInitializationStartPC(codeStream.position); } } codeStream.recordPositionsFrom(pc, this.sourceStart); Index: compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java,v retrieving revision 1.71 diff -u -r1.71 ASTNode.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 11 May 2006 10:22:12 -0000 1.71 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java 5 Sep 2006 13:09:23 -0000 @@ -26,7 +26,7 @@ public final static int Bit1 = 0x1; // return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement) public final static int Bit2 = 0x2; // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl) public final static int Bit3 = 0x4; // return type (operator) | name reference kind (name ref) | implicit this (this ref) - public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl) + public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl) public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref) public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) @@ -108,6 +108,8 @@ // for name references public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3; + + // for name refs or local decls public static final int FirstAssignmentToLocal = Bit4; // for this reference @@ -119,10 +121,12 @@ // for statements public static final int IsReachable = Bit32; - public static final int IsLocalDeclarationReachable = Bit31; public static final int LabelUsed = Bit7; public static final int DocumentedFallthrough = Bit30; + // local decls + public static final int IsLocalDeclarationReachable = Bit31; + // try statements public static final int IsSubRoutineEscaping = Bit15; public static final int IsTryBlockExiting = Bit30; Index: compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java,v retrieving revision 1.102.4.1 diff -u -r1.102.4.1 Expression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 2 Jul 2006 10:11:31 -0000 1.102.4.1 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java 5 Sep 2006 13:09:26 -0000 @@ -530,15 +530,16 @@ scope.problemReporter().autoboxing(this, compileTimeType, runtimeType); compileTimeType = unboxedType; } - } else { - if (compileTimeType != TypeBinding.NULL && compileTimeType.isBaseType()) { - TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType); - if (boxedType == runtimeType) // Object o = 12; - boxedType = compileTimeType; - this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id; - scope.problemReporter().autoboxing(this, compileTimeType, scope.environment().computeBoxingType(boxedType)); - return; - } + } else if (compileTimeType != TypeBinding.NULL && compileTimeType.isBaseType()) { + TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType); + if (boxedType == runtimeType) // Object o = 12; + boxedType = compileTimeType; + this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id; + scope.problemReporter().autoboxing(this, compileTimeType, scope.environment().computeBoxingType(boxedType)); + return; + } else if (this.constant != Constant.NotAConstant && this.constant.typeID() != T_JavaLangString) { + this.implicitConversion = BOXING; + return; } int compileTimeTypeID, runtimeTypeID; if ((compileTimeTypeID = compileTimeType.id) == NoId) { // e.g. ? extends String ==> String (103227) Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.133.4.2 diff -u -r1.133.4.2 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 23 Aug 2006 15:34:15 -0000 1.133.4.2 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 5 Sep 2006 13:09:48 -0000 @@ -1727,37 +1727,34 @@ } public void generateConstant(Constant constant, int implicitConversionCode) { int targetTypeID = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; - if (targetTypeID != 0) { - switch (targetTypeID) { - case TypeIds.T_boolean : - generateInlinedValue(constant.booleanValue()); - break; - case TypeIds.T_char : - generateInlinedValue(constant.charValue()); - break; - case TypeIds.T_byte : - generateInlinedValue(constant.byteValue()); - break; - case TypeIds.T_short : - generateInlinedValue(constant.shortValue()); - break; - case TypeIds.T_int : - generateInlinedValue(constant.intValue()); - break; - case TypeIds.T_long : - generateInlinedValue(constant.longValue()); - break; - case TypeIds.T_float : - generateInlinedValue(constant.floatValue()); - break; - case TypeIds.T_double : - generateInlinedValue(constant.doubleValue()); - break; - case TypeIds.T_JavaLangString : - ldc(constant.stringValue()); - } - } else { - ldc(constant.stringValue()); + if (targetTypeID == 0) targetTypeID = constant.typeID(); // use default constant type + switch (targetTypeID) { + case TypeIds.T_boolean : + generateInlinedValue(constant.booleanValue()); + break; + case TypeIds.T_char : + generateInlinedValue(constant.charValue()); + break; + case TypeIds.T_byte : + generateInlinedValue(constant.byteValue()); + break; + case TypeIds.T_short : + generateInlinedValue(constant.shortValue()); + break; + case TypeIds.T_int : + generateInlinedValue(constant.intValue()); + break; + case TypeIds.T_long : + generateInlinedValue(constant.longValue()); + break; + case TypeIds.T_float : + generateInlinedValue(constant.floatValue()); + break; + case TypeIds.T_double : + generateInlinedValue(constant.doubleValue()); + break; + case TypeIds.T_JavaLangString : + ldc(constant.stringValue()); } if ((implicitConversionCode & TypeIds.BOXING) != 0) { // need boxing #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java,v retrieving revision 1.96.4.2 diff -u -r1.96.4.2 AutoBoxingTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java 4 Sep 2006 16:26:38 -0000 1.96.4.2 +++ src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java 5 Sep 2006 13:10:07 -0000 @@ -3648,4 +3648,94 @@ "Type mismatch: cannot convert from int to Byte\n" + "----------\n"); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255 +public void test123() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String[] args) {\n" + + " foo1();\n" + + " foo2();\n" + + " foo3();\n" + + " foo4();\n" + + " System.out.println(\"[done]\");\n" + + " }\n" + + " static void foo1() {\n" + + " Object x = true ? true : \"\";\n" + + " System.out.print(\"[1:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + " static void foo2() {\n" + + " Object x = Boolean.TRUE != null ? true : \"\";\n" + + " System.out.print(\"[2:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + " static void foo3() {\n" + + " Object x = false ? \"\" : false;\n" + + " System.out.print(\"[3:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + " static void foo4() {\n" + + " Object x = Boolean.TRUE == null ? \"\" : false;\n" + + " System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + "}", // ================= + }, + "[1:true,java.lang.Boolean][2:true,java.lang.Boolean][3:false,java.lang.Boolean][4:false,java.lang.Boolean][done]"); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255 - variation +public void test124() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " static void foo5() {\n" + + " boolean x = false ? \"\" : false;\n" + + " System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " } \n" + + "}", // ================= + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " boolean x = false ? \"\" : false;\n" + + " ^^^^^^^^^^^^^^^^^^\n" + + "Type mismatch: cannot convert from Object&Serializable&Comparable to boolean\n" + + "----------\n" + + "2. WARNING in X.java (at line 3)\n" + + " boolean x = false ? \"\" : false;\n" + + " ^^^^^\n" + + "The expression of type boolean is boxed into Boolean\n" + + "----------\n" + + "3. ERROR in X.java (at line 4)\n" + + " System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " ^^^^^^^^^^^^\n" + + "Cannot invoke getClass() on the primitive type boolean\n" + + "----------\n"); + } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255 - variation +public void test125() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " public static void main(String[] args) {\n" + + " foo1();\n" + + " foo2();\n" + + " foo3();\n" + + " System.out.println(\"[done]\");\n" + + " }\n" + + " static void foo1() {\n" + + " Object x = true ? 3.0f : false;\n" + + " System.out.print(\"[1:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + " static void foo2() {\n" + + " Object x = true ? 2 : false;\n" + + " System.out.print(\"[2:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + " static void foo3() {\n" + + " Object x = false ? 2 : false;\n" + + " System.out.print(\"[3:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + + " }\n" + + "}\n", // ================= + }, + "[1:3.0,java.lang.Float][2:2,java.lang.Integer][3:false,java.lang.Boolean][done]"); + } } Index: src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java,v retrieving revision 1.25.4.1 diff -u -r1.25.4.1 TryStatementTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java 23 Aug 2006 15:33:59 -0000 1.25.4.1 +++ src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java 5 Sep 2006 13:10:13 -0000 @@ -2723,8 +2723,8 @@ " 79 ldc [32]\n" + " 81 invokevirtual java.io.PrintStream.print(java.lang.String) : void [23]\n" + " 84 aconst_null\n" + - " 85 astore 6\n" + - " 87 aload 6\n" + + " 85 astore 6 [o]\n" + + " 87 aload 6 [o]\n" + " 89 invokevirtual java.lang.Object.toString() : java.lang.String [34]\n" + " 92 pop\n" + " 93 aload 4\n" + @@ -2768,7 +2768,8 @@ " [pc: 60, pc: 71] local: e index: 1 type: java.lang.Exception\n" + " [pc: 22, pc: 39] local: var index: 5 type: int\n" + " [pc: 76, pc: 93] local: var index: 5 type: int\n" + - " [pc: 33, pc: 39] local: o index: 6 type: java.lang.Object\n" + " [pc: 33, pc: 39] local: o index: 6 type: java.lang.Object\n" + + " [pc: 87, pc: 93] local: o index: 6 type: java.lang.Object\n" : " // Method descriptor #6 ()V\n" + " // Stack: 2, Locals: 8\n" + " public void save();\n" +