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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-2 / +4 lines)
Lines 189-195 Link Here
189
		return;
189
		return;
190
	}
190
	}
191
	if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
191
	if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
192
			|| ((implicitConversion & TypeIds.UNBOXING) != 0)) {
192
			|| ((implicitConversion & TypeIds.UNBOXING) != 0)
193
			|| (this.genericCast != null)) {
193
		receiver.generateCode(currentScope, codeStream, !isStatic);
194
		receiver.generateCode(currentScope, codeStream, !isStatic);
194
		pc = codeStream.position;
195
		pc = codeStream.position;
195
		if (this.codegenBinding.declaringClass == null) { // array length
196
		if (this.codegenBinding.declaringClass == null) { // array length
Lines 210-217 Link Here
210
			} else {
211
			} else {
211
				codeStream.invokestatic(syntheticAccessors[READ]);
212
				codeStream.invokestatic(syntheticAccessors[READ]);
212
			}
213
			}
214
			// required cast must occur even if no value is required
215
			if (this.genericCast != null) codeStream.checkcast(this.genericCast);
213
			if (valueRequired) {
216
			if (valueRequired) {
214
				if (this.genericCast != null) codeStream.checkcast(this.genericCast);
215
				codeStream.generateImplicitConversion(implicitConversion);
217
				codeStream.generateImplicitConversion(implicitConversion);
216
			} else {
218
			} else {
217
				if ((implicitConversion & TypeIds.UNBOXING) != 0) {
219
				if ((implicitConversion & TypeIds.UNBOXING) != 0) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-90 / +105 lines)
Lines 19-31 Link Here
19
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
19
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
20
20
21
public class SingleNameReference extends NameReference implements OperatorIds {
21
public class SingleNameReference extends NameReference implements OperatorIds {
22
    
22
23
	public static final int READ = 0;
23
	public static final int READ = 0;
24
	public static final int WRITE = 1;
24
	public static final int WRITE = 1;
25
	public char[] token;
25
	public char[] token;
26
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
26
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
27
	public TypeBinding genericCast;
27
	public TypeBinding genericCast;
28
	
28
29
	public SingleNameReference(char[] source, long pos) {
29
	public SingleNameReference(char[] source, long pos) {
30
		super();
30
		super();
31
		token = source;
31
		token = source;
Lines 33-46 Link Here
33
		sourceEnd = (int) pos;
33
		sourceEnd = (int) pos;
34
	}
34
	}
35
	public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
35
	public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
36
	
36
37
		boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0;
37
		boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0;
38
		// compound assignment extra work
38
		// compound assignment extra work
39
		if (isCompound) { // check the variable part is initialized if blank final
39
		if (isCompound) { // check the variable part is initialized if blank final
40
			switch (bits & RestrictiveFlagMASK) {
40
			switch (bits & RestrictiveFlagMASK) {
41
				case Binding.FIELD : // reading a field
41
				case Binding.FIELD : // reading a field
42
					FieldBinding fieldBinding;
42
					FieldBinding fieldBinding;
43
					if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
43
					if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
44
							&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
44
							&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
45
						if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
45
						if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
46
							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
46
							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
Lines 68-74 Link Here
68
		switch (bits & RestrictiveFlagMASK) {
68
		switch (bits & RestrictiveFlagMASK) {
69
			case Binding.FIELD : // assigning to a field
69
			case Binding.FIELD : // assigning to a field
70
				manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
70
				manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
71
	
71
72
				FieldBinding fieldBinding = (FieldBinding) binding;
72
				FieldBinding fieldBinding = (FieldBinding) binding;
73
				ReferenceBinding declaringClass = fieldBinding.declaringClass;
73
				ReferenceBinding declaringClass = fieldBinding.declaringClass;
74
				// check if accessing enum static field in initializer
74
				// check if accessing enum static field in initializer
Lines 82-88 Link Here
82
							&& methodScope.isInsideInitializerOrConstructor()) {
82
							&& methodScope.isInsideInitializerOrConstructor()) {
83
						currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
83
						currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
84
					}
84
					}
85
				}					
85
				}
86
				// check if assigning a final field
86
				// check if assigning a final field
87
				if (fieldBinding.isFinal()) {
87
				if (fieldBinding.isFinal()) {
88
					// inside a context where allowed
88
					// inside a context where allowed
Lines 90-96 Link Here
90
						if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
90
						if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
91
							currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
91
							currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
92
						} else {
92
						} else {
93
							flowContext.recordSettingFinal(fieldBinding, this, flowInfo);						
93
							flowContext.recordSettingFinal(fieldBinding, this, flowInfo);
94
						}
94
						}
95
						flowInfo.markAsDefinitelyAssigned(fieldBinding);
95
						flowInfo.markAsDefinitelyAssigned(fieldBinding);
96
					} else {
96
					} else {
Lines 98-104 Link Here
98
					}
98
					}
99
				}
99
				}
100
				break;
100
				break;
101
			case Binding.LOCAL : // assigning to a local variable 
101
			case Binding.LOCAL : // assigning to a local variable
102
				LocalVariableBinding localBinding = (LocalVariableBinding) binding;
102
				LocalVariableBinding localBinding = (LocalVariableBinding) binding;
103
				if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
103
				if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
104
					bits |= FirstAssignmentToLocal;
104
					bits |= FirstAssignmentToLocal;
Lines 113-119 Link Here
113
						} else if (flowInfo.isPotentiallyAssigned(localBinding)) {
113
						} else if (flowInfo.isPotentiallyAssigned(localBinding)) {
114
							currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
114
							currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
115
						} else {
115
						} else {
116
							flowContext.recordSettingFinal(localBinding, this, flowInfo);								
116
							flowContext.recordSettingFinal(localBinding, this, flowInfo);
117
						}
117
						}
118
					} else {
118
					} else {
119
						currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
119
						currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
Lines 131-137 Link Here
131
		return analyseCode(currentScope, flowContext, flowInfo, true);
131
		return analyseCode(currentScope, flowContext, flowInfo, true);
132
	}
