View | Details | Raw Unified | Return to bug 155255 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java (-43 / +31 lines)
Lines 32-42 Link Here
32
		this.declarationEnd = sourceEnd;
32
		this.declarationEnd = sourceEnd;
33
	}
33
	}
34
34
35
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
35
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
36
		FlowInfo flowInfo) {
37
	// record variable initialization if any
36
	// record variable initialization if any
38
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
37
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
39
		bits |= IsLocalDeclarationReachable; // only set if actually reached
38
		bits |= ASTNode.IsLocalDeclarationReachable; // only set if actually reached
40
	}
39
	}
41
	if (this.initialization == null) { 
40
	if (this.initialization == null) { 
42
		return flowInfo;
41
		return flowInfo;
Lines 46-51 Link Here
46
		this.initialization
45
		this.initialization
47
			.analyseCode(currentScope, flowContext, flowInfo)
46
			.analyseCode(currentScope, flowContext, flowInfo)
48
			.unconditionalInits();
47
			.unconditionalInits();
48
	if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
49
		this.bits |= FirstAssignmentToLocal;
50
	} else {
51
		this.bits &= ~FirstAssignmentToLocal;  // int i = (i = 0);
52
	}	
49
	flowInfo.markAsDefinitelyAssigned(binding);
53
	flowInfo.markAsDefinitelyAssigned(binding);
50
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
54
	if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
51
		switch(nullStatus) {
55
		switch(nullStatus) {
Lines 89-137 Link Here
89
			return;
93
			return;
90
		}
94
		}
91
		int pc = codeStream.position;
95
		int pc = codeStream.position;
92
		Constant inlinedValue;
93
96
94
		// something to initialize?
97
		// something to initialize?
95
		if (initialization != null) {
98
		generateInit: {
96
			// initialize to constant value?
99
			if (this.initialization == null) 
97
			if ((inlinedValue = initialization.constant) != Constant.NotAConstant) {
100
				break generateInit;
98
				// forget initializing unused or final locals set to constant value (final ones are inlined)
101
			// forget initializing unused or final locals set to constant value (final ones are inlined)
99
				if (binding.resolvedPosition != -1) { // may need to preserve variable
102
			if (binding.resolvedPosition < 0) {
100
					int initPC = codeStream.position;
103
				if (initialization.constant != Constant.NotAConstant) 
101
					codeStream.generateConstant(inlinedValue, initialization.implicitConversion);
104
					break generateInit;
102
					codeStream.recordPositionsFrom(initPC, initialization.sourceStart);
103
					codeStream.store(binding, false);
104
					binding.recordInitializationStartPC(codeStream.position);
105
					//				codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index 
106
					//				codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index		
107
				}
108
			} else { // initializing to non-constant value
109
				initialization.generateCode(currentScope, codeStream, true);
110
				// if binding unused generate then discard the value
105
				// if binding unused generate then discard the value
111
				if (binding.resolvedPosition != -1) {
106
				initialization.generateCode(currentScope, codeStream, false);
112
					// 26903, need extra cast to store null in array local var	
107
				break generateInit;
113
					if (binding.type.isArrayType() 
108
			}			
114
						&& (initialization.resolvedType == TypeBinding.NULL	// arrayLoc = null
109
			initialization.generateCode(currentScope, codeStream, true);
115
							|| ((initialization instanceof CastExpression)	// arrayLoc = (type[])null
110
			// 26903, need extra cast to store null in array local var	
116
								&& (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){
111
			if (binding.type.isArrayType() 
117
						codeStream.checkcast(binding.type); 
112
				&& (initialization.resolvedType == TypeBinding.NULL	// arrayLoc = null
118
					}					
113
					|| ((initialization instanceof CastExpression)	// arrayLoc = (type[])null
119
					codeStream.store(binding, false);
114
						&& (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){
120
					if (binding.initializationCount == 0) {
115
				codeStream.checkcast(binding.type); 
121
						/* Variable may have been initialized during the code initializing it
116
			}					
122
							e.g. int i = (i = 1);
117
			codeStream.store(binding, false);
123
						*/
118
			if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) {
124
						binding.recordInitializationStartPC(codeStream.position);
119
				/* Variable may have been initialized during the code initializing it
125
						//					codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index 
120
					e.g. int i = (i = 1);
126
						//					codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index 
121
				*/
127
					}
122
				binding.recordInitializationStartPC(codeStream.position);
128
				} else {
129
					if ((binding.type == TypeBinding.LONG) || (binding.type == TypeBinding.DOUBLE)) {
130
						codeStream.pop2();
131
					} else {
132
						codeStream.pop();
133
					}
134
				}
135
			}
123
			}
136
		}
124
		}
137
		codeStream.recordPositionsFrom(pc, this.sourceStart);
125
		codeStream.recordPositionsFrom(pc, this.sourceStart);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java (-2 / +6 lines)
Lines 26-32 Link Here
26
	public final static int Bit1 = 0x1; 						// return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
26
	public final static int Bit1 = 0x1; 						// return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
27
	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
27
	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
28
	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
28
	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
29
	public final static int Bit4 = 0x8; 						// return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
29
	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)
30
	public final static int Bit5 = 0x10; 						// value for return (expression) | has all method bodies (unit) | supertype ref (type ref)
30
	public final static int Bit5 = 0x10; 						// value for return (expression) | has all method bodies (unit) | supertype ref (type ref)
31
	public final static int Bit6 = 0x20; 						// depth (name ref, msg) | ignore need cast check (cast expression)
31
	public final static int Bit6 = 0x20; 						// depth (name ref, msg) | ignore need cast check (cast expression)
32
	public final static int Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement)
32
	public final static int Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement)
Lines 108-113 Link Here
108
	
108
	
109
	// for name references 
109
	// for name references 
110
	public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;	
110
	public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;	
111
	
112
	// for name refs or local decls
111
	public static final int FirstAssignmentToLocal = Bit4;
113
	public static final int FirstAssignmentToLocal = Bit4;
112
	
114
	
113
	// for this reference
115
	// for this reference
Lines 119-128 Link Here
119
121
120
	// for statements 
122
	// for statements 
121
	public static final int IsReachable = Bit32; 
123
	public static final int IsReachable = Bit32; 
122
	public static final int IsLocalDeclarationReachable = Bit31; 
123
	public static final int LabelUsed = Bit7;
124
	public static final int LabelUsed = Bit7;
124
	public static final int DocumentedFallthrough = Bit30;
125
	public static final int DocumentedFallthrough = Bit30;
125
	
126
	
127
	// local decls
128
	public static final int IsLocalDeclarationReachable = Bit31; 
129
	
126
	// try statements
130
	// try statements
127
	public static final int IsSubRoutineEscaping = Bit15;
131
	public static final int IsSubRoutineEscaping = Bit15;
128
	public static final int IsTryBlockExiting = Bit30;
132
	public static final int IsTryBlockExiting = Bit30;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java (-9 / +10 lines)
Lines 530-544 Link Here
530
				scope.problemReporter().autoboxing(this, compileTimeType, runtimeType);
530
				scope.problemReporter().autoboxing(this, compileTimeType, runtimeType);
531
				compileTimeType = unboxedType;
531
				compileTimeType = unboxedType;
532
			}
532
			}
533
		} else {
533
		} else if (compileTimeType != TypeBinding.NULL && compileTimeType.isBaseType()) {
534
			if (compileTimeType != TypeBinding.NULL && compileTimeType.isBaseType()) {
534
			TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType);
535
				TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType);
535
			if (boxedType == runtimeType) // Object o = 12;
536
				if (boxedType == runtimeType) // Object o = 12;
536
				boxedType = compileTimeType; 
537
					boxedType = compileTimeType; 
537
			this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id;
538
				this.implicitConversion = BOXING | (boxedType.id << 4) + compileTimeType.id;
538
			scope.problemReporter().autoboxing(this, compileTimeType, scope.environment().computeBoxingType(boxedType));
539
				scope.problemReporter().autoboxing(this, compileTimeType, scope.environment().computeBoxingType(boxedType));
539
			return;
540
				return;
540
		} else if (this.constant != Constant.NotAConstant && this.constant.typeID() != T_JavaLangString) {
541
			}