132
	}
133
	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
133
	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
134
	
134
135
		switch (bits & RestrictiveFlagMASK) {
135
		switch (bits & RestrictiveFlagMASK) {
136
			case Binding.FIELD : // reading a field
136
			case Binding.FIELD : // reading a field
137
				if (valueRequired) {
137
				if (valueRequired) {
Lines 150-156 Link Here
150
							&& methodScope.isInsideInitializerOrConstructor()) {
150
							&& methodScope.isInsideInitializerOrConstructor()) {
151
						currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
151
						currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
152
					}
152
					}
153
				}				
153
				}
154
				// check if reading a final blank field
154
				// check if reading a final blank field
155
				if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
155
				if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
156
					if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
156
					if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
Lines 174-184 Link Here
174
		}
174
		}
175
		return flowInfo;
175
		return flowInfo;
176
	}
176
	}
177
	
177
178
	public TypeBinding checkFieldAccess(BlockScope scope) {
178
	public TypeBinding checkFieldAccess(BlockScope scope) {
179
	
179
180
		FieldBinding fieldBinding = (FieldBinding) binding;
180
		FieldBinding fieldBinding = (FieldBinding) binding;
181
		
181
182
		bits &= ~RestrictiveFlagMASK; // clear bits
182
		bits &= ~RestrictiveFlagMASK; // clear bits
183
		bits |= Binding.FIELD;
183
		bits |= Binding.FIELD;
184
		MethodScope methodScope = scope.methodScope();
184
		MethodScope methodScope = scope.methodScope();
Lines 192-201 Link Here
192
			}
192
			}
193
		}
193
		}
194
		this.constant = fieldBinding.constant();
194
		this.constant = fieldBinding.constant();
195
	
195
196
		if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0))
196
		if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0))
197
			scope.problemReporter().deprecatedField(fieldBinding, this);
197
			scope.problemReporter().deprecatedField(fieldBinding, this);
198
	
198
199
		if ((this.bits & IsStrictlyAssigned) == 0
199
		if ((this.bits & IsStrictlyAssigned) == 0
200
				&& methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
200
				&& methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
201
				&& methodScope.lastVisibleFieldID >= 0
201
				&& methodScope.lastVisibleFieldID >= 0
Lines 205-240 Link Here
205
			this.bits |= ASTNode.IgnoreNoEffectAssignCheck;
205
			this.bits |= ASTNode.IgnoreNoEffectAssignCheck;
206
		}
206
		}
207
		return fieldBinding.type;
207
		return fieldBinding.type;
208
	
208
209
	}
209
	}
210
	
210
211
	/**
211
	/**
212
	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
212
	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
213
	 */
213
	 */
214
	public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
214
	public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
215
		if (runtimeTimeType == null || compileTimeType == null)
215
		if (runtimeTimeType == null || compileTimeType == null)
216
			return;				
216
			return;
217
		if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
217
		if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
218
			// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
218
			// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
219
			FieldBinding field = (FieldBinding) this.binding;
219
			FieldBinding field = (FieldBinding) this.binding;
220
			FieldBinding originalBinding = field.original();
220
			FieldBinding originalBinding = field.original();
221
			TypeBinding originalType = originalBinding.type;
221
			TypeBinding originalType = originalBinding.type;
222
		    // extra cast needed if method return type is type variable
222
		    // extra cast needed if method return type is type variable
223
			if (originalBinding != field 
223
			if (originalBinding != field
224
					&& originalType != field.type
224
					&& originalType != field.type
225
					&& runtimeTimeType.id != T_JavaLangObject
225
					&& runtimeTimeType.id != T_JavaLangObject
226
					&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
226
					&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
227
		    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
227
		    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
228
		    		? compileTimeType  // unboxing: checkcast before conversion
228
		    		? compileTimeType  // unboxing: checkcast before conversion
229
		    		: runtimeTimeType;
229
		    		: runtimeTimeType;
230
		        this.genericCast = originalType.genericCast(scope.boxing(targetType));
230
		        this.genericCast = originalType.genericCast(scope.boxing(targetType));
231
			} 	
231
			}
232
		}
232
		}
233
		super.computeConversion(scope, runtimeTimeType, compileTimeType);
233
		super.computeConversion(scope, runtimeTimeType, compileTimeType);
234
	}	
234
	}
235
235
236
	public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
236
	public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
237
	
237
238
		// optimizing assignment like: i = i + 1 or i = 1 + i
238
		// optimizing assignment like: i = i + 1 or i = 1 + i
239
		if (assignment.expression.isCompactableOperation()) {
239
		if (assignment.expression.isCompactableOperation()) {
240
			BinaryExpression operation = (BinaryExpression) assignment.expression;
240
			BinaryExpression operation = (BinaryExpression) assignment.expression;
Lines 245-253 Link Here
245
				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, operator, operation.implicitConversion, valueRequired);
245
				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, operator, operation.implicitConversion, valueRequired);
246
				if (valueRequired) {
246
				if (valueRequired) {
247
					codeStream.generateImplicitConversion(assignment.implicitConversion);
247
					codeStream.generateImplicitConversion(assignment.implicitConversion);
248
				}				
248
				}
249
				return;
249
				return;
250
			} 
250
			}
251
			if ((operation.right instanceof SingleNameReference)
251
			if ((operation.right instanceof SingleNameReference)
252
					&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
252
					&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
253
					&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
253
					&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
Lines 258-264 Link Here
258
				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
258
				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
259
				if (valueRequired) {
259
				if (valueRequired) {
260
					codeStream.generateImplicitConversion(assignment.implicitConversion);
260
					codeStream.generateImplicitConversion(assignment.implicitConversion);
261
				}				
261
				}
262
				return;
262
				return;
263
			}
263
			}
264
		}
264
		}
Lines 309-322 Link Here
309
					}
309
					}
310
					return;
310
					return;
311
				}
311
				}
312
				// 26903, need extra cast to store null in array local var	
312
				// 26903, need extra cast to store null in array local var