541
			this.implicitConversion = BOXING;
542
			return;
542
		}
543
		}
543
		int compileTimeTypeID, runtimeTypeID;
544
		int compileTimeTypeID, runtimeTypeID;
544
		if ((compileTimeTypeID = compileTimeType.id) == NoId) { // e.g. ? extends String  ==> String (103227)
545
		if ((compileTimeTypeID = compileTimeType.id) == NoId) { // e.g. ? extends String  ==> String (103227)
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-31 / +28 lines)
Lines 1727-1763 Link Here
1727
}
1727
}
1728
public void generateConstant(Constant constant, int implicitConversionCode) {
1728
public void generateConstant(Constant constant, int implicitConversionCode) {
1729
	int targetTypeID = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
1729
	int targetTypeID = (implicitConversionCode & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
1730
	if (targetTypeID != 0) {
1730
	if (targetTypeID == 0) targetTypeID = constant.typeID(); // use default constant type
1731
		switch (targetTypeID) {
1731
	switch (targetTypeID) {
1732
			case TypeIds.T_boolean :
1732
		case TypeIds.T_boolean :
1733
				generateInlinedValue(constant.booleanValue());
1733
			generateInlinedValue(constant.booleanValue());
1734
				break;
1734
			break;
1735
			case TypeIds.T_char :
1735
		case TypeIds.T_char :
1736
				generateInlinedValue(constant.charValue());
1736
			generateInlinedValue(constant.charValue());
1737
				break;
1737
			break;
1738
			case TypeIds.T_byte :
1738
		case TypeIds.T_byte :
1739
				generateInlinedValue(constant.byteValue());
1739
			generateInlinedValue(constant.byteValue());
1740
				break;
1740
			break;
1741
			case TypeIds.T_short :
1741
		case TypeIds.T_short :
1742
				generateInlinedValue(constant.shortValue());
1742
			generateInlinedValue(constant.shortValue());
1743
				break;
1743
			break;
1744
			case TypeIds.T_int :
1744
		case TypeIds.T_int :
1745
				generateInlinedValue(constant.intValue());
1745
			generateInlinedValue(constant.intValue());
1746
				break;
1746
			break;
1747
			case TypeIds.T_long :
1747
		case TypeIds.T_long :
1748
				generateInlinedValue(constant.longValue());
1748
			generateInlinedValue(constant.longValue());
1749
				break;
1749
			break;
1750
			case TypeIds.T_float :
1750
		case TypeIds.T_float :
1751
				generateInlinedValue(constant.floatValue());
1751
			generateInlinedValue(constant.floatValue());
1752
				break;
1752
			break;
1753
			case TypeIds.T_double :
1753
		case TypeIds.T_double :
1754
				generateInlinedValue(constant.doubleValue());
1754
			generateInlinedValue(constant.doubleValue());
1755
				break;
1755
			break;
1756
			case TypeIds.T_JavaLangString :
1756
		case TypeIds.T_JavaLangString :
1757
				ldc(constant.stringValue());
1757
			ldc(constant.stringValue());
1758
		}
1759
	} else {
1760
		ldc(constant.stringValue());
1761
	}
1758
	}
1762
	if ((implicitConversionCode & TypeIds.BOXING) != 0) {
1759
	if ((implicitConversionCode & TypeIds.BOXING) != 0) {
1763
		// need boxing
1760
		// need boxing
(-)src/org/eclipse/jdt/core/tests/compiler/regression/AutoBoxingTest.java (+90 lines)
Lines 3648-3651 Link Here
3648
		"Type mismatch: cannot convert from int to Byte\n" + 
3648
		"Type mismatch: cannot convert from int to Byte\n" + 
3649
		"----------\n");
3649
		"----------\n");
3650
}
3650
}
3651
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255
3652
public void test123() {
3653
	this.runConformTest(
3654
		new String[] {
3655
			"X.java",
3656
			"public class X {\n" + 
3657
			"	public static void main(String[] args) {\n" + 
3658
			"		foo1();\n" + 
3659
			"		foo2();\n" + 
3660
			"		foo3();\n" + 
3661
			"		foo4();\n" + 
3662
			"		System.out.println(\"[done]\");\n" + 
3663
			"	}\n" + 
3664
			"	static void foo1() {\n" + 
3665
			"		Object x = true ? true : \"\";\n" + 
3666
			"		System.out.print(\"[1:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3667
			"	}\n" + 
3668
			"	static void foo2() {\n" + 
3669
			"		Object x = Boolean.TRUE != null ? true : \"\";\n" + 
3670
			"		System.out.print(\"[2:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3671
			"	}\n" + 
3672
			"	static void foo3() {\n" + 
3673
			"		Object x = false ? \"\" : false;\n" + 
3674
			"		System.out.print(\"[3:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3675
			"	}\n" + 
3676
			"	static void foo4() {\n" + 
3677
			"		Object x = Boolean.TRUE == null ? \"\" : false;\n" + 
3678
			"		System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3679
			"	}\n" + 
3680
			"}", // =================
3681
		},
3682
		"[1:true,java.lang.Boolean][2:true,java.lang.Boolean][3:false,java.lang.Boolean][4:false,java.lang.Boolean][done]");
3683
}
3684
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255 - variation
3685
public void test124() {
3686
	this.runNegativeTest(
3687
		new String[] {
3688
			"X.java",
3689
			"public class X {\n" + 
3690
			"	static void foo5() {\n" + 
3691
			"		boolean x = false ? \"\" : false;\n" + 
3692
			"		System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3693
			"	}	\n" + 
3694
			"}", // =================
3695
		},
3696
		"----------\n" + 
3697
		"1. ERROR in X.java (at line 3)\n" + 
3698
		"	boolean x = false ? \"\" : false;\n" + 
3699
		"	            ^^^^^^^^^^^^^^^^^^\n" + 
3700
		"Type mismatch: cannot convert from Object&Serializable&Comparable<?> to boolean\n" + 
3701
		"----------\n" + 
3702
		"2. WARNING in X.java (at line 3)\n" + 
3703
		"	boolean x = false ? \"\" : false;\n" + 
3704
		"	                         ^^^^^\n" + 
3705
		"The expression of type boolean is boxed into Boolean\n" + 
3706
		"----------\n" + 
3707
		"3. ERROR in X.java (at line 4)\n" + 
3708
		"	System.out.print(\"[4:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3709
		"	                                  ^^^^^^^^^^^^\n" + 
3710
		"Cannot invoke getClass() on the primitive type boolean\n" + 
3711
		"----------\n");
3712
	}
3713
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=155255 - variation
3714
public void test125() {
3715
	this.runConformTest(
3716
		new String[] {
3717
			"X.java",
3718
			"public class X {\n" + 
3719
			"	public static void main(String[] args) {\n" + 
3720
			"		foo1();\n" + 
3721
			"		foo2();\n" + 
3722
			"		foo3();\n" + 
3723
			"		System.out.println(\"[done]\");\n" + 
3724
			"	}\n" + 
3725
			"	static void foo1() {\n" + 
3726
			"		Object x = true ? 3.0f : false;\n" + 
3727
			"		System.out.print(\"[1:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3728
			"	}\n" + 
3729
			"	static void foo2() {\n" + 
3730
			"		Object x = true ? 2 : false;\n" + 
3731
			"		System.out.print(\"[2:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3732
			"	}\n" + 
3733
			"	static void foo3() {\n" + 
3734
			"		Object x = false ? 2 : false;\n" + 
3735
			"		System.out.print(\"[3:\"+ x + \",\" + x.getClass().getCanonicalName() + \"]\");\n" + 
3736
			"	}\n" + 
3737
			"}\n", // =================
3738
		},
3739
		"[1:3.0,java.lang.Float][2:2,java.lang.Integer][3:false,java.lang.Boolean][done]");
3740
	}
3651
}
3741
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/TryStatementTest.java (-3 / +4 lines)
Lines 2723-2730 Link Here
2723
			"    79  ldc <String \"[finally]\"> [32]\n" + 