313
				if (localBinding.type.isArrayType() 
313
				if (localBinding.type.isArrayType()
314
					&& (assignment.expression.resolvedType == TypeBinding.NULL	// arrayLoc = null
314
					&& (assignment.expression.resolvedType == TypeBinding.NULL	// arrayLoc = null
315
						|| ((assignment.expression instanceof CastExpression)	// arrayLoc = (type[])null
315
						|| ((assignment.expression instanceof CastExpression)	// arrayLoc = (type[])null
316
							&& (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){
316
							&& (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){
317
					codeStream.checkcast(localBinding.type); 
317
					codeStream.checkcast(localBinding.type);
318
				}
318
				}
319
				
319
320
				// normal local assignment (since cannot store in outer local which are final locations)
320
				// normal local assignment (since cannot store in outer local which are final locations)
321
				codeStream.store(localBinding, valueRequired);
321
				codeStream.store(localBinding, valueRequired);
322
				if ((bits & FirstAssignmentToLocal) != 0) { // for local variable debug attributes
322
				if ((bits & FirstAssignmentToLocal) != 0) { // for local variable debug attributes
Lines 354-367 Link Here
354
								break;
354
								break;
355
							}
355
							}
356
						}
356
						}
357
						// managing private access							
357
						// managing private access
358
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
358
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
359
							codeStream.getstatic(fieldBinding);
359
							codeStream.getstatic(fieldBinding);
360
						} else {
360
						} else {
361
							codeStream.invokestatic(syntheticAccessors[READ]);
361
							codeStream.invokestatic(syntheticAccessors[READ]);
362
						}
362
						}
363
						// required cast must occur even if no value is required
364
						if (this.genericCast != null) codeStream.checkcast(this.genericCast);
363
						if (valueRequired) {
365
						if (valueRequired) {
364
							if (this.genericCast != null) codeStream.checkcast(this.genericCast);
365
							codeStream.generateImplicitConversion(implicitConversion);
366
							codeStream.generateImplicitConversion(implicitConversion);
366
						} else {
367
						} else {
367
							if ((implicitConversion & TypeIds.UNBOXING) != 0) {
368
							if ((implicitConversion & TypeIds.UNBOXING) != 0) {
Lines 376-384 Link Here
376
								default :
377
								default :
377
									codeStream.pop();
378
									codeStream.pop();
378
							}
379
							}
379
						}							
380
						}
380
					} else {
381
					} else {
381
						if (!valueRequired && ((implicitConversion & TypeIds.UNBOXING) == 0)) {
382
						if (!valueRequired
383
								&& ((implicitConversion & TypeIds.UNBOXING) == 0)
384
								&& this.genericCast == null) { // required cast must occur even if no value is required
382
							// if no valueRequired, optimize out entire gen
385
							// if no valueRequired, optimize out entire gen
383
							break;
386
							break;
384
						}
387
						}
Lines 390-404 Link Here
390
						} else {
393
						} else {
391
							generateReceiver(codeStream);
394
							generateReceiver(codeStream);
392
						}
395
						}
393
						// managing private access							
396
						// managing private access
394
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
397
						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
395
							codeStream.getfield(fieldBinding);
398
							codeStream.getfield(fieldBinding);
396
						} else {
399
						} else {
397
							codeStream.invokestatic(syntheticAccessors[READ]);
400
							codeStream.invokestatic(syntheticAccessors[READ]);
398
						}
401
						}
399
						// managing generic cast
402
						// managing generic cast
400
						if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
403
						if (this.genericCast != null) codeStream.checkcast(this.genericCast);
401
						codeStream.generateImplicitConversion(implicitConversion);
404
						codeStream.generateImplicitConversion(implicitConversion);
405
						if (!valueRequired) {
406
							switch (fieldBinding.type.id) {
407
								case T_long :
408
								case T_double :
409
									codeStream.pop2();
410
									break;
411
								default :
412
									codeStream.pop();
413
							}
414
						}
402
					}
415
					}
403
					break;
416
					break;
404
				case Binding.LOCAL : // reading a local
417
				case Binding.LOCAL : // reading a local
Lines 415-421 Link Here
415
						}
428
						}
416
						codeStream.generateImplicitConversion(implicitConversion);
429
						codeStream.generateImplicitConversion(implicitConversion);
417
					} else if ((implicitConversion & TypeIds.UNBOXING) != 0) {
430
					} else if ((implicitConversion & TypeIds.UNBOXING) != 0) {
418
419
						// outer local?
431
						// outer local?
420
						if ((bits & DepthMASK) != 0) {
432
						if ((bits & DepthMASK) != 0) {
421
							// outer local can be reached either through a synthetic arg or a synthetic field
433
							// outer local can be reached either through a synthetic arg or a synthetic field
Lines 426-435 Link Here
426
							codeStream.load(localBinding);
438
							codeStream.load(localBinding);
427
						}
439
						}
428
						codeStream.generateImplicitConversion(implicitConversion);
440
						codeStream.generateImplicitConversion(implicitConversion);
429
						if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
441
						switch (localBinding.type.id) {
430
							codeStream.pop2();
442
							case T_long :
431
						} else {
443
							case T_double :
432
							codeStream.pop();
444
								codeStream.pop2();
445
								break;
446
							default :
447
								codeStream.pop();
433
						}
448
						}
434
					}
449
					}
435
			}
450
			}
Lines 443-456 Link Here
443
	 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
458
	 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
444
	 */
459
	 */
445
	public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
460
	public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
446
	
461
447
		this.generateCompoundAssignment(
462
		this.generateCompoundAssignment(
448
			currentScope, 
463
			currentScope,
449
			codeStream, 
464
			codeStream,
450
			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
465
			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
451
			expression,
466
			expression,
452
			operator, 
467
			operator,
453
			assignmentImplicitConversion, 
468
			assignmentImplicitConversion,
454
			valueRequired);
469
			valueRequired);
455
	}
470
	}
456
	/*
471
	/*
Lines 497-503 Link Here
497
						codeStream.store(localBinding, false);
512
						codeStream.store(localBinding, false);
498
						return;
513
						return;
499
					case T_int :
514
					case T_int :
500
						if (((assignConstant = expression.constant) != Constant.NotAConstant) 
515
						if (((assignConstant = expression.constant) != Constant.NotAConstant)
501
							&& (assignConstant.typeID() != T_float) // only for integral types
516
							&& (assignConstant.typeID() != T_float) // only for integral types
502
							&& (assignConstant.typeID() != T_double)
517
							&& (assignConstant.typeID() != T_double)
503
							&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
518
							&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
Lines 526-536 Link Here
526
			case T_JavaLangString :
541
			case T_JavaLangString :
527
			case T_JavaLangObject :
542
			case T_JavaLangObject :
528
			case T_undefined :
543
			case T_undefined :
529
				// we enter here if the single name reference is a field of type java.lang.String or if the type of the 
544
				// we enter here if the single name reference is a field of type java.lang.String or if the type of the
530
				// operation is java.lang.Object
545
				// operation is java.lang.Object
531
				// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
546
				// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
532
				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
547
				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
533
				// no need for generic cast on previous #getfield since using Object string buffer methods.			
548
				// no need for generic cast on previous #getfield since using Object string buffer methods.
534
				break;
549
				break;
535
			default :
550
			default :
536
				// promote the array reference to the suitable operation type
551
				// promote the array reference to the suitable operation type
Lines 539-548 Link Here
539
				codeStream.generateImplicitConversion(this.implicitConversion);
554
				codeStream.generateImplicitConversion(this.implicitConversion);
540
				// generate the increment value (will by itself  be promoted to the operation value)
555
				// generate the increment value (will by itself  be promoted to the operation value)
541
				if (expression == IntLiteral.One){ // prefix operation
556
				if (expression == IntLiteral.One){ // prefix operation
542
					codeStream.generateConstant(expression.constant, this.implicitConversion);			
557
					codeStream.generateConstant(expression.constant, this.implicitConversion);
543
				} else {
558
				} else {
544
					expression.generateCode(currentScope, codeStream, true);
559
					expression.generateCode(currentScope, codeStream, true);
545
				}		
560
				}
546
				// perform the operation
561
				// perform the operation
547
				codeStream.sendOperator(operator, operationTypeID);
562
				codeStream.sendOperator(operator, operationTypeID);
548
				// cast the value back to the array reference type
563
				// cast the value back to the array reference type
Lines 566-572 Link Here
566
				codeStream.store(localBinding, false);
581
				codeStream.store(localBinding, false);
567
		}
582
		}
568
	}
583
	}
569
	
584
570
	public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
585
	public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
571
		switch (bits & RestrictiveFlagMASK) {
586
		switch (bits & RestrictiveFlagMASK) {
572
			case Binding.FIELD : // assigning to a field
587
			case Binding.FIELD : // assigning to a field
Lines 607-620 Link Here
607
						}
622
						}
608
					}
623
					}
609
				}
624
				}
610
				if (this.genericCast != null) 
625
				if (this.genericCast != null)
611
					codeStream.checkcast(this.genericCast);
626
					codeStream.checkcast(this.genericCast);
612
				codeStream.generateImplicitConversion(this.implicitConversion);		
627
				codeStream.generateImplicitConversion(this.implicitConversion);
613
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
628
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
614
				codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
629
				codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
615
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
630
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
616
				fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], false);
631
				fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], false);
617
				// no need for generic cast 
632
				// no need for generic cast
618
				return;
633
				return;
619
			case Binding.LOCAL : // assigning to a local variable
634
			case Binding.LOCAL : // assigning to a local variable
620
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
635
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
Lines 641-656 Link Here
641
					codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
656
					codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
642
					codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
657
					codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
643
					codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
658
					codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
644
	
659
645
					codeStream.store(localBinding, false);
660
					codeStream.store(localBinding, false);
646
				}
661
				}
647
		}
662
		}
648
	}	
663
	}
649
	
664
650
	public void generateReceiver(CodeStream codeStream) {
665
	public void generateReceiver(CodeStream codeStream) {
651
		codeStream.aload_0();
666
		codeStream.aload_0();
652
	}
667
	}
653
	
668
654
	/**
669
	/**
655
	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
670
	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
656
	 */