2723
			"    79  ldc <String \"[finally]\"> [32]\n" + 
2724
			"    81  invokevirtual java.io.PrintStream.print(java.lang.String) : void [23]\n" + 
2724
			"    81  invokevirtual java.io.PrintStream.print(java.lang.String) : void [23]\n" + 
2725
			"    84  aconst_null\n" + 
2725
			"    84  aconst_null\n" + 
2726
			"    85  astore 6\n" + 
2726
			"    85  astore 6 [o]\n" + 
2727
			"    87  aload 6\n" + 
2727
			"    87  aload 6 [o]\n" + 
2728
			"    89  invokevirtual java.lang.Object.toString() : java.lang.String [34]\n" + 
2728
			"    89  invokevirtual java.lang.Object.toString() : java.lang.String [34]\n" + 
2729
			"    92  pop\n" + 
2729
			"    92  pop\n" + 
2730
			"    93  aload 4\n" + 
2730
			"    93  aload 4\n" + 
Lines 2768-2774 Link Here
2768
			"        [pc: 60, pc: 71] local: e index: 1 type: java.lang.Exception\n" + 
2768
			"        [pc: 60, pc: 71] local: e index: 1 type: java.lang.Exception\n" + 
2769
			"        [pc: 22, pc: 39] local: var index: 5 type: int\n" + 
2769
			"        [pc: 22, pc: 39] local: var index: 5 type: int\n" + 
2770
			"        [pc: 76, pc: 93] local: var index: 5 type: int\n" + 
2770
			"        [pc: 76, pc: 93] local: var index: 5 type: int\n" + 
2771
			"        [pc: 33, pc: 39] local: o index: 6 type: java.lang.Object\n"
2771
			"        [pc: 33, pc: 39] local: o index: 6 type: java.lang.Object\n" + 
2772
			"        [pc: 87, pc: 93] local: o index: 6 type: java.lang.Object\n"
2772
	: 		"  // Method descriptor #6 ()V\n" + 
2773
	: 		"  // Method descriptor #6 ()V\n" + 
2773
			"  // Stack: 2, Locals: 8\n" + 
2774
			"  // Stack: 2, Locals: 8\n" + 
2774
			"  public void save();\n" + 
2775
			"  public void save();\n" + 

Return to bug 155255