671
	 */
Lines 671-696 Link Here
671
		}
686
		}
672
		return null;
687
		return null;
673
	}
688
	}
674
	
689
675
	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
690
	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
676
	
691
677
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
692
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
678
		//If inlinable field, forget the access emulation, the code gen will directly target it
693
		//If inlinable field, forget the access emulation, the code gen will directly target it
679
		if (((bits & DepthMASK) == 0) || (constant != Constant.NotAConstant)) return;
694
		if (((bits & DepthMASK) == 0) || (constant != Constant.NotAConstant)) return;
680
	
695
681
		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
696
		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
682
			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
697
			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
683
		}
698
		}
684
		}
699
		}
685
	}
700
	}
686
	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
701
	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
687
	
702
688
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
703
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
689
	
704
690
		//If inlinable field, forget the access emulation, the code gen will directly target it
705
		//If inlinable field, forget the access emulation, the code gen will directly target it
691
		if (constant != Constant.NotAConstant)
706
		if (constant != Constant.NotAConstant)
692
			return;
707
			return;
693
	
708
694
		if ((bits & Binding.FIELD) != 0) {
709
		if ((bits & Binding.FIELD) != 0) {
695
			FieldBinding fieldBinding = (FieldBinding) binding;
710
			FieldBinding fieldBinding = (FieldBinding) binding;
696
			FieldBinding codegenField = fieldBinding.original();
711
			FieldBinding codegenField = fieldBinding.original();
Lines 701-707 Link Here
701
							&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
716
							&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
702
				if (syntheticAccessors == null)
717
				if (syntheticAccessors == null)
703
					syntheticAccessors = new MethodBinding[2];
718
					syntheticAccessors = new MethodBinding[2];
704
				syntheticAccessors[isReadAccess ? READ : WRITE] = 
719
				syntheticAccessors[isReadAccess ? READ : WRITE] =
705
				    ((SourceTypeBinding)currentScope.enclosingSourceType().
720
				    ((SourceTypeBinding)currentScope.enclosingSourceType().
706
						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess);
721
						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess);
707
				currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
722
				currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
Lines 710-716 Link Here
710
			// if the binding declaring class is not visible, need special action
725
			// if the binding declaring class is not visible, need special action
711
			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
726
			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
712
			// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
727
			// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
713
			// and not from Object or implicit static field access.	
728
			// and not from Object or implicit static field access.
714
			if (fieldBinding.declaringClass != this.actualReceiverType
729
			if (fieldBinding.declaringClass != this.actualReceiverType
715
					&& !this.actualReceiverType.isArrayType()
730
					&& !this.actualReceiverType.isArrayType()
716
					&& fieldBinding.declaringClass != null // array.length
731
					&& fieldBinding.declaringClass != null // array.length
Lines 720-732 Link Here
720
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
735
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
721
						&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
736
						&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
722
					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
737
					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
723
		
738
724
					this.codegenBinding = 
739
					this.codegenBinding =
725
					    currentScope.enclosingSourceType().getUpdatedFieldBinding(
740
					    currentScope.enclosingSourceType().getUpdatedFieldBinding(
726
						       codegenField, 
741
						       codegenField,
727
						        (ReferenceBinding)this.actualReceiverType.erasure());
742
						        (ReferenceBinding)this.actualReceiverType.erasure());
728
				}
743
				}
729
			}					
744
			}
730
		}
745
		}
731
	}
746
	}
732
747
Lines 747-753 Link Here
747
				return FlowInfo.UNKNOWN;
762
				return FlowInfo.UNKNOWN;
748
			}
763
			}
749
	}
764
	}
750
	return FlowInfo.NON_NULL; // never get there 
765
	return FlowInfo.NON_NULL; // never get there
751
}
766
}
752
767
753
	/**
768
	/**
Lines 755-761 Link Here
755
	 */
770
	 */
756
	public TypeBinding postConversionType(Scope scope) {
771
	public TypeBinding postConversionType(Scope scope) {
757
		TypeBinding convertedType = this.resolvedType;
772
		TypeBinding convertedType = this.resolvedType;
758
		if (this.genericCast != null) 
773
		if (this.genericCast != null)
759
			convertedType = this.genericCast;
774
			convertedType = this.genericCast;
760
		int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
775
		int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
761
		switch (runtimeType) {
776
		switch (runtimeType) {
Lines 784-802 Link Here
784
				convertedType = TypeBinding.DOUBLE;
799
				convertedType = TypeBinding.DOUBLE;
785
				break;
800
				break;
786
			default :
801
			default :
787
		}		
802
		}
788
		if ((this.implicitConversion & BOXING) != 0) {
803
		if ((this.implicitConversion & BOXING) != 0) {
789
			convertedType = scope.environment().computeBoxingType(convertedType);
804
			convertedType = scope.environment().computeBoxingType(convertedType);
790
		}
805
		}
791
		return convertedType;
806
		return convertedType;
792
	}
807
	}
793
	
808
794
	public StringBuffer printExpression(int indent, StringBuffer output){
809
	public StringBuffer printExpression(int indent, StringBuffer output){
795
	
810
796
		return output.append(token);
811
		return output.append(token);
797
	}
812
	}
798
	public TypeBinding reportError(BlockScope scope) {
813
	public TypeBinding reportError(BlockScope scope) {
799
		
814
800
		//=====error cases=======
815
		//=====error cases=======
801
		constant = Constant.NotAConstant;
816
		constant = Constant.NotAConstant;
802
		if (binding instanceof ProblemFieldBinding) {
817
		if (binding instanceof ProblemFieldBinding) {
Lines 808-817 Link Here
808
		}
823
		}
809
		return null;
824
		return null;
810
	}
825
	}
811
		
826
812
	public TypeBinding resolveType(BlockScope scope) {
827
	public TypeBinding resolveType(BlockScope scope) {
813
		// for code gen, harm the restrictiveFlag 	
828
		// for code gen, harm the restrictiveFlag
814
	
829
815
		if (this.actualReceiverType != null) {
830
		if (this.actualReceiverType != null) {
816
			this.binding = scope.getField(this.actualReceiverType, token, this);
831
			this.binding = scope.getField(this.actualReceiverType, token, this);
817
		} else {
832
		} else {
Lines 834-840 Link Here
834
							TypeBinding fieldType = variable.type;
849
							TypeBinding fieldType = variable.type;
835
							if ((this.bits & IsStrictlyAssigned) == 0) {
850
							if ((this.bits & IsStrictlyAssigned) == 0) {
836
								constant = variable.constant();
851
								constant = variable.constant();
837
								if (fieldType != null) 
852
								if (fieldType != null)
838
									fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access
853
									fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access
839
							} else {
854
							} else {
840
								constant = Constant.NotAConstant;
855
								constant = Constant.NotAConstant;
Lines 848-859 Link Here
848
						}
863
						}
849
						// perform capture conversion if read access
864
						// perform capture conversion if read access
850
						TypeBinding fieldType = checkFieldAccess(scope);
865
						TypeBinding fieldType = checkFieldAccess(scope);
851
						return this.resolvedType = 
866
						return this.resolvedType =
852
							(((this.bits & IsStrictlyAssigned) == 0) 
867
							(((this.bits & IsStrictlyAssigned) == 0)
853
								? fieldType.capture(scope, this.sourceEnd)
868
								? fieldType.capture(scope, this.sourceEnd)
854
								: fieldType);
869
								: fieldType);
855
					}
870
					}
856
	
871
857
					// thus it was a type
872
					// thus it was a type
858
					bits &= ~RestrictiveFlagMASK;  // clear bits
873
					bits &= ~RestrictiveFlagMASK;  // clear bits
859
					bits |= Binding.TYPE;
874
					bits |= Binding.TYPE;
Lines 867-889 Link Here
867
					return this.resolvedType = type;
882
					return this.resolvedType = type;
868
			}
883
			}
869
		}
884
		}
870
	
885
871
		// error scenarii
886
		// error scenarii
872
		return this.resolvedType = this.reportError(scope);
887
		return this.resolvedType = this.reportError(scope);
873
	}
888
	}
874
	
889
875
	public void traverse(ASTVisitor visitor, BlockScope scope) {
890
	public void traverse(ASTVisitor visitor, BlockScope scope) {
876
		visitor.visit(this, scope);
891
		visitor.visit(this, scope);
877
		visitor.endVisit(this, scope);
892
		visitor.endVisit(this, scope);
878
	}
893
	}
879
	
894
880
	public void traverse(ASTVisitor visitor, ClassScope scope) {
895
	public void traverse(ASTVisitor visitor, ClassScope scope) {
881
		visitor.visit(this, scope);
896
		visitor.visit(this, scope);
882
		visitor.endVisit(this, scope);
897
		visitor.endVisit(this, scope);
883
	}
898
	}
884
899
885
	public String unboundReferenceErrorName(){
900
	public String unboundReferenceErrorName(){
886
	
901
887
		return new String(token);
902
		return new String(token);
888
	}	
903
	}
889
}
904
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-3 / +3 lines)
Lines 144-154 Link Here
144
	} else {
144
	} else {
145
		codeStream.invokestatic(syntheticAccessor);
145
		codeStream.invokestatic(syntheticAccessor);
146
	}
146
	}
147
	// operation on the returned value
147
	// required cast must occur even if no value is required
148
	if (this.valueCast != null) codeStream.checkcast(this.valueCast);
149
148
	if (valueRequired){
150
	if (valueRequired){
149
		// implicit conversion if necessary
151
		// implicit conversion if necessary
150
		if (this.valueCast != null) 
151
			codeStream.checkcast(this.valueCast);
152
		codeStream.generateImplicitConversion(implicitConversion);
152
		codeStream.generateImplicitConversion(implicitConversion);
153
	} else {
153
	} else {
154
		// pop return value if any
154
		// pop return value if any

Return to bug 177194