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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/NameReference.java (-1 / +1 lines)
Lines 14-20 Link Here
14
14
15
public abstract class NameReference extends Reference implements InvocationSite {
15
public abstract class NameReference extends Reference implements InvocationSite {
16
16
17
	public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
17
	public Binding binding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
18
18
19
	public TypeBinding actualReceiverType;	// modified receiver type - actual one according to namelookup
19
	public TypeBinding actualReceiverType;	// modified receiver type - actual one according to namelookup
20
20
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java (-3 / +4 lines)
Lines 16-21 Link Here
16
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
16
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
17
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
17
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
18
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
19
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
19
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
20
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
22
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
Lines 173-179 Link Here
173
			falseLabel.place();
174
			falseLabel.place();
174
			codeStream.iconst_0();
175
			codeStream.iconst_0();
175
			jumpLabel.place();
176
			jumpLabel.place();
176
			codeStream.putstatic(this.assertionSyntheticFieldBinding);
177
			codeStream.fieldAccess(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
177
		}
178
		}
178
		// generate static fields/initializers/enum constants
179
		// generate static fields/initializers/enum constants
179
		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
180
		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
Lines 206-218 Link Here
206
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
207
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
207
							codeStream.dup();
208
							codeStream.dup();
208
							codeStream.generateInlinedValue(fieldDecl.binding.id);
209
							codeStream.generateInlinedValue(fieldDecl.binding.id);
209
							codeStream.getstatic(fieldDecl.binding);
210
							codeStream.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */);
210
							codeStream.aastore();
211
							codeStream.aastore();
211
						}
212
						}
212
					}
213
					}
213
				}
214
				}
214
			}
215
			}
215
			codeStream.putstatic(declaringType.enumValuesSyntheticfield);
216
			codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */);
216
			if (remainingFieldCount != 0) {
217
			if (remainingFieldCount != 0) {
217
				// if fields that are not enum constants need to be generated (static initializer/static field)
218
				// if fields that are not enum constants need to be generated (static initializer/static field)
218
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
219
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java (-2 / +2 lines)
Lines 228-234 Link Here
228
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
228
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
229
			codeStream.aload_0();
229
			codeStream.aload_0();
230
			codeStream.load(syntheticArg);
230
			codeStream.load(syntheticArg);
231
			codeStream.putfield(syntheticArg.matchingField);
231
			codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
232
		}
232
		}
233
	}
233
	}
234
	syntheticArgs = nestedType.syntheticOuterLocalVariables();
234
	syntheticArgs = nestedType.syntheticOuterLocalVariables();
Lines 237-243 Link Here
237
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
237
		if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
238
			codeStream.aload_0();
238
			codeStream.aload_0();
239
			codeStream.load(syntheticArg);
239
			codeStream.load(syntheticArg);
240
			codeStream.putfield(syntheticArg.matchingField);
240
			codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
241
		}
241
		}
242
	}
242
	}
243
}
243
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java (-1 / +1 lines)
Lines 101-107 Link Here
101
101
102
		if (this.assertionSyntheticFieldBinding != null) {
102
		if (this.assertionSyntheticFieldBinding != null) {
103
			BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
103
			BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
104
			codeStream.getstatic(this.assertionSyntheticFieldBinding);
104
			codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
105
			codeStream.ifne(assertionActivationLabel);
105
			codeStream.ifne(assertionActivationLabel);
106
106
107
			BranchLabel falseLabel;
107
			BranchLabel falseLabel;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java (-13 / +29 lines)
Lines 10-18 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.compiler.ast;
11
package org.eclipse.jdt.internal.compiler.ast;
12
12
13
import org.eclipse.jdt.internal.compiler.codegen.*;
13
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.flow.*;
14
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
15
import org.eclipse.jdt.internal.compiler.lookup.*;
15
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
16
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
19
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
20
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
16
21
17
public abstract class Reference extends Expression  {
22
public abstract class Reference extends Expression  {
18
/**
23
/**
Lines 26-67 Link Here
26
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
31
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
27
	return flowInfo;
32
	return flowInfo;
28
}
33
}
34
29
public FieldBinding fieldBinding() {
35
public FieldBinding fieldBinding() {
30
	//this method should be sent one FIELD-tagged references
36
	//this method should be sent one FIELD-tagged references
31
	//  (ref.bits & BindingIds.FIELD != 0)()
37
	//  (ref.bits & BindingIds.FIELD != 0)()
32
	return null ;
38
	return null ;
33
}
39
}
40
34
public void fieldStore(CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, boolean valueRequired) {
41
public void fieldStore(CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, boolean valueRequired) {
35
	int pc = codeStream.position;
42
	int pc = codeStream.position;
36
	if (fieldBinding.isStatic()) {
43
	if (fieldBinding.isStatic()) {
37
		if (valueRequired) {
44
		if (valueRequired) {
38
			if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
45
			switch (fieldBinding.type.id) {
39
				codeStream.dup2();
46
				case TypeIds.T_long :
40
			} else {
47
				case TypeIds.T_double :
41
				codeStream.dup();
48
					codeStream.dup2();
49
					break;
50
				default : 
51
					codeStream.dup();
52
					break;
42
			}
53
			}
43
		}
54
		}
44
		if (syntheticWriteAccessor == null) {
55
		if (syntheticWriteAccessor == null) {
45
			codeStream.putstatic(fieldBinding);
56
			codeStream.fieldAccess(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */);
46
		} else {
57
		} else {
47
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
58
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
48
		}
59
		}
49
	} else { // Stack:  [owner][new field value]  ---> [new field value][owner][new field value]
60
	} else { // Stack:  [owner][new field value]  ---> [new field value][owner][new field value]
50
		if (valueRequired) {
61
		if (valueRequired) {
51
			if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
62
			switch (fieldBinding.type.id) {
52
				codeStream.dup2_x1();
63
				case TypeIds.T_long :
53
			} else {
64
				case TypeIds.T_double :
54
				codeStream.dup_x1();
65
					codeStream.dup2_x1();
66
					break;
67
				default : 
68
					codeStream.dup_x1();
69
					break;
55
			}
70
			}
56
		}
71
		}
57
		if (syntheticWriteAccessor == null) {
72
		if (syntheticWriteAccessor == null) {
58
			codeStream.putfield(fieldBinding);
73
			codeStream.fieldAccess(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */);
59
		} else {
74
		} else {
60
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
75
			codeStream.invoke(Opcodes.OPC_invokestatic, syntheticWriteAccessor, null /* default declaringClass */);
61
		}
76
		}
62
	}
77
	}
63
	codeStream.recordPositionsFrom(pc, this.sourceStart);
78
	codeStream.recordPositionsFrom(pc, this.sourceStart);
64
}
79
}
80
65
public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired);
81
public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired);
66
82
67
public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired);
83
public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired);
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-65 / +66 lines)
Lines 278-286 Link Here
278
	}
278
	}
279
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
279
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
280
		case Binding.FIELD : // assigning to a field
280
		case Binding.FIELD : // assigning to a field
281
			FieldBinding fieldBinding;
282
			int pc = codeStream.position;
281
			int pc = codeStream.position;
283
			if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
282
			FieldBinding codegenBinding = ((FieldBinding) this.binding).original();
283
			if (!codegenBinding.isStatic()) { // need a receiver?
284
				if ((this.bits & ASTNode.DepthMASK) != 0) {
284
				if ((this.bits & ASTNode.DepthMASK) != 0) {
285
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
285
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
286
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
286
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 291-304 Link Here
291
			}
291
			}
292
			codeStream.recordPositionsFrom(pc, this.sourceStart);
292
			codeStream.recordPositionsFrom(pc, this.sourceStart);
293
			assignment.expression.generateCode(currentScope, codeStream, true);
293
			assignment.expression.generateCode(currentScope, codeStream, true);
294
			fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], valueRequired);
294
			fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], valueRequired);
295
			if (valueRequired) {
295
			if (valueRequired) {
296
				codeStream.generateImplicitConversion(assignment.implicitConversion);
296
				codeStream.generateImplicitConversion(assignment.implicitConversion);
297
			}
297
			}
298
			// no need for generic cast as value got dupped
298
			// no need for generic cast as value got dupped
299
			return;
299
			return;
300
		case Binding.LOCAL : // assigning to a local variable
300
		case Binding.LOCAL : // assigning to a local variable
301
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
301
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
302
			if (localBinding.resolvedPosition != -1) {
302
			if (localBinding.resolvedPosition != -1) {
303
				assignment.expression.generateCode(currentScope, codeStream, true);
303
				assignment.expression.generateCode(currentScope, codeStream, true);
304
			} else {
304
			} else {
Lines 354-361 Link Here
354
	} else {
354
	} else {
355
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
355
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
356
			case Binding.FIELD : // reading a field
356
			case Binding.FIELD : // reading a field
357
				FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
357
				FieldBinding codegenField = ((FieldBinding) this.binding).original();
358
				Constant fieldConstant = fieldBinding.constant();
358
				Constant fieldConstant = codegenField.constant();
359
				if (fieldConstant != Constant.NotAConstant) {
359
				if (fieldConstant != Constant.NotAConstant) {
360
					// directly use inlined value for constant fields
360
					// directly use inlined value for constant fields
361
					if (valueRequired) {
361
					if (valueRequired) {
Lines 364-370 Link Here
364
					codeStream.recordPositionsFrom(pc, this.sourceStart);
364
					codeStream.recordPositionsFrom(pc, this.sourceStart);
365
					return;
365
					return;
366
				}
366
				}
367
				if (fieldBinding.isStatic()) {
367
				if (codegenField.isStatic()) {
368
					if (!valueRequired
368
					if (!valueRequired
369
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
369
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
370
							&& ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure()
370
							&& ((FieldBinding)this.binding).original().declaringClass == this.actualReceiverType.erasure()
Lines 376-382 Link Here
376
					}
376
					}
377
					// managing private access
377
					// managing private access
378
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
378
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
379
						codeStream.getstatic(fieldBinding);
379
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
380
						codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
380
					} else {
381
					} else {
381
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
382
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
382
					}
383
					}
Lines 398-411 Link Here
398
					}
399
					}
399
					// managing private access
400
					// managing private access
400
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
401
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
401
						codeStream.getfield(fieldBinding);
402
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
403
						codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
402
					} else {
404
					} else {
403
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
405
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
404
					}
406
					}
405
				}
407
				}
406
				break;
408
				break;
407
			case Binding.LOCAL : // reading a local
409
			case Binding.LOCAL : // reading a local
408
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
410
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
409
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
411
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
410
					// if no valueRequired, optimize out entire gen
412
					// if no valueRequired, optimize out entire gen
411
					codeStream.recordPositionsFrom(pc, this.sourceStart);
413
					codeStream.recordPositionsFrom(pc, this.sourceStart);
Lines 470-479 Link Here
470
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
472
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
471
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
473
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
472
		case Binding.FIELD : // assigning to a field
474
		case Binding.FIELD : // assigning to a field
473
			FieldBinding fieldBinding;
475
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
474
			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
476
			if (codegenField.isStatic()) {
475
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
477
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
476
					codeStream.getstatic(fieldBinding);
478
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);					
479
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
477
				} else {
480
				} else {
478
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
481
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
479
				}
482
				}
Lines 487-500 Link Here
487
				}
490
				}
488
				codeStream.dup();
491
				codeStream.dup();
489
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
492
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
490
					codeStream.getfield(fieldBinding);
493
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
494
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
491
				} else {
495
				} else {
492
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
496
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
493
				}
497
				}
494
			}
498
			}
495
			break;
499
			break;
496
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
500
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
497
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
501
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
498
			// using incr bytecode if possible
502
			// using incr bytecode if possible
499
			switch (localBinding.type.id) {
503
			switch (localBinding.type.id) {
500
				case T_JavaLangString :
504
				case T_JavaLangString :
Lines 564-579 Link Here
564
	// store the result back into the variable
568
	// store the result back into the variable
565
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
569
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
566
		case Binding.FIELD : // assigning to a field
570
		case Binding.FIELD : // assigning to a field
567
			fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
571
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
572
			fieldStore(codeStream, codegenField, writeAccessor, valueRequired);
568
			// no need for generic cast as value got dupped
573
			// no need for generic cast as value got dupped
569
			return;
574
			return;
570
		case Binding.LOCAL : // assigning to a local variable
575
		case Binding.LOCAL : // assigning to a local variable
571
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
576
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
572
			if (valueRequired) {
577
			if (valueRequired) {
573
				if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
578
				switch (localBinding.type.id) {
574
					codeStream.dup2();
579
					case TypeIds.T_long :
575
				} else {
580
					case TypeIds.T_double :
576
					codeStream.dup();
581
						codeStream.dup2();
582
						break;
583
					default:
584
						codeStream.dup();
585
						break;
577
				}
586
				}
578
			}
587
			}
579
			codeStream.store(localBinding, false);
588
			codeStream.store(localBinding, false);
Lines 583-592 Link Here
583
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
592
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
584
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
593
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
585
		case Binding.FIELD : // assigning to a field
594
		case Binding.FIELD : // assigning to a field
586
			FieldBinding fieldBinding;
595
			FieldBinding codegenField = (((FieldBinding)this.binding).original());
587
			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
596
			if (codegenField.isStatic()) {
588
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
597
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
589
					codeStream.getstatic(fieldBinding);
598
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
599
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
590
				} else {
600
				} else {
591
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
601
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
592
				}
602
				}
Lines 600-606 Link Here
600
				}
610
				}
601
				codeStream.dup();
611
				codeStream.dup();
602
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
612
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
603
					codeStream.getfield(fieldBinding);
613
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
614
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
604
				} else {
615
				} else {
605
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
616
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
606
				}
617
				}
Lines 610-629 Link Here
610
				codeStream.checkcast(this.genericCast);
621
				codeStream.checkcast(this.genericCast);
611
				operandType = this.genericCast;
622
				operandType = this.genericCast;
612
			} else {
623
			} else {
613
				operandType = fieldBinding.type;
624
				operandType = codegenField.type;
614
			}
625
			}
615
			if (valueRequired) {
626
			if (valueRequired) {
616
				if (fieldBinding.isStatic()) {
627
				if (codegenField.isStatic()) {
617
					if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) {
628
					switch (operandType.id) {
618
						codeStream.dup2();
629
						case TypeIds.T_long :
619
					} else {
630
						case TypeIds.T_double :
620
						codeStream.dup();
631
							codeStream.dup2();
621
					}
632
							break;
633
						default:
634
							codeStream.dup();
635
							break;
636
					}					
622
				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
637
				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
623
					if ((operandType == TypeBinding.LONG) || (operandType == TypeBinding.DOUBLE)) {
638
					switch (operandType.id) {
624
						codeStream.dup2_x1();
639
						case TypeIds.T_long :
625
					} else {
640
						case TypeIds.T_double :
626
						codeStream.dup_x1();
641
							codeStream.dup2_x1();
642
							break;
643
						default:
644
							codeStream.dup_x1();
645
							break;
627
					}
646
					}
628
				}
647
				}
629
			}
648
			}
Lines 631-641 Link Here
631
			codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
650
			codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
632
			codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
651
			codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
633
			codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
652
			codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
634
			fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], false);
653
			fieldStore(codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], false);
635
			// no need for generic cast 
654
			// no need for generic cast 
636
			return;
655
			return;
637
		case Binding.LOCAL : // assigning to a local variable
656
		case Binding.LOCAL : // assigning to a local variable
638
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
657
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
639
			// using incr bytecode if possible
658
			// using incr bytecode if possible
640
			if (localBinding.type == TypeBinding.INT) {
659
			if (localBinding.type == TypeBinding.INT) {
641
				if (valueRequired) {
660
				if (valueRequired) {
Lines 649-659 Link Here
649
			} else {
668
			} else {
650
				codeStream.load(localBinding);
669
				codeStream.load(localBinding);
651
				if (valueRequired){
670
				if (valueRequired){
652
					if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
671
					switch (localBinding.type.id) {
653
						codeStream.dup2();
672
						case TypeIds.T_long :
654
					} else {
673
						case TypeIds.T_double :
655
						codeStream.dup();
674
							codeStream.dup2();
656
					}
675
							break;
676
						default:
677
							codeStream.dup();
678
							break;
679
					}					
657
				}
680
				}
658
				codeStream.generateImplicitConversion(this.implicitConversion);
681
				codeStream.generateImplicitConversion(this.implicitConversion);
659
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
682
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
Lines 710-716 Link Here
710
	if ((this.bits & Binding.FIELD) != 0) {
733
	if ((this.bits & Binding.FIELD) != 0) {
711
		FieldBinding fieldBinding = (FieldBinding) this.binding;
734
		FieldBinding fieldBinding = (FieldBinding) this.binding;
712
		FieldBinding codegenField = fieldBinding.original();
735
		FieldBinding codegenField = fieldBinding.original();
713
		this.codegenBinding = codegenField;
714
		if (((this.bits & ASTNode.DepthMASK) != 0)
736
		if (((this.bits & ASTNode.DepthMASK) != 0)
715
			&& (codegenField.isPrivate() // private access
737
			&& (codegenField.isPrivate() // private access
716
				|| (codegenField.isProtected() // implicit protected access
738
				|| (codegenField.isProtected() // implicit protected access
Lines 723-748 Link Here
723
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
745
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
724
			return;
746
			return;
725
		}
747
		}
726
		// if the binding declaring class is not visible, need special action
727
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
728
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
729
		// and not from Object or implicit static field access.
730
		if (fieldBinding.declaringClass != this.actualReceiverType
731
				&& !this.actualReceiverType.isArrayType()
732
				&& fieldBinding.declaringClass != null // array.length
733
				&& fieldBinding.constant() == Constant.NotAConstant) {
734
			CompilerOptions options = currentScope.compilerOptions();
735
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
736
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
737
					&& fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
738
					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
739
740
					this.codegenBinding =
741
					    currentScope.enclosingSourceType().getUpdatedFieldBinding(
742
						       codegenField,
743
						        (ReferenceBinding)this.actualReceiverType.erasure());
744
			}
745
		}
746
	}
748
	}
747
}
749
}
748
750
Lines 832-838 Link Here
832
		this.actualReceiverType = scope.enclosingSourceType();
834
		this.actualReceiverType = scope.enclosingSourceType();
833
		this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/);
835
		this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/);
834
	}
836
	}
835
	this.codegenBinding = this.binding;
836
	if (this.binding.isValidBinding()) {
837
	if (this.binding.isValidBinding()) {
837
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
838
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
838
			case Binding.VARIABLE : // =========only variable============
839
			case Binding.VARIABLE : // =========only variable============
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-83 / +67 lines)
Lines 17-23 Link Here
17
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
17
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
18
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
18
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.Constant;
22
import org.eclipse.jdt.internal.compiler.lookup.Binding;
21
import org.eclipse.jdt.internal.compiler.lookup.Binding;
23
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
Lines 41-51 Link Here
41
	public Expression receiver;
40
	public Expression receiver;
42
	public char[] token;
41
	public char[] token;
43
	public FieldBinding binding;															// exact binding resulting from lookup
42
	public FieldBinding binding;															// exact binding resulting from lookup
44
	protected FieldBinding codegenBinding;									// actual binding used for code generation (if no synthetic accessor)
45
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
43
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
46
44
47
	public long nameSourcePosition; //(start<<32)+end
45
	public long nameSourcePosition; //(start<<32)+end
48
	public TypeBinding receiverType;
46
	public TypeBinding actualReceiverType;
49
	public TypeBinding genericCast;
47
	public TypeBinding genericCast;
50
48
51
public FieldReference(char[] source, long pos) {
49
public FieldReference(char[] source, long pos) {
Lines 162-176 Link Here
162
160
163
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
161
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
164
	int pc = codeStream.position;
162
	int pc = codeStream.position;
163
	FieldBinding codegenBinding = this.binding.original();
165
	this.receiver.generateCode(
164
	this.receiver.generateCode(
166
		currentScope,
165
		currentScope,
167
		codeStream,
166
		codeStream,
168
		!this.codegenBinding.isStatic());
167
		!codegenBinding.isStatic());
169
	codeStream.recordPositionsFrom(pc, this.sourceStart);
168
	codeStream.recordPositionsFrom(pc, this.sourceStart);
170
	assignment.expression.generateCode(currentScope, codeStream, true);
169
	assignment.expression.generateCode(currentScope, codeStream, true);
171
	fieldStore(
170
	fieldStore(
172
		codeStream,
171
		codeStream,
173
		this.codegenBinding,
172
		codegenBinding,
174
		this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
173
		this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
175
		valueRequired);
174
		valueRequired);
176
	if (valueRequired) {
175
	if (valueRequired) {
Lines 195-203 Link Here
195
		codeStream.recordPositionsFrom(pc, this.sourceStart);
194
		codeStream.recordPositionsFrom(pc, this.sourceStart);
196
		return;
195
		return;
197
	}
196
	}
198
	boolean isStatic = this.codegenBinding.isStatic();
197
	FieldBinding codegenBinding = this.binding.original();
198
	boolean isStatic = codegenBinding.isStatic();
199
	boolean isThisReceiver = this.receiver instanceof ThisReference;
199
	boolean isThisReceiver = this.receiver instanceof ThisReference;
200
	Constant fieldConstant = this.codegenBinding.constant();
200
	Constant fieldConstant = codegenBinding.constant();
201
	if (fieldConstant != Constant.NotAConstant) {
201
	if (fieldConstant != Constant.NotAConstant) {
202
		if (!isThisReceiver) {
202
		if (!isThisReceiver) {
203
			this.receiver.generateCode(currentScope, codeStream, !isStatic);
203
			this.receiver.generateCode(currentScope, codeStream, !isStatic);
Lines 218-224 Link Here
218
			|| (this.genericCast != null)) {
218
			|| (this.genericCast != null)) {
219
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
219
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
220
		pc = codeStream.position;
220
		pc = codeStream.position;
221
		if (this.codegenBinding.declaringClass == null) { // array length
221
		if (codegenBinding.declaringClass == null) { // array length
222
			codeStream.arraylength();
222
			codeStream.arraylength();
223
			if (valueRequired) {
223
			if (valueRequired) {
224
				codeStream.generateImplicitConversion(this.implicitConversion);
224
				codeStream.generateImplicitConversion(this.implicitConversion);
Lines 228-237 Link Here
228
			}
228
			}
229
		} else {
229
		} else {
230
			if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
230
			if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
231
				TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
231
				if (isStatic) {
232
				if (isStatic) {
232
					codeStream.getstatic(this.codegenBinding);
233
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
233
				} else {
234
				} else {
234
					codeStream.getfield(this.codegenBinding);
235
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
235
				}
236
				}
236
			} else {
237
			} else {
237
				codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
238
				codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
Lines 244-250 Link Here
244
				boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
245
				boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
245
				// conversion only generated if unboxing
246
				// conversion only generated if unboxing
246
				if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
247
				if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
247
				switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.type.id) {
248
				switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) {
248
					case T_long :
249
					case T_long :
249
					case T_double :
250
					case T_double :
250
						codeStream.pop2();
251
						codeStream.pop2();
Lines 258-271 Link Here
258
		if (isThisReceiver) {
259
		if (isThisReceiver) {
259
			if (isStatic){
260
			if (isStatic){
260
				// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
261
				// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
261
				if (this.binding.original().declaringClass != this.receiverType.erasure()) {
262
				if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) {
262
					MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ];
263
					MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ];
263
					if (accessor == null) {
264
					if (accessor == null) {
264
						codeStream.getstatic(this.codegenBinding);
265
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
266
						codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
265
					} else {
267
					} else {
266
						codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
268
						codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
267
					}
269
					}
268
					switch (this.codegenBinding.type.id) {
270
					switch (codegenBinding.type.id) {
269
						case T_long :
271
						case T_long :
270
						case T_double :
272
						case T_double :
271
							codeStream.pop2();
273
							codeStream.pop2();
Lines 288-307 Link Here
288
290
289
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
291
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
290
	boolean isStatic;
292
	boolean isStatic;
291
	this.receiver.generateCode(
293
	FieldBinding codegenBinding = this.binding.original();
292
		currentScope,
294
	this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
293
		codeStream,
294
		!(isStatic = this.codegenBinding.isStatic()));
295
	if (isStatic) {
295
	if (isStatic) {
296
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
296
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
297
			codeStream.getstatic(this.codegenBinding);
297
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
298
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
298
		} else {
299
		} else {
299
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
300
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
300
		}
301
		}
301
	} else {
302
	} else {
302
		codeStream.dup();
303
		codeStream.dup();
303
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
304
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
304
			codeStream.getfield(this.codegenBinding);
305
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
306
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
305
		} else {
307
		} else {
306
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
308
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
307
		}
309
		}
Lines 329-358 Link Here
329
			// cast the value back to the array reference type
331
			// cast the value back to the array reference type
330
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
332
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
331
	}
333
	}
332
	fieldStore(
334
	fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], valueRequired);
333
		codeStream,
334
		this.codegenBinding,
335
		this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
336
		valueRequired);
337
	// no need for generic cast as value got dupped
335
	// no need for generic cast as value got dupped
338
}
336
}
339
337
340
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
338
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
341
	boolean isStatic;
339
	boolean isStatic;
342
	this.receiver.generateCode(
340
	FieldBinding codegenBinding = this.binding.original();
343
		currentScope,
341
	this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
344
		codeStream,
345
		!(isStatic = this.codegenBinding.isStatic()));
346
	if (isStatic) {
342
	if (isStatic) {
347
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
343
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
348
			codeStream.getstatic(this.codegenBinding);
344
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
345
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
349
		} else {
346
		} else {
350
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
347
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
351
		}
348
		}
352
	} else {
349
	} else {
353
		codeStream.dup();
350
		codeStream.dup();
354
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
351
		if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
355
			codeStream.getfield(this.codegenBinding);
352
			TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis());
353
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
356
		} else {
354
		} else {
357
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
355
			codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */);
358
		}
356
		}
Lines 362-384 Link Here
362
		codeStream.checkcast(this.genericCast);
360
		codeStream.checkcast(this.genericCast);
363
		operandType = this.genericCast;
361
		operandType = this.genericCast;
364
	} else {
362
	} else {
365
		operandType = this.codegenBinding.type;
363
		operandType = codegenBinding.type;
366
	}	
364
	}	
367
	if (valueRequired) {
365
	if (valueRequired) {
368
		if (isStatic) {
366
		if (isStatic) {
369
			if ((operandType == TypeBinding.LONG)
367
			switch (operandType.id) {
370
				|| (operandType == TypeBinding.DOUBLE)) {
368
				case TypeIds.T_long :
371
				codeStream.dup2();
369
				case TypeIds.T_double :
372
			} else {
370
					codeStream.dup2();
373
				codeStream.dup();
371
					break;
374
			}
372
				default :
373
					codeStream.dup();
374
					break;
375
			}			
375
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
376
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
376
			if ((operandType == TypeBinding.LONG)
377
			switch (operandType.id) {
377
				|| (operandType == TypeBinding.DOUBLE)) {
378
				case TypeIds.T_long :
378
				codeStream.dup2_x1();
379
				case TypeIds.T_double :
379
			} else {
380
					codeStream.dup2_x1();
380
				codeStream.dup_x1();
381
					break;
381
			}
382
				default :
383
					codeStream.dup_x1();
384
					break;
385
			}			
382
		}
386
		}
383
	}
387
	}
384
	codeStream.generateImplicitConversion(this.implicitConversion);		
388
	codeStream.generateImplicitConversion(this.implicitConversion);		
Lines 388-394 Link Here
388
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
392
	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
389
	codeStream.generateImplicitConversion(
393
	codeStream.generateImplicitConversion(
390
		postIncrement.preAssignImplicitConversion);
394
		postIncrement.preAssignImplicitConversion);
391
	fieldStore(codeStream, this.codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false);
395
	fieldStore(codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false);
392
}
396
}
393
397
394
/**
398
/**
Lines 412-427 Link Here
412
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
416
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
413
417
414
	// if field from parameterized type got found, use the original field at codegen time
418
	// if field from parameterized type got found, use the original field at codegen time
415
	this.codegenBinding = this.binding.original();
419
	FieldBinding codegenBinding = this.binding.original();
416
420
417
	if (this.binding.isPrivate()) {
421
	if (this.binding.isPrivate()) {
418
		if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass)
422
		if ((currentScope.enclosingSourceType() != codegenBinding.declaringClass)
419
				&& this.binding.constant() == Constant.NotAConstant) {
423
				&& this.binding.constant() == Constant.NotAConstant) {
420
			if (this.syntheticAccessors == null)
424
			if (this.syntheticAccessors == null)
421
				this.syntheticAccessors = new MethodBinding[2];
425
				this.syntheticAccessors = new MethodBinding[2];
422
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] =
426
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] =
423
				((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess);
427
				((SourceTypeBinding) codegenBinding.declaringClass).addSyntheticMethod(codegenBinding, isReadAccess);
424
			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
428
			currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
425
			return;
429
			return;
426
		}
430
		}
427
431
Lines 433-440 Link Here
433
				.currentCompatibleType);
437
				.currentCompatibleType);
434
		if (this.syntheticAccessors == null)
438
		if (this.syntheticAccessors == null)
435
			this.syntheticAccessors = new MethodBinding[2];
439
			this.syntheticAccessors = new MethodBinding[2];
436
		this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess);
440
		this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(codegenBinding, isReadAccess);
437
		currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
441
		currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
438
		return;
442
		return;
439
443
440
	} else if (this.binding.isProtected()) {
444
	} else if (this.binding.isProtected()) {
Lines 449-479 Link Here
449
					(this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
453
					(this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
450
			if (this.syntheticAccessors == null)
454
			if (this.syntheticAccessors == null)
451
				this.syntheticAccessors = new MethodBinding[2];
455
				this.syntheticAccessors = new MethodBinding[2];
452
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess);
456
			this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(codegenBinding, isReadAccess);
453
			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
457
			currentScope.problemReporter().needToEmulateFieldAccess(codegenBinding, this, isReadAccess);
454
			return;
458
			return;
455
		}
459
		}
456
	}
460
	}
457
	// if the binding declaring class is not visible, need special action
458
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
459
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
460
	// and not from Object or implicit static field access.
461
	if (this.binding.declaringClass != this.receiverType
462
			&& !this.receiverType.isArrayType()
463
			&& this.binding.declaringClass != null // array.length
464
			&& this.binding.constant() == Constant.NotAConstant) {
465
		CompilerOptions options = currentScope.compilerOptions();
466
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
467
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic()))
468
				&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
469
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
470
471
			this.codegenBinding =
472
				currentScope.enclosingSourceType().getUpdatedFieldBinding(
473
					this.codegenBinding,
474
					(ReferenceBinding) this.receiverType.erasure());
475
		}
476
	}
477
}
461
}
478
462
479
public int nullStatus(FlowInfo flowInfo) {
463
public int nullStatus(FlowInfo flowInfo) {
Lines 546-580 Link Here
546
		this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
530
		this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
547
		receiverCast = true;
531
		receiverCast = true;
548
	}
532
	}
549
	this.receiverType = this.receiver.resolveType(scope);
533
	this.actualReceiverType = this.receiver.resolveType(scope);
550
	if (this.receiverType == null) {
534
	if (this.actualReceiverType == null) {
551
		this.constant = Constant.NotAConstant;
535
		this.constant = Constant.NotAConstant;
552
		return null;
536
		return null;
553
	}
537
	}
554
	if (receiverCast) {
538
	if (receiverCast) {
555
		 // due to change of declaring class with receiver type, only identity cast should be notified
539
		 // due to change of declaring class with receiver type, only identity cast should be notified
556
		if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) {
540
		if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) {
557
				scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
541
				scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);
558
		}
542
		}
559
	}
543
	}
560
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
544
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
561
	FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this);
545
	FieldBinding fieldBinding = this.binding = scope.getField(this.actualReceiverType, this.token, this);
562
	if (!fieldBinding.isValidBinding()) {
546
	if (!fieldBinding.isValidBinding()) {
563
		this.constant = Constant.NotAConstant;
547
		this.constant = Constant.NotAConstant;
564
		if (this.receiver.resolvedType instanceof ProblemReferenceBinding) {
548
		if (this.receiver.resolvedType instanceof ProblemReferenceBinding) {
565
			// problem already got signaled on receiver, do not report secondary problem
549
			// problem already got signaled on receiver, do not report secondary problem
566
			return null;
550
			return null;
567
		}
551
		}
568
		scope.problemReporter().invalidField(this, this.receiverType);
552
		scope.problemReporter().invalidField(this, this.actualReceiverType);
569
		return null;
553
		return null;
570
	}
554
	}
571
	TypeBinding receiverErasure = this.receiverType.erasure();
555
	TypeBinding receiverErasure = this.actualReceiverType.erasure();
572
	if (receiverErasure instanceof ReferenceBinding) {
556
	if (receiverErasure instanceof ReferenceBinding) {
573
		if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) {
557
		if (receiverErasure.findSuperTypeOriginatingFrom(fieldBinding.declaringClass) == null) {
574
			this.receiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
558
			this.actualReceiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
575
		}
559
		}
576
	}
560
	}
577
	this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
561
	this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
578
	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) {
562
	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) {
579
		scope.problemReporter().deprecatedField(fieldBinding, this);
563
		scope.problemReporter().deprecatedField(fieldBinding, this);
580
	}
564
	}
Lines 589-595 Link Here
589
		}
573
		}
590
		ReferenceBinding declaringClass = this.binding.declaringClass;
574
		ReferenceBinding declaringClass = this.binding.declaringClass;
591
		if (!isImplicitThisRcv
575
		if (!isImplicitThisRcv
592
				&& declaringClass != this.receiverType
576
				&& declaringClass != this.actualReceiverType
593
				&& declaringClass.canBeSeenBy(scope)) {
577
				&& declaringClass.canBeSeenBy(scope)) {
594
			scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
578
			scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
595
		}
579
		}
Lines 620-626 Link Here
620
}
604
}
621
605
622
public void setActualReceiverType(ReferenceBinding receiverType) {
606
public void setActualReceiverType(ReferenceBinding receiverType) {
623
	// ignored
607
	this.actualReceiverType = receiverType;
624
}
608
}
625
609
626
public void setDepth(int depth) {
610
public void setDepth(int depth) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java (-5 / +5 lines)
Lines 373-383 Link Here
373
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
373
					if (scopeModifiers == -1) scopeModifiers = scope.getDeclarationModifiers();
374
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers);
374
					scope.problemReporter().javadocInvalidValueReference(fieldRef.sourceStart, fieldRef.sourceEnd, scopeModifiers);
375
				}
375
				}
376
				else if (fieldRef.receiverType != null) {
376
				else if (fieldRef.actualReceiverType != null) {
377
					if (scope.enclosingSourceType().isCompatibleWith(fieldRef.receiverType)) {
377
					if (scope.enclosingSourceType().isCompatibleWith(fieldRef.actualReceiverType)) {
378
						fieldRef.bits |= ASTNode.SuperAccess;
378
						fieldRef.bits |= ASTNode.SuperAccess;
379
					}
379
					}
380
					fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.receiverType, fieldRef.token, new TypeBinding[0], fieldRef);
380
					fieldRef.methodBinding = scope.findMethod((ReferenceBinding)fieldRef.actualReceiverType, fieldRef.token, new TypeBinding[0], fieldRef);
381
				}
381
				}
382
			}
382
			}
383
383
Lines 390-397 Link Here
390
			}
390
			}
391
391
392
			// Verify type references
392
			// Verify type references
393
			if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.receiverType instanceof ReferenceBinding) {
393
			if (!hasProblems && fieldRef.binding != null && fieldRef.binding.isValidBinding() && fieldRef.actualReceiverType instanceof ReferenceBinding) {
394
				ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.receiverType;
394
				ReferenceBinding resolvedType = (ReferenceBinding) fieldRef.actualReceiverType;
395
				verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers);
395
				verifyTypeReference(fieldRef, fieldRef.receiver, scope, source15, resolvedType, fieldRef.binding.modifiers);
396
			}
396
			}
397
397
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-30 / +1 lines)
Lines 149-155 Link Here
149
149
150
	// actual message invocation
150
	// actual message invocation
151
	if (this.syntheticAccessor == null){
151
	if (this.syntheticAccessor == null){
152
		TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope);
152
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null);
153
		if (isStatic){
153
		if (isStatic){
154
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
154
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
155
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
155
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
Lines 193-227 Link Here
193
	return this.genericTypeArguments;
193
	return this.genericTypeArguments;
194
}
194
}
195
195
196
protected TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope) {
197
	// constantpool declaringClass
198
	MethodBinding codegenBinding = this.binding.original();
199
	TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
200
	// Post 1.4.0 target, array clone() invocations are qualified with array type
201
	// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
202
	if (codegenBinding == currentScope.environment().arrayClone) {
203
		CompilerOptions options = currentScope.compilerOptions();
204
		if (options.sourceLevel > ClassFileConstants.JDK1_4 ) {
205
			constantPoolDeclaringClass = this.actualReceiverType.erasure();
206
		}
207
	} else {
208
		// if the binding declaring class is not visible, need special action
209
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
210
		// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
211
		// and not from Object or implicit static method call.
212
		if (constantPoolDeclaringClass != this.actualReceiverType && this.receiverGenericCast == null && !this.actualReceiverType.isArrayType()) {
213
			CompilerOptions options = currentScope.compilerOptions();
214
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
215
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && codegenBinding.isStatic()))
216
						&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
217
					|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
218
				constantPoolDeclaringClass = this.actualReceiverType.erasure();
219
			}
220
		}				
221
	}
222
	return constantPoolDeclaringClass;
223
}
224
225
public boolean isSuperAccess() {
196
public boolean isSuperAccess() {
226
	return this.receiver.isSuper();
197
	return this.receiver.isSuper();
227
}
198
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java (-8 / +8 lines)
Lines 41-59 Link Here
41
41
42
		this.constant = Constant.NotAConstant;
42
		this.constant = Constant.NotAConstant;
43
		if (this.receiver == null) {
43
		if (this.receiver == null) {
44
			this.receiverType = scope.enclosingReceiverType();
44
			this.actualReceiverType = scope.enclosingReceiverType();
45
		} else if (scope.kind == Scope.CLASS_SCOPE) {
45
		} else if (scope.kind == Scope.CLASS_SCOPE) {
46
			this.receiverType = this.receiver.resolveType((ClassScope) scope);
46
			this.actualReceiverType = this.receiver.resolveType((ClassScope) scope);
47
		} else {
47
		} else {
48
			this.receiverType = this.receiver.resolveType((BlockScope)scope);
48
			this.actualReceiverType = this.receiver.resolveType((BlockScope)scope);
49
		}
49
		}
50
		if (this.receiverType == null) {
50
		if (this.actualReceiverType == null) {
51
			return null;
51
			return null;
52
		}
52
		}
53
53
54
		Binding fieldBinding = (this.receiver != null && this.receiver.isThis())
54
		Binding fieldBinding = (this.receiver != null && this.receiver.isThis())
55
			? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/)
55
			? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/)
56
			: scope.getField(this.receiverType, this.token, this);
56
			: scope.getField(this.actualReceiverType, this.token, this);
57
		if (!fieldBinding.isValidBinding()) {
57
		if (!fieldBinding.isValidBinding()) {
58
			// implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
58
			// implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
59
			switch (fieldBinding.problemId()) {
59
			switch (fieldBinding.problemId()) {
Lines 72-79 Link Here
72
				// problem already got signaled on receiver, do not report secondary problem
72
				// problem already got signaled on receiver, do not report secondary problem
73
				return null;
73
				return null;
74
			}
74
			}
75
			if (this.receiverType instanceof ReferenceBinding) {
75
			if (this.actualReceiverType instanceof ReferenceBinding) {
76
				ReferenceBinding refBinding = (ReferenceBinding) this.receiverType;
76
				ReferenceBinding refBinding = (ReferenceBinding) this.actualReceiverType;
77
				MethodBinding possibleMethod = this.receiver.isThis()
77
				MethodBinding possibleMethod = this.receiver.isThis()
78
					? scope.getImplicitMethod(this.token, Binding.NO_TYPES, this)
78
					? scope.getImplicitMethod(this.token, Binding.NO_TYPES, this)
79
					: scope.getMethod(refBinding, this.token, Binding.NO_TYPES, this);
79
					: scope.getMethod(refBinding, this.token, Binding.NO_TYPES, this);
Lines 82-88 Link Here
82
				} else {
82
				} else {
83
					ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod;
83
					ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) possibleMethod;
84
					if (problemMethodBinding.closestMatch == null) {
84
					if (problemMethodBinding.closestMatch == null) {
85
						scope.problemReporter().javadocInvalidField(this, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
85
						scope.problemReporter().javadocInvalidField(this, fieldBinding, this.actualReceiverType, scope.getDeclarationModifiers());
86
					} else {
86
					} else {
87
						this.methodBinding = problemMethodBinding.closestMatch;
87
						this.methodBinding = problemMethodBinding.closestMatch;
88
					}
88
					}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-161 / +104 lines)
Lines 44-50 Link Here
44
44
45
	public char[][] tokens;
45
	public char[][] tokens;
46
	public long[] sourcePositions;
46
	public long[] sourcePositions;
47
	public FieldBinding[] otherBindings, otherCodegenBindings;
47
	public FieldBinding[] otherBindings;
48
	int[] otherDepths;
48
	int[] otherDepths;
49
	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
49
	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
50
	public SyntheticMethodBinding syntheticWriteAccessor;
50
	public SyntheticMethodBinding syntheticWriteAccessor;
Lines 69-75 Link Here
69
		case Binding.FIELD : // reading a field
69
		case Binding.FIELD : // reading a field
70
			lastFieldBinding = (FieldBinding) this.binding;
70
			lastFieldBinding = (FieldBinding) this.binding;
71
			if (needValue || complyTo14) {
71
			if (needValue || complyTo14) {
72
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
72
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, 0, flowInfo);
73
			}
73
			}
74
			// check if final blank field
74
			// check if final blank field
75
			if (lastFieldBinding.isBlankFinal()
75
			if (lastFieldBinding.isBlankFinal()
Lines 107-120 Link Here
107
			lastFieldBinding = this.otherBindings[i];
107
			lastFieldBinding = this.otherBindings[i];
108
			needValue = !this.otherBindings[i+1].isStatic();
108
			needValue = !this.otherBindings[i+1].isStatic();
109
			if (needValue || complyTo14) {
109
			if (needValue || complyTo14) {
110
				manageSyntheticAccessIfNecessary(
110
				manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, i + 1, flowInfo);
111
					currentScope,
112
					lastFieldBinding,
113
					i == 0
114
						? ((VariableBinding)this.binding).type
115
						: this.otherBindings[i-1].type,
116
					i + 1,
117
					flowInfo);
118
			}
111
			}
119
		}
112
		}
120
		lastFieldBinding = this.otherBindings[otherBindingsCount-1];
113
		lastFieldBinding = this.otherBindings[otherBindingsCount-1];
Lines 127-150 Link Here
127
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
120
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
128
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
121
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
129
		}
122
		}
130
		TypeBinding lastReceiverType;
123
		manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, otherBindingsCount, flowInfo);
131
		switch (otherBindingsCount) {
132
			case 0 :
133
				lastReceiverType = this.actualReceiverType;
134
				break;
135
			case 1 :
136
				lastReceiverType = ((VariableBinding)this.binding).type;
137
				break;
138
			default:
139
				lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
140
				break;
141
		}
142
		manageSyntheticAccessIfNecessary(
143
			currentScope,
144
			lastFieldBinding,
145
			lastReceiverType,
146
			otherBindingsCount,
147
			flowInfo);
148
	}
124
	}
149
125
150
	if (assignment.expression != null) {
126
	if (assignment.expression != null) {
Lines 176-195 Link Here
176
			}
152
			}
177
		}
153
		}
178
	}
154
	}
179
	// equivalent to valuesRequired[maxOtherBindings]
155
	manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, -1 /*write-access*/, flowInfo);
180
	TypeBinding lastReceiverType;
181
	switch (otherBindingsCount) {
182
		case 0 :
183
			lastReceiverType = this.actualReceiverType;
184
			break;
185
		case 1 :
186
			lastReceiverType = ((VariableBinding)this.binding).type;
187
			break;
188
		default :
189
			lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
190
			break;
191
	}
192
	manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
193
156
194
	return flowInfo;
157
	return flowInfo;
195
}
158
}
Lines 207-213 Link Here
207
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
170
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
208
		case Binding.FIELD : // reading a field
171
		case Binding.FIELD : // reading a field
209
			if (needValue || complyTo14) {
172
			if (needValue || complyTo14) {
210
				manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, this.actualReceiverType, 0, flowInfo);
173
				manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, 0, flowInfo);
211
			}
174
			}
212
			if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
175
			if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
213
				FieldBinding fieldBinding = (FieldBinding) this.binding;
176
				FieldBinding fieldBinding = (FieldBinding) this.binding;
Lines 221-228 Link Here
221
			break;
184
			break;
222
		case Binding.LOCAL : // reading a local variable
185
		case Binding.LOCAL : // reading a local variable
223
			LocalVariableBinding localBinding;
186
			LocalVariableBinding localBinding;
224
			if (!flowInfo
187
			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
225
				.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
226
				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
188
				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
227
			}
189
			}
228
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
190
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0)	{
Lines 240-259 Link Here
240
		for (int i = 0; i < otherBindingsCount; i++) {
202
		for (int i = 0; i < otherBindingsCount; i++) {
241
			needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired;
203
			needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired;
242
			if (needValue || complyTo14) {
204
			if (needValue || complyTo14) {
243
				TypeBinding lastReceiverType = getGenericCast(i);
205
				manageSyntheticAccessIfNecessary(currentScope, this.otherBindings[i], i + 1, flowInfo);
244
				if (lastReceiverType == null) {
245
					if (i == 0) {
246
						 lastReceiverType = ((VariableBinding)this.binding).type;
247
					} else {
248
						lastReceiverType = this.otherBindings[i-1].type;
249
					}
250
				}
251
				manageSyntheticAccessIfNecessary(
252
					currentScope,
253
					this.otherBindings[i],
254
					lastReceiverType,
255
					i + 1,
256
					flowInfo);
257
			}
206
			}
258
		}
207
		}
259
	}
208
	}
Lines 376-382 Link Here
376
				boolean isFirst = lastFieldBinding == this.binding
325
				boolean isFirst = lastFieldBinding == this.binding
377
												&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
326
												&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
378
												&& this.otherBindings == null; // could be dup: next.next.next
327
												&& this.otherBindings == null; // could be dup: next.next.next
379
				TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
328
				TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
380
				if (valueRequired
329
				if (valueRequired
381
						|| (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
330
						|| (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
382
						|| ((this.implicitConversion & TypeIds.UNBOXING) != 0)
331
						|| ((this.implicitConversion & TypeIds.UNBOXING) != 0)
Lines 391-405 Link Here
391
							codeStream.pop();
340
							codeStream.pop();
392
						}
341
						}
393
					} else {
342
					} else {
394
						SyntheticMethodBinding accessor =
343
						SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
395
							this.syntheticReadAccessors == null
396
								? null
397
								: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
398
						if (accessor == null) {
344
						if (accessor == null) {
345
							TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);
399
							if (isStatic) {
346
							if (isStatic) {
400
								codeStream.getstatic(lastFieldBinding);
347
								codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
401
							} else {
348
							} else {
402
								codeStream.getfield(lastFieldBinding);
349
								codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
403
							}
350
							}
404
						} else {
351
						} else {
405
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
352
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
Lines 436-464 Link Here
436
	codeStream.recordPositionsFrom(pc, this.sourceStart);
383
	codeStream.recordPositionsFrom(pc, this.sourceStart);
437
}
384
}
438
385
439
public void generateCompoundAssignment(
386
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
440
	BlockScope currentScope,
441
	CodeStream codeStream,
442
	Expression expression,
443
	int operator,
444
	int assignmentImplicitConversion,
445
	boolean valueRequired) {
446
447
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
387
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
448
	SyntheticMethodBinding accessor =
388
	boolean isFirst = lastFieldBinding == this.binding
449
		this.syntheticReadAccessors == null
389
		&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
450
			? null
390
		&& this.otherBindings == null; // could be dup: next.next.next
451
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
391
	TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);			
392
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
452
	if (lastFieldBinding.isStatic()) {
393
	if (lastFieldBinding.isStatic()) {
453
		if (accessor == null) {
394
		if (accessor == null) {
454
			codeStream.getstatic(lastFieldBinding);
395
			codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
455
		} else {
396
		} else {
456
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
397
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
457
		}
398
		}
458
	} else {
399
	} else {
459
		codeStream.dup();
400
		codeStream.dup();
460
		if (accessor == null) {
401
		if (accessor == null) {
461
			codeStream.getfield(lastFieldBinding);
402
			codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
462
		} else {
403
		} else {
463
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
404
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
464
		}
405
		}
Lines 473-479 Link Here
473
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
414
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
474
			break;
415
			break;
475
		default :
416
		default :
476
			TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
417
			TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
477
			if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
418
			if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
478
			// promote the array reference to the suitable operation type
419
			// promote the array reference to the suitable operation type
479
			codeStream.generateImplicitConversion(this.implicitConversion);
420
			codeStream.generateImplicitConversion(this.implicitConversion);
Lines 495-518 Link Here
495
436
496
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
437
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
497
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
438
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
439
	boolean isFirst = lastFieldBinding == this.binding
440
		&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
441
		&& this.otherBindings == null; // could be dup: next.next.next
442
	TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);			
498
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null
443
	SyntheticMethodBinding accessor = this.syntheticReadAccessors == null
499
			? null
444
			? null
500
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
445
			: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
501
	if (lastFieldBinding.isStatic()) {
446
	if (lastFieldBinding.isStatic()) {
502
		if (accessor == null) {
447
		if (accessor == null) {
503
			codeStream.getstatic(lastFieldBinding);
448
			codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
504
		} else {
449
		} else {
505
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
450
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass);
506
		}
451
		}
507
	} else {
452
	} else {
508
		codeStream.dup();
453
		codeStream.dup();
509
		if (accessor == null) {
454
		if (accessor == null) {
510
			codeStream.getfield(lastFieldBinding);
455
			codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, null /* default declaringClass */);
511
		} else {
456
		} else {
512
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
457
			codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
513
		}
458
		}
514
	}
459
	}
515
	TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
460
	TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
516
	TypeBinding operandType;
461
	TypeBinding operandType;
517
	if (requiredGenericCast != null) {
462
	if (requiredGenericCast != null) {
518
		codeStream.checkcast(requiredGenericCast);
463
		codeStream.checkcast(requiredGenericCast);
Lines 523-541 Link Here
523
	// duplicate the old field value
468
	// duplicate the old field value
524
	if (valueRequired) {
469
	if (valueRequired) {
525
		if (lastFieldBinding.isStatic()) {
470
		if (lastFieldBinding.isStatic()) {
526
			if ((operandType == TypeBinding.LONG)
471
			switch (operandType.id) {
527
				|| (operandType == TypeBinding.DOUBLE)) {
472
				case TypeIds.T_long :
528
				codeStream.dup2();
473
				case TypeIds.T_double :
529
			} else {
474
					codeStream.dup2();
530
				codeStream.dup();
475
					break;
531
			}
476
				default:
477
					codeStream.dup();
478
					break;
479
			}			
532
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
480
		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
533
			if ((operandType == TypeBinding.LONG)
481
			switch (operandType.id) {
534
				|| (operandType == TypeBinding.DOUBLE)) {
482
				case TypeIds.T_long :
535
				codeStream.dup2_x1();
483
				case TypeIds.T_double :
536
			} else {
484
					codeStream.dup2_x1();
537
				codeStream.dup_x1();
485
					break;
538
			}
486
				default:
487
					codeStream.dup_x1();
488
					break;
489
			}			
539
		}
490
		}
540
	}
491
	}
541
	codeStream.generateImplicitConversion(this.implicitConversion);		
492
	codeStream.generateImplicitConversion(this.implicitConversion);		
Lines 554-569 Link Here
554
 */
505
 */
555
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
506
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
556
	// determine the rank until which we now we do not need any actual value for the field access
507
	// determine the rank until which we now we do not need any actual value for the field access
557
	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
508
	int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
558
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
509
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
559
	FieldBinding lastFieldBinding = null;
510
	FieldBinding lastFieldBinding;
560
	TypeBinding lastGenericCast = null;
511
	TypeBinding lastGenericCast;
512
	TypeBinding lastReceiverType;
561
	boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
513
	boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
562
514
563
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
515
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
564
		case Binding.FIELD :
516
		case Binding.FIELD :
565
			lastFieldBinding = (FieldBinding) this.codegenBinding;
517
			lastFieldBinding = ((FieldBinding) this.binding).original();
566
			lastGenericCast = this.genericCast;
518
			lastGenericCast = this.genericCast;
519
			lastReceiverType = this.actualReceiverType;
567
			// if first field is actually constant, we can inline it
520
			// if first field is actually constant, we can inline it
568
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
521
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
569
				break;
522
				break;
Lines 581-588 Link Here
581
			}
534
			}
582
			break;
535
			break;
583
		case Binding.LOCAL : // reading the first local variable
536
		case Binding.LOCAL : // reading the first local variable
537
			lastFieldBinding = null;
538
			lastGenericCast = null;
539
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
540
			lastReceiverType = localBinding.type;
584
			if (!needValue) break; // no value needed
541
			if (!needValue) break; // no value needed
585
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
586
			// regular local variable read
542
			// regular local variable read
587
			Constant localConstant = localBinding.constant();
543
			Constant localConstant = localBinding.constant();
588
			if (localConstant != Constant.NotAConstant) {
544
			if (localConstant != Constant.NotAConstant) {
Lines 598-612 Link Here
598
					codeStream.load(localBinding);
554
					codeStream.load(localBinding);
599
				}
555
				}
600
			}
556
			}
557
			break;
558
		default : // should not occur
559
			return null;
601
	}
560
	}
602
561
603
	// all intermediate field accesses are read accesses
562
	// all intermediate field accesses are read accesses
604
	// only the last field binding is a write access
563
	// only the last field binding is a write access
605
	int positionsLength = this.sourcePositions.length;
564
	int positionsLength = this.sourcePositions.length;
606
	if (this.otherCodegenBindings != null) {
565
	FieldBinding initialFieldBinding = lastFieldBinding; // can be null if initial was a local binding
566
	if (this.otherBindings != null) {
607
		for (int i = 0; i < otherBindingsCount; i++) {
567
		for (int i = 0; i < otherBindingsCount; i++) {
608
			int pc = codeStream.position;
568
			int pc = codeStream.position;
609
			FieldBinding nextField = this.otherCodegenBindings[i];
569
			FieldBinding nextField = this.otherBindings[i].original();
610
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
570
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
611
			if (lastFieldBinding != null) {
571
			if (lastFieldBinding != null) {
612
				needValue = !nextField.isStatic();
572
				needValue = !nextField.isStatic();
Lines 623-646 Link Here
623
					if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
583
					if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) {
624
						MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
584
						MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
625
						if (accessor == null) {
585
						if (accessor == null) {
586
							TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
626
							if (lastFieldBinding.isStatic()) {
587
							if (lastFieldBinding.isStatic()) {
627
								codeStream.getstatic(lastFieldBinding);
588
								codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
628
							} else {
589
							} else {
629
								codeStream.getfield(lastFieldBinding);
590
								codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
630
							}
591
							}
631
						} else {
592
						} else {
632
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
593
							codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
633
						}
594
						}
634
						if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
595
						if (lastGenericCast != null) {
596
							codeStream.checkcast(lastGenericCast);
597
							lastReceiverType = lastGenericCast;
598
						} else {
599
							lastReceiverType = lastFieldBinding.type;
600
						}
635
						if (!needValue) codeStream.pop();
601
						if (!needValue) codeStream.pop();
636
					} else {
602
					} else {
637
						if (this.codegenBinding == lastFieldBinding) {
603
						if (lastFieldBinding == initialFieldBinding) {
638
							if (lastFieldBinding.isStatic()){
604
							if (lastFieldBinding.isStatic()){
639
								// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
605
								// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
640
								if (((FieldBinding)this.binding).original().declaringClass != this.actualReceiverType.erasure()) {
606
								if (initialFieldBinding.declaringClass != this.actualReceiverType.erasure()) {
641
									MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
607
									MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i];
642
									if (accessor == null) {
608
									if (accessor == null) {
643
										codeStream.getstatic(lastFieldBinding);
609
										TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, lastReceiverType, i == 0 && this.indexOfFirstFieldBinding == 1);
610
										codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
644
									} else {
611
									} else {
645
										codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
612
										codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
646
									}
613
									}
Lines 651-656 Link Here
651
							codeStream.invokeObjectGetClass(); // perform null check
618
							codeStream.invokeObjectGetClass(); // perform null check
652
							codeStream.pop();
619
							codeStream.pop();
653
						}
620
						}
621
						lastReceiverType = lastFieldBinding.type;
654
					}
622
					}
655
					if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
623
					if ((positionsLength - otherBindingsCount + i - 1) >= 0) {
656
						int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
624
						int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32);
Lines 676-690 Link Here
676
	return null;
644
	return null;
677
}
645
}
678
646
679
// get the matching codegenBinding
680
protected FieldBinding getCodegenBinding(int index) {
647
protected FieldBinding getCodegenBinding(int index) {
681
  if (index == 0){
648
  if (index == 0){
682
		return (FieldBinding)this.codegenBinding;
649
		return ((FieldBinding)this.binding).original();
683
	} else {
650
	} else {
684
		return this.otherCodegenBindings[index-1];
651
		return this.otherBindings[index-1].original();
685
	}
652
	}
686
}
653
}
687
654
655
/**
656
 * Returns the receiver type for the final field in sequence (i.e. the return type of the previous binding)
657
 * @return receiver type for the final field in sequence
658
 */
659
protected TypeBinding getFinalReceiverType() {
660
	int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length;
661
	switch (otherBindingsCount) {
662
		case 0 :
663
			return this.actualReceiverType;
664
		case 1 :
665
			return this.genericCast != null ? this.genericCast : ((VariableBinding)this.binding).type;
666
		default:
667
			TypeBinding previousGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[otherBindingsCount-2];
668
			return previousGenericCast != null ? previousGenericCast : this.otherBindings[otherBindingsCount-2].type;
669
	}	
670
}
671
688
// get the matching generic cast
672
// get the matching generic cast
689
protected TypeBinding getGenericCast(int index) {
673
protected TypeBinding getGenericCast(int index) {
690
   if (index == 0){
674
   if (index == 0){
Lines 694-700 Link Here
694
		return this.otherGenericCasts[index-1];
678
		return this.otherGenericCasts[index-1];
695
	}
679
	}
696
}
680
}
697
698
public TypeBinding getOtherFieldBindings(BlockScope scope) {
681
public TypeBinding getOtherFieldBindings(BlockScope scope) {
699
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
682
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
700
	int length = this.tokens.length;
683
	int length = this.tokens.length;
Lines 730-736 Link Here
730
	}
713
	}
731
	// allocation of the fieldBindings array	and its respective constants
714
	// allocation of the fieldBindings array	and its respective constants
732
	int otherBindingsLength = length - index;
715
	int otherBindingsLength = length - index;
733
	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
716
	this.otherBindings = new FieldBinding[otherBindingsLength];
734
	this.otherDepths = new int[otherBindingsLength];
717
	this.otherDepths = new int[otherBindingsLength];
735
718
736
	// fill the first constant (the one of the binding)
719
	// fill the first constant (the one of the binding)
Lines 825-842 Link Here
825
/**
808
/**
826
 * index is <0 to denote write access emulation
809
 * index is <0 to denote write access emulation
827
 */
810
 */
828
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, 	int index, FlowInfo flowInfo) {
811
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, int index, FlowInfo flowInfo) {
829
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
812
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)	return;
830
	// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
813
	// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
831
	if (fieldBinding.constant() != Constant.NotAConstant)
814
	if (fieldBinding.constant() != Constant.NotAConstant)
832
		return;
815
		return;
833
816
834
	// if field from parameterized type got found, use the original field at codegen time
835
	FieldBinding originalField = fieldBinding.original();
836
	if (originalField != fieldBinding) {
837
		setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField);
838
	}
839
840
	if (fieldBinding.isPrivate()) { // private access
817
	if (fieldBinding.isPrivate()) { // private access
841
	    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
818
	    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
842
		if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
819
		if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) {
Lines 852-885 Link Here
852
829
853
		// implicit protected access
830
		// implicit protected access
854
		if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
831
		if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) {
855
		    FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
832
		    FieldBinding codegenField = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index);
856
		    setSyntheticAccessor(fieldBinding, index,
833
		    setSyntheticAccessor(fieldBinding, index,
857
		            ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 /*read-access?*/));
834
		            ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(codegenField, index >= 0 /*read-access?*/));
858
			currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 /*read-access?*/);
835
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, index >= 0 /*read-access?*/);
859
			return;
836
			return;
860
		}
837
		}
861
	}
838
	}
862
	// if the binding declaring class is not visible, need special action
863
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
864
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
865
	// and not from Object or implicit static field access.
866
	if (fieldBinding.declaringClass != lastReceiverType
867
			&& !lastReceiverType.isArrayType()
868
			&& fieldBinding.declaringClass != null // array.length
869
			&& fieldBinding.constant() == Constant.NotAConstant) {
870
		CompilerOptions options = currentScope.compilerOptions();
871
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
872
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 &&  this.indexOfFirstFieldBinding == 1 && fieldBinding.isStatic()))
873
				&& fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
874
				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
875
876
		    setCodegenBinding(
877
		            index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index,
878
		            currentScope.enclosingSourceType().getUpdatedFieldBinding(
879
		                    getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index),
880
		                    (ReferenceBinding)lastReceiverType.erasure()));
881
		}
882
	}
883
}
839
}
884
840
885
public int nullStatus(FlowInfo flowInfo) {
841
public int nullStatus(FlowInfo flowInfo) {
Lines 908-914 Link Here
908
 */
864
 */
909
public TypeBinding postConversionType(Scope scope) {
865
public TypeBinding postConversionType(Scope scope) {
910
	TypeBinding convertedType = this.resolvedType;
866
	TypeBinding convertedType = this.resolvedType;
911
	TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
867
	TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
912
	if (requiredGenericCast != null)
868
	if (requiredGenericCast != null)
913
		convertedType = requiredGenericCast;
869
		convertedType = requiredGenericCast;
914
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
870
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
Lines 973-979 Link Here
973
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
929
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
974
	this.actualReceiverType = scope.enclosingReceiverType();
930
	this.actualReceiverType = scope.enclosingReceiverType();
975
	this.constant = Constant.NotAConstant;
931
	this.constant = Constant.NotAConstant;
976
	if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
932
	if ((this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
977
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
933
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
978
			case Binding.VARIABLE : //============only variable===========
934
			case Binding.VARIABLE : //============only variable===========
979
			case Binding.TYPE | Binding.VARIABLE :
935
			case Binding.TYPE | Binding.VARIABLE :
Lines 1056-1074 Link Here
1056
	return this.resolvedType = reportError(scope);
1012
	return this.resolvedType = reportError(scope);
1057
}
1013
}
1058
1014
1059
// set the matching codegenBinding and generic cast
1060
protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) {
1061
	if (index == 0){
1062
		this.codegenBinding = someCodegenBinding;
1063
	} else {
1064
	    int length = this.otherBindings.length;
1065
		if (this.otherCodegenBindings == this.otherBindings){
1066
			System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length);
1067
		}
1068
		this.otherCodegenBindings[index-1] = someCodegenBinding;
1069
	}
1070
}
1071
1072
public void setFieldIndex(int index) {
1015
public void setFieldIndex(int index) {
1073
	this.indexOfFirstFieldBinding = index;
1016
	this.indexOfFirstFieldBinding = index;
1074
}
1017
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java (-2 / +2 lines)
Lines 104-112 Link Here
104
		this.initialization.generateCode(currentScope, codeStream, true);
104
		this.initialization.generateCode(currentScope, codeStream, true);
105
		// store into field
105
		// store into field
106
		if (isStatic) {
106
		if (isStatic) {
107
			codeStream.putstatic(this.binding);
107
			codeStream.fieldAccess(Opcodes.OPC_putstatic, this.binding, null /* default declaringClass */);
108
		} else {
108
		} else {
109
			codeStream.putfield(this.binding);
109
			codeStream.fieldAccess(Opcodes.OPC_putfield, this.binding, null /* default declaringClass */);
110
		}
110
		}
111
	}
111
	}
112
	codeStream.recordPositionsFrom(pc, this.sourceStart);
112
	codeStream.recordPositionsFrom(pc, this.sourceStart);
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java (-25 / +3 lines)
Lines 11-17 Link Here
11
package org.eclipse.jdt.internal.compiler.lookup;
11
package org.eclipse.jdt.internal.compiler.lookup;
12
12
13
import java.util.HashMap;
13
import java.util.HashMap;
14
import java.util.Hashtable;
15
import java.util.Iterator;
14
import java.util.Iterator;
16
15
17
import org.eclipse.jdt.core.compiler.CharOperation;
16
import org.eclipse.jdt.core.compiler.CharOperation;
Lines 26-33 Link Here
26
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
25
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
27
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
28
import org.eclipse.jdt.internal.compiler.impl.Constant;
27
import org.eclipse.jdt.internal.compiler.impl.Constant;
29
import org.eclipse.jdt.internal.compiler.util.Util;
30
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
28
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
29
import org.eclipse.jdt.internal.compiler.util.Util;
31
30
32
public class SourceTypeBinding extends ReferenceBinding {
31
public class SourceTypeBinding extends ReferenceBinding {
33
	public ReferenceBinding superclass;
32
	public ReferenceBinding superclass;
Lines 39-53 Link Here
39
38
40
	public ClassScope scope;
39
	public ClassScope scope;
41
40
42
	// Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
41
	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
43
	// if a new category is added, also increment MAX_SYNTHETICS
42
	// if a new category is added, also increment MAX_SYNTHETICS
44
	private final static int METHOD_EMUL = 0;
43
	private final static int METHOD_EMUL = 0;
45
	private final static int FIELD_EMUL = 1;
44
	private final static int FIELD_EMUL = 1;
46
	private final static int CLASS_LITERAL_EMUL = 2;
45
	private final static int CLASS_LITERAL_EMUL = 2;
47
	/** @deprecated */
48
	private final static int RECEIVER_TYPE_EMUL = 3;
49
46
50
	private final static int MAX_SYNTHETICS = 4;
47
	private final static int MAX_SYNTHETICS = 3;
51
48
52
	HashMap[] synthetics;
49
	HashMap[] synthetics;
53
	char[] genericReferenceTypeSignature;
50
	char[] genericReferenceTypeSignature;
Lines 1065-1089 Link Here
1065
public ReferenceBinding[] memberTypes() {
1062
public ReferenceBinding[] memberTypes() {
1066
	return this.memberTypes;
1063
	return this.memberTypes;
1067
}
1064
}
1068
///** @deprecated */
1069
public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
1070
	if (this.synthetics == null)
1071
		this.synthetics = new HashMap[MAX_SYNTHETICS];
1072
	if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1073
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(5);
1074
1075
	Hashtable fieldMap = (Hashtable) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetField);
1076
	if (fieldMap == null) {
1077
		fieldMap = new Hashtable(5);
1078
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
1079
	}
1080
	FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
1081
	if (updatedField == null){
1082
		updatedField = new FieldBinding(targetField, newDeclaringClass);
1083
		fieldMap.put(newDeclaringClass, updatedField);
1084
	}
1085
	return updatedField;
1086
}
1087
1065
1088
public boolean hasMemberTypes() {
1066
public boolean hasMemberTypes() {
1089
    return this.memberTypes.length > 0;
1067
    return this.memberTypes.length > 0;
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java (-165 / +185 lines)
Lines 21-26 Link Here
21
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
21
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
23
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
24
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
24
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.lookup.*;
26
import org.eclipse.jdt.internal.compiler.lookup.*;
26
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
27
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
Lines 1214-1219 Link Here
1214
	this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv;
1215
	this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_fdiv;
1215
}
1216
}
1216
1217
1218
public void fieldAccess(byte opcode, FieldBinding fieldBinding, TypeBinding declaringClass) {
1219
	if (declaringClass == null) declaringClass = fieldBinding.declaringClass;
1220
	if (declaringClass.leafComponentType().isNestedType()) {
1221
		this.classFile.recordInnerClasses(declaringClass);
1222
	}
1223
	TypeBinding returnType = fieldBinding.type;
1224
	int returnTypeSize;
1225
	switch (returnType.id) {
1226
		case TypeIds.T_long :
1227
		case TypeIds.T_double :
1228
			returnTypeSize = 2;
1229
			break;
1230
		default :
1231
			returnTypeSize = 1;
1232
			break;
1233
	}
1234
	this.fieldAccess(opcode, returnTypeSize, declaringClass.constantPoolName(), fieldBinding.name, returnType.signature());
1235
}
1236
1237
private void fieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] fieldName, char[] signature) {
1238
	this.countLabels = 0;
1239
	switch(opcode) {
1240
		case Opcodes.OPC_getfield :
1241
			if (returnTypeSize == 2) {
1242
				this.stackDepth++;
1243
			}
1244
			break;
1245
		case Opcodes.OPC_getstatic :
1246
			if (returnTypeSize == 2) {
1247
				this.stackDepth += 2;
1248
			} else {
1249
				this.stackDepth++;
1250
			}
1251
			break;
1252
		case Opcodes.OPC_putfield :
1253
			if (returnTypeSize == 2) {
1254
				this.stackDepth -= 3;
1255
			} else {
1256
				this.stackDepth -= 2;
1257
			}
1258
			break;
1259
		case Opcodes.OPC_putstatic :
1260
			if (returnTypeSize == 2) {
1261
				this.stackDepth -= 2;
1262
			} else {
1263
				this.stackDepth--;
1264
			}
1265
	}
1266
	if (this.stackDepth > this.stackMax) {
1267
		this.stackMax = this.stackDepth;
1268
	}
1269
	if (this.classFileOffset + 2 >= this.bCodeStream.length) {
1270
		resizeByteArray();
1271
	}
1272
	this.position++;
1273
	this.bCodeStream[this.classFileOffset++] = opcode;
1274
	writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, fieldName, signature));
1275
}
1276
1217
public void fload(int iArg) {
1277
public void fload(int iArg) {
1218
	this.countLabels = 0;
1278
	this.countLabels = 0;
1219
	this.stackDepth++;
1279
	this.stackDepth++;
Lines 1641-1647 Link Here
1641
	} else {
1701
	} else {
1642
		BranchLabel endLabel = new BranchLabel(this);
1702
		BranchLabel endLabel = new BranchLabel(this);
1643
		if (syntheticFieldBinding != null) { // non interface case
1703
		if (syntheticFieldBinding != null) { // non interface case
1644
			getstatic(syntheticFieldBinding);
1704
			fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
1645
			dup();
1705
			dup();
1646
			ifnonnull(endLabel);
1706
			ifnonnull(endLabel);
1647
			pop();
1707
			pop();
Lines 1684-1690 Link Here
1684
1744
1685
		if (syntheticFieldBinding != null) { // non interface case
1745
		if (syntheticFieldBinding != null) { // non interface case
1686
			dup();
1746
			dup();
1687
			putstatic(syntheticFieldBinding);
1747
			fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
1688
		}
1748
		}
1689
		goto_(endLabel);
1749
		goto_(endLabel);
1690
1750
Lines 1877-1933 Link Here
1877
	invokeAccessibleObjectSetAccessible();
1937
	invokeAccessibleObjectSetAccessible();
1878
}
1938
}
1879
1939
1880
private void generateFieldAccess(byte opcode, int returnTypeSize, char[] declaringClass, char[] name, char[] signature) {
1881
	this.countLabels = 0;
1882
	switch(opcode) {
1883
		case Opcodes.OPC_getfield :
1884
			if (returnTypeSize == 2) {
1885
				this.stackDepth++;
1886
			}
1887
			break;
1888
		case Opcodes.OPC_getstatic :
1889
			if (returnTypeSize == 2) {
1890
				this.stackDepth += 2;
1891
			} else {
1892
				this.stackDepth++;
1893
			}
1894
			break;
1895
		case Opcodes.OPC_putfield :
1896
			if (returnTypeSize == 2) {
1897
				this.stackDepth -= 3;
1898
			} else {
1899
				this.stackDepth -= 2;
1900
			}
1901
			break;
1902
		case Opcodes.OPC_putstatic :
1903
			if (returnTypeSize == 2) {
1904
				this.stackDepth -= 2;
1905
			} else {
1906
				this.stackDepth--;
1907
			}
1908
	}
1909
	if (this.stackDepth > this.stackMax) {
1910
		this.stackMax = this.stackDepth;
1911
	}
1912
	if (this.classFileOffset + 2 >= this.bCodeStream.length) {
1913
		resizeByteArray();
1914
	}
1915
	this.position++;
1916
	this.bCodeStream[this.classFileOffset++] = opcode;
1917
	writeUnsignedShort(this.constantPool.literalIndexForField(declaringClass, name, signature));
1918
}
1919
1920
private void generateFieldAccess(byte opcode, int returnTypeSize, ReferenceBinding binding, char[] name, TypeBinding type) {
1921
	if (binding.isNestedType()) {
1922
		this.classFile.recordInnerClasses(binding);
1923
	}
1924
	TypeBinding leafComponentType = type.leafComponentType();
1925
	if (leafComponentType.isNestedType()) {
1926
		this.classFile.recordInnerClasses(leafComponentType);
1927
	}
1928
	this.generateFieldAccess(opcode, returnTypeSize, binding.constantPoolName(), name, type.signature());
1929
}
1930
1931
/**
1940
/**
1932
 * Generates the sequence of instructions which will perform the conversion of the expression
1941
 * Generates the sequence of instructions which will perform the conversion of the expression
1933
 * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
1942
 * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted).
Lines 2251-2264 Link Here
2251
	} else if (mappingSequence[0] instanceof FieldBinding) {
2260
	} else if (mappingSequence[0] instanceof FieldBinding) {
2252
		FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
2261
		FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
2253
		aload_0();
2262
		aload_0();
2254
		getfield(fieldBinding);
2263
		fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2255
	} else {
2264
	} else {
2256
		load((LocalVariableBinding) mappingSequence[0]);
2265
		load((LocalVariableBinding) mappingSequence[0]);
2257
	}
2266
	}
2258
	for (int i = 1, length = mappingSequence.length; i < length; i++) {
2267
	for (int i = 1, length = mappingSequence.length; i < length; i++) {
2259
		if (mappingSequence[i] instanceof FieldBinding) {
2268
		if (mappingSequence[i] instanceof FieldBinding) {
2260
			FieldBinding fieldBinding = (FieldBinding) mappingSequence[i];
2269
			FieldBinding fieldBinding = (FieldBinding) mappingSequence[i];
2261
			getfield(fieldBinding);
2270
			fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2262
		} else {
2271
		} else {
2263
			invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */);
2272
			invoke(Opcodes.OPC_invokestatic, (MethodBinding) mappingSequence[i], null /* default declaringClass */);
2264
		}
2273
		}
Lines 2400-2410 Link Here
2400
//}
2409
//}
2401
public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
2410
public void generateSyntheticBodyForEnumValues(SyntheticMethodBinding methodBinding) {
2402
	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
2411
	ClassScope scope = ((SourceTypeBinding)methodBinding.declaringClass).scope;
2403
	FieldBinding enumValuesSyntheticfield = scope.referenceContext.enumValuesSyntheticfield;
2404
	initializeMaxLocals(methodBinding);
2412
	initializeMaxLocals(methodBinding);
2405
	TypeBinding enumArray = methodBinding.returnType;
2413
	TypeBinding enumArray = methodBinding.returnType;
2406
2414
	fieldAccess(Opcodes.OPC_getstatic, scope.referenceContext.enumValuesSyntheticfield, null /* default declaringClass */);
2407
	getstatic(enumValuesSyntheticfield);
2408
	dup();
2415
	dup();
2409
	astore_0();
2416
	astore_0();
2410
	iconst_0();
2417
	iconst_0();
Lines 2425-2435 Link Here
2425
public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
2432
public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessBinding) {
2426
	initializeMaxLocals(accessBinding);
2433
	initializeMaxLocals(accessBinding);
2427
	FieldBinding fieldBinding = accessBinding.targetReadField;
2434
	FieldBinding fieldBinding = accessBinding.targetReadField;
2428
	if (fieldBinding.isStatic())
2435
	if (fieldBinding.isStatic()) {
2429
		getstatic(fieldBinding);
2436
		fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */);
2430
	else {
2437
	} else {
2431
		aload_0();
2438
		aload_0();
2432
		getfield(fieldBinding);
2439
		fieldAccess(Opcodes.OPC_getfield, fieldBinding, null /* default declaringClass */);
2433
	}
2440
	}
2434
	switch (fieldBinding.type.id) {
2441
	switch (fieldBinding.type.id) {
2435
//		case T_void :
2442
//		case T_void :
Lines 2461-2471 Link Here
2461
	FieldBinding fieldBinding = accessBinding.targetWriteField;
2468
	FieldBinding fieldBinding = accessBinding.targetWriteField;
2462
	if (fieldBinding.isStatic()) {
2469
	if (fieldBinding.isStatic()) {
2463
		load(fieldBinding.type, 0);
2470
		load(fieldBinding.type, 0);
2464
		putstatic(fieldBinding);
2471
		fieldAccess(Opcodes.OPC_putstatic, fieldBinding, null /* default declaringClass */);
2465
	} else {
2472
	} else {
2466
		aload_0();
2473
		aload_0();
2467
		load(fieldBinding.type, 1);
2474
		load(fieldBinding.type, 1);
2468
		putfield(fieldBinding);
2475
		fieldAccess(Opcodes.OPC_putfield, fieldBinding, null /* default declaringClass */);
2469
	}
2476
	}
2470
	return_();
2477
	return_();
2471
}
2478
}
Lines 2551-2557 Link Here
2551
	initializeMaxLocals(methodBinding);
2558
	initializeMaxLocals(methodBinding);
2552
	final BranchLabel nullLabel = new BranchLabel(this);
2559
	final BranchLabel nullLabel = new BranchLabel(this);
2553
	FieldBinding syntheticFieldBinding = methodBinding.targetReadField;
2560
	FieldBinding syntheticFieldBinding = methodBinding.targetReadField;
2554
	getstatic(syntheticFieldBinding);
2561
	fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
2555
	dup();
2562
	dup();
2556
	ifnull(nullLabel);
2563
	ifnull(nullLabel);
2557
	areturn();
2564
	areturn();
Lines 2575-2581 Link Here
2575
				final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/);
2582
				final ExceptionLabel anyExceptionHandler = new ExceptionLabel(this, TypeBinding.LONG /* represents NoSuchFieldError*/);
2576
				anyExceptionHandler.placeStart();
2583
				anyExceptionHandler.placeStart();
2577
				aload_0();
2584
				aload_0();
2578
				getstatic(fieldBinding);
2585
				fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null /* default declaringClass */);
2579
				invokeEnumOrdinal(enumBinding.constantPoolName());
2586
				invokeEnumOrdinal(enumBinding.constantPoolName());
2580
				this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810
2587
				this.generateInlinedValue(fieldBinding.id + 1); // zero should not be returned see bug 141810
2581
				iastore();
2588
				iastore();
Lines 2591-2597 Link Here
2591
	}
2598
	}
2592
	aload_0();
2599
	aload_0();
2593
	dup();
2600
	dup();
2594
	putstatic(syntheticFieldBinding);
2601
	fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
2595
	areturn();
2602
	areturn();
2596
	removeVariable(localVariableBinding);
2603
	removeVariable(localVariableBinding);
2597
}
2604
}
Lines 2868-2983 Link Here
2868
	return contents;
2875
	return contents;
2869
}
2876
}
2870
2877
2871
public void getfield(FieldBinding fieldBinding) {
2878
/**
2872
	int returnTypeSize = 1;
2879
 * Returns the type that should be substituted to original binding declaring class as the proper receiver type
2873
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
2880
 * @param currentScope
2874
		returnTypeSize = 2;
2881
 * @param codegenBinding
2875
	}
2882
 * @param actualReceiverType
2876
	generateFieldAccess(
2883
 * @param isImplicitThisReceiver
2877
			Opcodes.OPC_getfield,
2884
 * @return the receiver type to use in constant pool
2878
			returnTypeSize,
2885
 */
2879
			fieldBinding.declaringClass,
2886
public static TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope, FieldBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver) {
2880
			fieldBinding.name,
2887
	ReferenceBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
2881
			fieldBinding.type);
2888
	// if the binding declaring class is not visible, need special action
2889
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
2890
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
2891
	// and not from Object or implicit static field access.
2892
	if (constantPoolDeclaringClass != actualReceiverType.erasure()
2893
			&& !actualReceiverType.isArrayType()
2894
			&& constantPoolDeclaringClass != null // array.length
2895
			&& codegenBinding.constant() == Constant.NotAConstant) {
2896
		CompilerOptions options = currentScope.compilerOptions();
2897
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
2898
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic()))
2899
					&& constantPoolDeclaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields
2900
				|| !constantPoolDeclaringClass.canBeSeenBy(currentScope)) {
2901
2902
			return actualReceiverType.erasure();
2903
		}
2904
	}	
2905
	return constantPoolDeclaringClass;
2882
}
2906
}
2883
2907
2908
/**
2909
 * Returns the type that should be substituted to original binding declaring class as the proper receiver type
2910
 * @param currentScope
2911
 * @param codegenBinding
2912
 * @param actualReceiverType
2913
 * @param isImplicitThisReceiver
2914
 * @param hasGenericCast
2915
 * @return the receiver type to use in constant pool
2916
 */
2917
public static TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope, MethodBinding codegenBinding, TypeBinding actualReceiverType, boolean isImplicitThisReceiver, boolean hasGenericCast) {
2918
	TypeBinding constantPoolDeclaringClass = codegenBinding.declaringClass;
2919
	// Post 1.4.0 target, array clone() invocations are qualified with array type
2920
	// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
2921
	if (codegenBinding == currentScope.environment().arrayClone) {
2922
		CompilerOptions options = currentScope.compilerOptions();
2923
		if (options.sourceLevel > ClassFileConstants.JDK1_4 ) {
2924
			constantPoolDeclaringClass = actualReceiverType.erasure();
2925
		}
2926
	} else {
2927
		// if the binding declaring class is not visible, need special action
2928
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
2929
		// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
2930
		// and not from Object or implicit static method call.
2931
		if (constantPoolDeclaringClass != actualReceiverType.erasure() && !hasGenericCast && !actualReceiverType.isArrayType()) {
2932
			CompilerOptions options = currentScope.compilerOptions();
2933
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
2934
						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(isImplicitThisReceiver && codegenBinding.isStatic()))
2935
						&& codegenBinding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
2936
					|| !codegenBinding.declaringClass.canBeSeenBy(currentScope)) {
2937
				constantPoolDeclaringClass = actualReceiverType.erasure();
2938
			}
2939
		}				
2940
	}
2941
	return constantPoolDeclaringClass;
2942
}
2884
protected int getPosition() {
2943
protected int getPosition() {
2885
	return this.position;
2944
	return this.position;
2886
}
2945
}
2887
2946
2888
public void getstatic(FieldBinding fieldBinding) {
2889
	int returnTypeSize = 1;
2890
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
2891
		returnTypeSize = 2;
2892
	}
2893
	generateFieldAccess(
2894
			Opcodes.OPC_getstatic,
2895
			returnTypeSize,
2896
			fieldBinding.declaringClass,
2897
			fieldBinding.name,
2898
			fieldBinding.type);
2899
}
2900
2901
public void getTYPE(int baseTypeID) {
2947
public void getTYPE(int baseTypeID) {
2902
	this.countLabels = 0;
2948
	this.countLabels = 0;
2903
	switch (baseTypeID) {
2949
	switch (baseTypeID) {
2904
		case TypeIds.T_byte :
2950
		case TypeIds.T_byte :
2905
			// getstatic: java.lang.Byte.TYPE
2951
			// getstatic: java.lang.Byte.TYPE
2906
			generateFieldAccess(
2952
			fieldAccess(
2907
					Opcodes.OPC_getstatic,
2953
					Opcodes.OPC_getstatic,
2908
					1,
2954
					1, // return type size
2909
					ConstantPool.JavaLangByteConstantPoolName,
2955
					ConstantPool.JavaLangByteConstantPoolName,
2910
					ConstantPool.TYPE,
2956
					ConstantPool.TYPE,
2911
					ConstantPool.JavaLangClassSignature);
2957
					ConstantPool.JavaLangClassSignature);
2912
			break;
2958
			break;
2913
		case TypeIds.T_short :
2959
		case TypeIds.T_short :
2914
			// getstatic: java.lang.Short.TYPE
2960
			// getstatic: java.lang.Short.TYPE
2915
			generateFieldAccess(
2961
			fieldAccess(
2916
					Opcodes.OPC_getstatic,
2962
					Opcodes.OPC_getstatic,
2917
					1,
2963
					1, // return type size
2918
					ConstantPool.JavaLangShortConstantPoolName,
2964
					ConstantPool.JavaLangShortConstantPoolName,
2919
					ConstantPool.TYPE,
2965
					ConstantPool.TYPE,
2920
					ConstantPool.JavaLangClassSignature);
2966
					ConstantPool.JavaLangClassSignature);
2921
			break;
2967
			break;
2922
		case TypeIds.T_char :
2968
		case TypeIds.T_char :
2923
			// getstatic: java.lang.Character.TYPE
2969
			// getstatic: java.lang.Character.TYPE
2924
			generateFieldAccess(
2970
			fieldAccess(
2925
					Opcodes.OPC_getstatic,
2971
					Opcodes.OPC_getstatic,
2926
					1,
2972
					1, // return type size
2927
					ConstantPool.JavaLangCharacterConstantPoolName,
2973
					ConstantPool.JavaLangCharacterConstantPoolName,
2928
					ConstantPool.TYPE,
2974
					ConstantPool.TYPE,
2929
					ConstantPool.JavaLangClassSignature);
2975
					ConstantPool.JavaLangClassSignature);
2930
			break;
2976
			break;
2931
		case TypeIds.T_int :
2977
		case TypeIds.T_int :
2932
			// getstatic: java.lang.Integer.TYPE
2978
			// getstatic: java.lang.Integer.TYPE
2933
			generateFieldAccess(
2979
			fieldAccess(
2934
					Opcodes.OPC_getstatic,
2980
					Opcodes.OPC_getstatic,
2935
					1,
2981
					1, // return type size
2936
					ConstantPool.JavaLangIntegerConstantPoolName,
2982
					ConstantPool.JavaLangIntegerConstantPoolName,
2937
					ConstantPool.TYPE,
2983
					ConstantPool.TYPE,
2938
					ConstantPool.JavaLangClassSignature);
2984
					ConstantPool.JavaLangClassSignature);
2939
			break;
2985
			break;
2940
		case TypeIds.T_long :
2986
		case TypeIds.T_long :
2941
			// getstatic: java.lang.Long.TYPE
2987
			// getstatic: java.lang.Long.TYPE
2942
			generateFieldAccess(
2988
			fieldAccess(
2943
					Opcodes.OPC_getstatic,
2989
					Opcodes.OPC_getstatic,
2944
					1,
2990
					1, // return type size
2945
					ConstantPool.JavaLangLongConstantPoolName,
2991
					ConstantPool.JavaLangLongConstantPoolName,
2946
					ConstantPool.TYPE,
2992
					ConstantPool.TYPE,
2947
					ConstantPool.JavaLangClassSignature);
2993
					ConstantPool.JavaLangClassSignature);
2948
			break;
2994
			break;
2949
		case TypeIds.T_float :
2995
		case TypeIds.T_float :
2950
			// getstatic: java.lang.Float.TYPE
2996
			// getstatic: java.lang.Float.TYPE
2951
			generateFieldAccess(
2997
			fieldAccess(
2952
					Opcodes.OPC_getstatic,
2998
					Opcodes.OPC_getstatic,
2953
					1,
2999
					1, // return type size
2954
					ConstantPool.JavaLangFloatConstantPoolName,
3000
					ConstantPool.JavaLangFloatConstantPoolName,
2955
					ConstantPool.TYPE,
3001
					ConstantPool.TYPE,
2956
					ConstantPool.JavaLangClassSignature);
3002
					ConstantPool.JavaLangClassSignature);
2957
			break;
3003
			break;
2958
		case TypeIds.T_double :
3004
		case TypeIds.T_double :
2959
			// getstatic: java.lang.Double.TYPE
3005
			// getstatic: java.lang.Double.TYPE
2960
			generateFieldAccess(
3006
			fieldAccess(
2961
					Opcodes.OPC_getstatic,
3007
					Opcodes.OPC_getstatic,
2962
					1,
3008
					1, // return type size
2963
					ConstantPool.JavaLangDoubleConstantPoolName,
3009
					ConstantPool.JavaLangDoubleConstantPoolName,
2964
					ConstantPool.TYPE,
3010
					ConstantPool.TYPE,
2965
					ConstantPool.JavaLangClassSignature);
3011
					ConstantPool.JavaLangClassSignature);
2966
			break;
3012
			break;
2967
		case TypeIds.T_boolean :
3013
		case TypeIds.T_boolean :
2968
			// getstatic: java.lang.Boolean.TYPE
3014
			// getstatic: java.lang.Boolean.TYPE
2969
			generateFieldAccess(
3015
			fieldAccess(
2970
					Opcodes.OPC_getstatic,
3016
					Opcodes.OPC_getstatic,
2971
					1,
3017
					1, // return type size
2972
					ConstantPool.JavaLangBooleanConstantPoolName,
3018
					ConstantPool.JavaLangBooleanConstantPoolName,
2973
					ConstantPool.TYPE,
3019
					ConstantPool.TYPE,
2974
					ConstantPool.JavaLangClassSignature);
3020
					ConstantPool.JavaLangClassSignature);
2975
			break;
3021
			break;
2976
		case TypeIds.T_void :
3022
		case TypeIds.T_void :
2977
			// getstatic: java.lang.Void.TYPE
3023
			// getstatic: java.lang.Void.TYPE
2978
			generateFieldAccess(
3024
			fieldAccess(
2979
					Opcodes.OPC_getstatic,
3025
					Opcodes.OPC_getstatic,
2980
					1,
3026
					1, // return type size
2981
					ConstantPool.JavaLangVoidConstantPoolName,
3027
					ConstantPool.JavaLangVoidConstantPoolName,
2982
					ConstantPool.TYPE,
3028
					ConstantPool.TYPE,
2983
					ConstantPool.JavaLangClassSignature);
3029
					ConstantPool.JavaLangClassSignature);
Lines 3726-3731 Link Here
3726
	writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding));
3772
	writeUnsignedShort(this.constantPool.literalIndexForType(typeBinding));
3727
}
3773
}
3728
3774
3775
protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
3776
	this.countLabels = 0;
3777
	if (opcode == Opcodes.OPC_invokeinterface) {
3778
		// invokeinterface
3779
		if (this.classFileOffset + 4 >= this.bCodeStream.length) {
3780
			resizeByteArray();
3781
		}
3782
		this.position +=3;
3783
		this.bCodeStream[this.classFileOffset++] = opcode;
3784
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
3785
		this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize;
3786
		this.bCodeStream[this.classFileOffset++] = 0;
3787
	} else {
3788
		// invokespecial
3789
		// invokestatic
3790
		// invokevirtual
3791
		if (this.classFileOffset + 2 >= this.bCodeStream.length) {
3792
			resizeByteArray();
3793
		}
3794
		this.position++;
3795
		this.bCodeStream[this.classFileOffset++] = opcode;
3796
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
3797
	}
3798
	this.stackDepth += returnTypeSize - receiverAndArgsSize;
3799
	if (this.stackDepth > this.stackMax) {
3800
		this.stackMax = this.stackDepth;
3801
	}
3802
}
3803
3729
public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) {
3804
public void invoke(byte opcode, MethodBinding methodBinding, TypeBinding declaringClass) {
3730
	if (declaringClass == null) declaringClass = methodBinding.declaringClass;
3805
	if (declaringClass == null) declaringClass = methodBinding.declaringClass;
3731
    if (declaringClass.isNestedType()) {
3806
    if (declaringClass.isNestedType()) {
Lines 3808-3842 Link Here
3808
			methodBinding.signature(this.classFile));
3883
			methodBinding.signature(this.classFile));
3809
}
3884
}
3810
3885
3811
protected void invoke(byte opcode, int receiverAndArgsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) {
3812
	this.countLabels = 0;
3813
	if (opcode == Opcodes.OPC_invokeinterface) {
3814
		// invokeinterface
3815
		if (this.classFileOffset + 4 >= this.bCodeStream.length) {
3816
			resizeByteArray();
3817
		}
3818
		this.position +=3;
3819
		this.bCodeStream[this.classFileOffset++] = opcode;
3820
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, true));
3821
		this.bCodeStream[this.classFileOffset++] = (byte) receiverAndArgsSize;
3822
		this.bCodeStream[this.classFileOffset++] = 0;
3823
	} else {
3824
		// invokespecial
3825
		// invokestatic
3826
		// invokevirtual
3827
		if (this.classFileOffset + 2 >= this.bCodeStream.length) {
3828
			resizeByteArray();
3829
		}
3830
		this.position++;
3831
		this.bCodeStream[this.classFileOffset++] = opcode;
3832
		writeUnsignedShort(this.constantPool.literalIndexForMethod(declaringClass, selector, signature, false));
3833
	}
3834
	this.stackDepth += returnTypeSize - receiverAndArgsSize;
3835
	if (this.stackDepth > this.stackMax) {
3836
		this.stackMax = this.stackDepth;
3837
	}
3838
}
3839
3840
protected void invokeAccessibleObjectSetAccessible() {
3886
protected void invokeAccessibleObjectSetAccessible() {
3841
	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
3887
	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
3842
	invoke(
3888
	invoke(
Lines 5115-5121 Link Here
5115
	load(localBinding.type, localBinding.resolvedPosition);
5161
	load(localBinding.type, localBinding.resolvedPosition);
5116
}
5162
}
5117
5163
5118
public final void load(TypeBinding typeBinding, int resolvedPosition) {
5164
protected final void load(TypeBinding typeBinding, int resolvedPosition) {
5119
	this.countLabels = 0;
5165
	this.countLabels = 0;
5120
	// Using dedicated int bytecode
5166
	// Using dedicated int bytecode
5121
	switch(typeBinding.id) {
5167
	switch(typeBinding.id) {
Lines 5658-5689 Link Here
5658
		this.stackMax = this.stackDepth;
5704
		this.stackMax = this.stackDepth;
5659
}
5705
}
5660
5706
5661
public void putfield(FieldBinding fieldBinding) {
5662
	int returnTypeSize = 1;
5663
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
5664
		returnTypeSize = 2;
5665
	}
5666
	generateFieldAccess(
5667
			Opcodes.OPC_putfield,
5668
			returnTypeSize,
5669
			fieldBinding.declaringClass,
5670
			fieldBinding.name,
5671
			fieldBinding.type);
5672
}
5673
5674
public void putstatic(FieldBinding fieldBinding) {
5675
	int returnTypeSize = 1;
5676
	if ((fieldBinding.type.id == TypeIds.T_double) || (fieldBinding.type.id == TypeIds.T_long)) {
5677
		returnTypeSize = 2;
5678
	}
5679
	generateFieldAccess(
5680
			Opcodes.OPC_putstatic,
5681
			returnTypeSize,
5682
			fieldBinding.declaringClass,
5683
			fieldBinding.name,
5684
			fieldBinding.type);
5685
}
5686
5687
public void record(LocalVariableBinding local) {
5707
public void record(LocalVariableBinding local) {
5688
	if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS
5708
	if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS
5689
			| ClassFileConstants.ATTR_STACK_MAP_TABLE
5709
			| ClassFileConstants.ATTR_STACK_MAP_TABLE
(-)compiler/org/eclipse/jdt/internal/compiler/codegen/StackMapFrameCodeStream.java (-2 / +2 lines)
Lines 273-279 Link Here
273
		// use in CLDC mode
273
		// use in CLDC mode
274
		BranchLabel endLabel = new BranchLabel(this);
274
		BranchLabel endLabel = new BranchLabel(this);
275
		if (syntheticFieldBinding != null) { // non interface case
275
		if (syntheticFieldBinding != null) { // non interface case
276
			getstatic(syntheticFieldBinding);
276
			fieldAccess(Opcodes.OPC_getstatic, syntheticFieldBinding, null /* default declaringClass */);
277
			dup();
277
			dup();
278
			ifnonnull(endLabel);
278
			ifnonnull(endLabel);
279
			pop();
279
			pop();
Lines 316-322 Link Here
316
316
317
		if (syntheticFieldBinding != null) { // non interface case
317
		if (syntheticFieldBinding != null) { // non interface case
318
			dup();
318
			dup();
319
			putstatic(syntheticFieldBinding);
319
			fieldAccess(Opcodes.OPC_putstatic, syntheticFieldBinding, null /* default declaringClass */);
320
		}
320
		}
321
		int fromPC = this.position;
321
		int fromPC = this.position;
322
		goto_(endLabel);
322
		goto_(endLabel);
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java (-112 / +88 lines)
Lines 15-33 Link Here
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
16
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
20
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
21
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
22
import org.eclipse.jdt.internal.compiler.impl.Constant;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
23
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
24
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
25
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
28
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
31
28
32
public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants {
29
public class CodeSnippetFieldReference extends FieldReference implements ProblemReasons, EvaluationConstants {
33
30
Lines 43-68 Link Here
43
	this.evaluationContext = evaluationContext;
40
	this.evaluationContext = evaluationContext;
44
}
41
}
45
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
42
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
46
43
	FieldBinding codegenBinding = this.binding.original();
47
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
44
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
48
		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
45
		this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
49
		assignment.expression.generateCode(currentScope, codeStream, true);
46
		assignment.expression.generateCode(currentScope, codeStream, true);
50
		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
47
		fieldStore(codeStream, codegenBinding, null, valueRequired);
51
	} else {
48
	} else {
52
		codeStream.generateEmulationForField(this.codegenBinding);
49
		codeStream.generateEmulationForField(codegenBinding);
53
		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
50
		this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
54
		if (this.codegenBinding.isStatic()) { // need a receiver?
51
		if (codegenBinding.isStatic()) { // need a receiver?
55
			codeStream.aconst_null();
52
			codeStream.aconst_null();
56
		}
53
		}
57
		assignment.expression.generateCode(currentScope, codeStream, true);
54
		assignment.expression.generateCode(currentScope, codeStream, true);
58
		if (valueRequired) {
55
		if (valueRequired) {
59
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
56
			switch (codegenBinding.type.id) {
60
				codeStream.dup2_x2();
57
				case TypeIds.T_long :
61
			} else {
58
				case TypeIds.T_double :
62
				codeStream.dup_x2();
59
					codeStream.dup2_x2();
63
			}
60
					break;
61
				default :
62
					codeStream.dup_x2();
63
					break;
64
			}			
64
		}
65
		}
65
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
66
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
66
	}
67
	}
67
	if (valueRequired){
68
	if (valueRequired){
68
		codeStream.generateImplicitConversion(assignment.implicitConversion);
69
		codeStream.generateImplicitConversion(assignment.implicitConversion);
Lines 76-108 Link Here
76
 * @param valueRequired boolean
77
 * @param valueRequired boolean
77
 */
78
 */
78
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
79
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
79
80
	int pc = codeStream.position;
80
	int pc = codeStream.position;
81
	if (this.constant != Constant.NotAConstant) {
81
	if (this.constant != Constant.NotAConstant) {
82
		if (valueRequired) {
82
		if (valueRequired) {
83
			codeStream.generateConstant(this.constant, this.implicitConversion);
83
			codeStream.generateConstant(this.constant, this.implicitConversion);
84
		}
84
		}
85
	} else {
85
	} else {
86
		boolean isStatic = this.codegenBinding.isStatic();
86
		FieldBinding codegenBinding = this.binding.original();
87
		boolean isStatic = codegenBinding.isStatic();
87
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
88
		this.receiver.generateCode(currentScope, codeStream, !isStatic);
88
		if (valueRequired) {
89
		if (valueRequired) {
89
			Constant fieldConstant = this.codegenBinding.constant();
90
			Constant fieldConstant = codegenBinding.constant();
90
			if (fieldConstant == Constant.NotAConstant) {
91
			if (fieldConstant == Constant.NotAConstant) {
91
				if (this.codegenBinding.declaringClass == null) { // array length
92
				if (codegenBinding.declaringClass == null) { // array length
92
					codeStream.arraylength();
93
					codeStream.arraylength();
93
				} else {
94
				} else {
94
					if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
95
					if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
96
						TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
97
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, someReceiverType, this.receiver.isImplicitThis());
95
						if (isStatic) {
98
						if (isStatic) {
96
							codeStream.getstatic(this.codegenBinding);
99
							codeStream.fieldAccess(Opcodes.OPC_getstatic , codegenBinding, constantPoolDeclaringClass);
97
						} else {
100
						} else {
98
							codeStream.getfield(this.codegenBinding);
101
							codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
99
						}
102
						}
100
					} else {
103
					} else {
101
						if (isStatic) {
104
						if (isStatic) {
102
							// we need a null on the stack to use the reflect emulation
105
							// we need a null on the stack to use the reflect emulation
103
							codeStream.aconst_null();
106
							codeStream.aconst_null();
104
						}
107
						}
105
						codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
108
						codeStream.generateEmulatedReadAccessForField(codegenBinding);
106
					}
109
					}
107
				}
110
				}
108
				codeStream.generateImplicitConversion(this.implicitConversion);
111
				codeStream.generateImplicitConversion(this.implicitConversion);
Lines 124-138 Link Here
124
}
127
}
125
128
126
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
129
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
127
128
	boolean isStatic;
130
	boolean isStatic;
129
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
131
	FieldBinding codegenBinding = this.binding.original();
130
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
132
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
133
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
134
		TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
135
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, someReceiverType, this.receiver.isImplicitThis());
131
		if (isStatic) {
136
		if (isStatic) {
132
			codeStream.getstatic(this.codegenBinding);
137
			codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
133
		} else {
138
		} else {
134
			codeStream.dup();
139
			codeStream.dup();
135
			codeStream.getfield(this.codegenBinding);
140
			codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
136
		}
141
		}
137
		int operationTypeID;
142
		int operationTypeID;
138
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
143
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
Lines 155-171 Link Here
155
				// cast the value back to the array reference type
160
				// cast the value back to the array reference type
156
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
161
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
157
		}
162
		}
158
		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
163
		fieldStore(codeStream, codegenBinding, null, valueRequired);
159
	} else {
164
	} else {
160
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
165
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
161
		if (isStatic) {
166
		if (isStatic) {
162
			// used to store the value
167
			// used to store the value
163
			codeStream.generateEmulationForField(this.codegenBinding);
168
			codeStream.generateEmulationForField(codegenBinding);
164
			codeStream.aconst_null();
169
			codeStream.aconst_null();
165
170
166
			// used to retrieve the actual value
171
			// used to retrieve the actual value
167
			codeStream.aconst_null();
172
			codeStream.aconst_null();
168
			codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
173
			codeStream.generateEmulatedReadAccessForField(codegenBinding);
169
		} else {
174
		} else {
170
			// used to store the value
175
			// used to store the value
171
			codeStream.generateEmulationForField(this.binding);
176
			codeStream.generateEmulationForField(this.binding);
Lines 173-179 Link Here
173
178
174
			// used to retrieve the actual value
179
			// used to retrieve the actual value
175
			codeStream.dup();
180
			codeStream.dup();
176
			codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
181
			codeStream.generateEmulatedReadAccessForField(codegenBinding);
177
		}
182
		}
178
		int operationTypeID;
183
		int operationTypeID;
179
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
184
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
Lines 195-201 Link Here
195
		// current stack is:
200
		// current stack is:
196
		// field receiver value
201
		// field receiver value
197
		if (valueRequired) {
202
		if (valueRequired) {
198
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
203
			if ((codegenBinding.type == TypeBinding.LONG) || (codegenBinding.type == TypeBinding.DOUBLE)) {
199
				codeStream.dup2_x2();
204
				codeStream.dup2_x2();
200
			} else {
205
			} else {
201
				codeStream.dup_x2();
206
				codeStream.dup_x2();
Lines 203-263 Link Here
203
		}
208
		}
204
		// current stack is:
209
		// current stack is:
205
		// value field receiver value
210
		// value field receiver value
206
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
211
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
207
	}
212
	}
208
}
213
}
209
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
214
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
210
	boolean isStatic;
215
	boolean isStatic;
211
	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
216
	FieldBinding codegenBinding = this.binding.original();
217
	if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
212
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
218
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
213
	} else {
219
	} else {
214
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
220
		this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
215
		if (isStatic) {
221
		if (isStatic) {
216
			codeStream.aconst_null();
222
			codeStream.aconst_null();
217
		}
223
		}
218
		// the actual stack is: receiver
224
		// the actual stack is: receiver
219
		codeStream.dup();
225
		codeStream.dup();
220
		// the actual stack is: receiver receiver
226
		// the actual stack is: receiver receiver
221
		codeStream.generateEmulatedReadAccessForField(this.codegenBinding);
227
		codeStream.generateEmulatedReadAccessForField(codegenBinding);
222
		// the actual stack is: receiver value
228
		// the actual stack is: receiver value
223
		// receiver value
229
		// receiver value
224
		// value receiver value 							dup_x1 or dup2_x1 if value required
230
		// value receiver value 							dup_x1 or dup2_x1 if value required
225
		// value value receiver value						dup_x1 or dup2_x1
231
		// value value receiver value					dup_x1 or dup2_x1
226
		// value value receiver								pop or pop2
232
		// value value receiver							pop or pop2
227
		// value value receiver field						generateEmulationForField
233
		// value value receiver field						generateEmulationForField
228
		// value value field receiver 						swap
234
		// value value field receiver 					swap
229
		// value field receiver value field receiver 		dup2_x1 or dup2_x2
235
		// value field receiver value field receiver 	dup2_x1 or dup2_x2
230
		// value field receiver value 				 		pop2
236
		// value field receiver value 				 	pop2
231
		// value field receiver newvalue 				 	generate constant + op
237
		// value field receiver newvalue 				generate constant + op
232
		// value 											store
238
		// value 												store
233
		if (valueRequired) {
239
		int typeID;
234
			if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
240
		switch (typeID = codegenBinding.type.id) {
241
			case TypeIds.T_long :
242
			case TypeIds.T_double :
243
				if (valueRequired) {
244
					codeStream.dup2_x1();
245
				}
235
				codeStream.dup2_x1();
246
				codeStream.dup2_x1();
236
			} else {
247
				codeStream.pop2();
248
				break;
249
			default :
250
				if (valueRequired) {
251
					codeStream.dup_x1();
252
				}
237
				codeStream.dup_x1();
253
				codeStream.dup_x1();
238
			}
254
				codeStream.pop();
239
		}
255
				break;
240
		if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
241
			codeStream.dup2_x1();
242
			codeStream.pop2();
243
		} else {
244
			codeStream.dup_x1();
245
			codeStream.pop();
246
		}
256
		}
247
		codeStream.generateEmulationForField(this.codegenBinding);
257
		codeStream.generateEmulationForField(codegenBinding);
248
		codeStream.swap();
258
		codeStream.swap();
249
259
		switch (typeID) {
250
		if ((this.codegenBinding.type == TypeBinding.LONG) || (this.codegenBinding.type == TypeBinding.DOUBLE)) {
260
			case TypeIds.T_long :
251
			codeStream.dup2_x2();
261
			case TypeIds.T_double :
252
		} else {
262
				codeStream.dup2_x2();
253
			codeStream.dup2_x1();
263
				break;
264
			default :
265
				codeStream.dup2_x1();
266
				break;
254
		}
267
		}
255
		codeStream.pop2();
268
		codeStream.pop2();
256
269
257
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
270
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
258
		codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
271
		codeStream.sendOperator(postIncrement.operator, codegenBinding.type.id);
259
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
272
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
260
		codeStream.generateEmulatedWriteAccessForField(this.codegenBinding);
273
		codeStream.generateEmulatedWriteAccessForField(codegenBinding);
261
	}
274
	}
262
}
275
}
263
/*
276
/*
Lines 267-309 Link Here
267
	// The private access will be managed through the code generation
280
	// The private access will be managed through the code generation
268
281
269
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
282
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
270
271
	// if field from parameterized type got found, use the original field at codegen time
272
	if (this.binding instanceof ParameterizedFieldBinding) {
273
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
274
	    this.codegenBinding = parameterizedField.originalField;
275
	    // extra cast needed if field type was type variable
276
	    if (this.codegenBinding.type.isTypeVariable()) {
277
	        TypeVariableBinding variableReturnType = (TypeVariableBinding) this.codegenBinding.type;
278
	        if (variableReturnType.firstBound != parameterizedField.type) { // no need for extra cast if same as first bound anyway
279
			    this.genericCast = parameterizedField.type.erasure();
280
	        }
281
	    }
282
	} else {
283
	    this.codegenBinding = this.binding;
284
	}
285
286
	// if the binding declaring class is not visible, need special action
287
	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
288
	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
289
	TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.receiverType;
290
	if (this.binding.declaringClass != someReceiverType
291
			&& !someReceiverType.isArrayType()
292
			&& this.binding.declaringClass != null // array.length
293
			&& this.binding.constant() == Constant.NotAConstant) {
294
295
		CompilerOptions options = currentScope.compilerOptions();
296
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
297
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !this.receiver.isImplicitThis() || !this.codegenBinding.isStatic())
298
				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields
299
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
300
301
			this.codegenBinding =
302
				currentScope.enclosingSourceType().getUpdatedFieldBinding(
303
					this.codegenBinding,
304
					(ReferenceBinding) someReceiverType.erasure());
305
		}
306
	}
307
}
283
}
308
public TypeBinding resolveType(BlockScope scope) {
284
public TypeBinding resolveType(BlockScope scope) {
309
	// Answer the signature type of the field.
285
	// Answer the signature type of the field.
Lines 311-323 Link Here
311
	// and initialized with a (compile time) constant
287
	// and initialized with a (compile time) constant
312
288
313
	// regular receiver reference
289
	// regular receiver reference
314
	this.receiverType = this.receiver.resolveType(scope);
290
	this.actualReceiverType = this.receiver.resolveType(scope);
315
	if (this.receiverType == null){
291
	if (this.actualReceiverType == null){
316
		this.constant = Constant.NotAConstant;
292
		this.constant = Constant.NotAConstant;
317
		return null;
293
		return null;
318
	}
294
	}
319
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
295
	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
320
	this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this);
296
	this.binding = scope.getField(this.actualReceiverType, this.token, this);
321
	FieldBinding firstAttempt = this.binding;
297
	FieldBinding firstAttempt = this.binding;
322
	boolean isNotVisible = false;
298
	boolean isNotVisible = false;
323
	if (!this.binding.isValidBinding()) {
299
	if (!this.binding.isValidBinding()) {
Lines 328-352 Link Here
328
					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
304
					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
329
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
305
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
330
						this.constant = Constant.NotAConstant;
306
						this.constant = Constant.NotAConstant;
331
						scope.problemReporter().invalidField(this, this.receiverType);
307
						scope.problemReporter().invalidField(this, this.actualReceiverType);
332
						return null;
308
						return null;
333
					}
309
					}
334
				} else {
310
				} else {
335
					this.constant = Constant.NotAConstant;
311
					this.constant = Constant.NotAConstant;
336
					scope.problemReporter().invalidField(this, this.receiverType);
312
					scope.problemReporter().invalidField(this, this.actualReceiverType);
337
					return null;
313
					return null;
338
				}
314
				}
339
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
315
			CodeSnippetScope localScope = new CodeSnippetScope(scope);
340
			this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
316
			this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
341
		}
317
		}
342
	}
318
	}
343
319
344
	if (!this.binding.isValidBinding()) {
320
	if (!this.binding.isValidBinding()) {
345
		this.constant = Constant.NotAConstant;
321
		this.constant = Constant.NotAConstant;
346
		if (isNotVisible) {
322
		if (isNotVisible) {
347
			this.codegenBinding = this.binding = firstAttempt;
323
			this.binding = firstAttempt;
348
		}
324
		}
349
		scope.problemReporter().invalidField(this, this.receiverType);
325
		scope.problemReporter().invalidField(this, this.actualReceiverType);
350
		return null;
326
		return null;
351
	}
327
	}
352
328
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java (-113 / +120 lines)
Lines 16-28 Link Here
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
17
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
18
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
18
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
19
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
21
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
21
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
22
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
22
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
23
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
24
import org.eclipse.jdt.internal.compiler.impl.Constant;
23
import org.eclipse.jdt.internal.compiler.impl.Constant;
25
import org.eclipse.jdt.internal.compiler.lookup.*;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
27
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
34
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
35
import org.eclipse.jdt.internal.compiler.lookup.Scope;
36
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
38
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
39
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
26
40
27
/**
41
/**
28
 * A single name reference inside a code snippet can denote a field of a remote
42
 * A single name reference inside a code snippet can denote a field of a remote
Lines 108-118 Link Here
108
			return;
122
			return;
109
		}
123
		}
110
		if ((operation.right instanceof SingleNameReference)
124
		if ((operation.right instanceof SingleNameReference)
111
			&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
125
				&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
112
			&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
126
				&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
113
			&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
127
				&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
114
			&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
128
				&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
115
			&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
129
				&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // exclude string concatenation which would occur backwards
116
			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
130
			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
117
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
131
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
118
			if (valueRequired) {
132
			if (valueRequired) {
Lines 123-131 Link Here
123
	}
137
	}
124
	switch (this.bits & RestrictiveFlagMASK) {
138
	switch (this.bits & RestrictiveFlagMASK) {
125
		case Binding.FIELD : // assigning to a field
139
		case Binding.FIELD : // assigning to a field
126
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
140
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
127
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
141
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
128
				if (!fieldBinding.isStatic()) { // need a receiver?
142
				if (!codegenField.isStatic()) { // need a receiver?
129
					if ((this.bits & DepthMASK) != 0) {
143
					if ((this.bits & DepthMASK) != 0) {
130
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
144
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
131
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
145
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 135-147 Link Here
135
					}
149
					}
136
				}
150
				}
137
				assignment.expression.generateCode(currentScope, codeStream, true);
151
				assignment.expression.generateCode(currentScope, codeStream, true);
138
				fieldStore(codeStream, fieldBinding, null, valueRequired);
152
				fieldStore(codeStream, codegenField, null, valueRequired);
139
				if (valueRequired) {
153
				if (valueRequired) {
140
					codeStream.generateImplicitConversion(assignment.implicitConversion);
154
					codeStream.generateImplicitConversion(assignment.implicitConversion);
141
				}
155
				}
142
			} else {
156
			} else {
143
				codeStream.generateEmulationForField(fieldBinding);
157
				codeStream.generateEmulationForField(codegenField);
144
				if (!fieldBinding.isStatic()) { // need a receiver?
158
				if (!codegenField.isStatic()) { // need a receiver?
145
					if ((this.bits & DepthMASK) != 0) {
159
					if ((this.bits & DepthMASK) != 0) {
146
						// internal error, per construction we should have found it
160
						// internal error, per construction we should have found it
147
						// not yet supported
161
						// not yet supported
Lines 154-173 Link Here
154
				}
168
				}
155
				assignment.expression.generateCode(currentScope, codeStream, true);
169
				assignment.expression.generateCode(currentScope, codeStream, true);
156
				if (valueRequired) {
170
				if (valueRequired) {
157
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
171
					if ((codegenField.type == TypeBinding.LONG) || (codegenField.type == TypeBinding.DOUBLE)) {
158
						codeStream.dup2_x2();
172
						codeStream.dup2_x2();
159
					} else {
173
					} else {
160
						codeStream.dup_x2();
174
						codeStream.dup_x2();
161
					}
175
					}
162
				}
176
				}
163
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
177
				codeStream.generateEmulatedWriteAccessForField(codegenField);
164
				if (valueRequired) {
178
				if (valueRequired) {
165
					codeStream.generateImplicitConversion(assignment.implicitConversion);
179
					codeStream.generateImplicitConversion(assignment.implicitConversion);
166
				}
180
				}
167
			}
181
			}
168
			return;
182
			return;
169
		case Binding.LOCAL : // assigning to a local variable
183
		case Binding.LOCAL : // assigning to a local variable
170
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
184
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
171
			if (localBinding.resolvedPosition != -1) {
185
			if (localBinding.resolvedPosition != -1) {
172
				assignment.expression.generateCode(currentScope, codeStream, true);
186
				assignment.expression.generateCode(currentScope, codeStream, true);
173
			} else {
187
			} else {
Lines 214-226 Link Here
214
			case Binding.FIELD : // reading a field
228
			case Binding.FIELD : // reading a field
215
				if (!valueRequired)
229
				if (!valueRequired)
216
					break;
230
					break;
217
				FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
231
				FieldBinding codegenField = ((FieldBinding) this.binding).original();
218
				Constant fieldConstant = fieldBinding.constant();
232
				Constant fieldConstant = codegenField.constant();
219
				if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
233
				if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
220
					if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
234
					if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
221
						 // directly use inlined value for constant fields
235
						TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
222
						boolean isStatic;
236
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
223
						if (!(isStatic = fieldBinding.isStatic())) {
237
						if (codegenField.isStatic()) {
238
							codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
239
						} else {
224
							if ((this.bits & DepthMASK) != 0) {
240
							if ((this.bits & DepthMASK) != 0) {
225
								ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
241
								ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
226
								Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
242
								Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 228-243 Link Here
228
							} else {
244
							} else {
229
								generateReceiver(codeStream);
245
								generateReceiver(codeStream);
230
							}
246
							}
231
						}
247
							codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
232
						// managing private access
233
						if (isStatic) {
234
							codeStream.getstatic(fieldBinding);
235
						} else {
236
							codeStream.getfield(fieldBinding);
237
						}
248
						}
238
					} else {
249
					} else {
239
						// managing private access
250
						// managing private access
240
						if (!fieldBinding.isStatic()) {
251
						if (!codegenField.isStatic()) {
241
							if ((this.bits & DepthMASK) != 0) {
252
							if ((this.bits & DepthMASK) != 0) {
242
								// internal error, per construction we should have found it
253
								// internal error, per construction we should have found it
243
								// not yet supported
254
								// not yet supported
Lines 248-254 Link Here
248
						} else {
259
						} else {
249
							codeStream.aconst_null();
260
							codeStream.aconst_null();
250
						}
261
						}
251
						codeStream.generateEmulatedReadAccessForField(fieldBinding);
262
						codeStream.generateEmulatedReadAccessForField(codegenField);
252
					}
263
					}
253
					if (this.genericCast != null) codeStream.checkcast(this.genericCast);
264
					if (this.genericCast != null) codeStream.checkcast(this.genericCast);
254
					codeStream.generateImplicitConversion(this.implicitConversion);
265
					codeStream.generateImplicitConversion(this.implicitConversion);
Lines 257-263 Link Here
257
				}
268
				}
258
				break;
269
				break;
259
			case Binding.LOCAL : // reading a local
270
			case Binding.LOCAL : // reading a local
260
				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
271
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
261
				if (!valueRequired)
272
				if (!valueRequired)
262
					break;
273
					break;
263
				// outer local?
274
				// outer local?
Lines 282-302 Link Here
282
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
293
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
283
	switch (this.bits & RestrictiveFlagMASK) {
294
	switch (this.bits & RestrictiveFlagMASK) {
284
		case Binding.FIELD : // assigning to a field
295
		case Binding.FIELD : // assigning to a field
285
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
296
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
286
			if (fieldBinding.isStatic()) {
297
			if (codegenField.isStatic()) {
287
				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
298
				if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
288
					codeStream.getstatic(fieldBinding);
299
					TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
300
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
301
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
289
				} else {
302
				} else {
290
					// used to store the value
303
					// used to store the value
291
					codeStream.generateEmulationForField(fieldBinding);
304
					codeStream.generateEmulationForField(codegenField);
292
					codeStream.aconst_null();
305
					codeStream.aconst_null();
293
306
294
					// used to retrieve the actual value
307
					// used to retrieve the actual value
295
					codeStream.aconst_null();
308
					codeStream.aconst_null();
296
					codeStream.generateEmulatedReadAccessForField(fieldBinding);
309
					codeStream.generateEmulatedReadAccessForField(codegenField);
297
				}
310
				}
298
			} else {
311
			} else {
299
				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
312
				if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
300
					if ((this.bits & DepthMASK) != 0) {
313
					if ((this.bits & DepthMASK) != 0) {
301
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
314
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
302
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
315
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
Lines 305-311 Link Here
305
						generateReceiver(codeStream);
318
						generateReceiver(codeStream);
306
					}
319
					}
307
					codeStream.dup();
320
					codeStream.dup();
308
					codeStream.getfield(fieldBinding);
321
					TypeBinding someReceiverType = this.delegateThis != null ? this.delegateThis.type : this.actualReceiverType;
322
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, someReceiverType, true /* implicit this */);
323
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
309
				} else {
324
				} else {
310
					if ((this.bits & DepthMASK) != 0) {
325
					if ((this.bits & DepthMASK) != 0) {
311
						// internal error, per construction we should have found it
326
						// internal error, per construction we should have found it
Lines 313-329 Link Here
313
						currentScope.problemReporter().needImplementation(this);
328
						currentScope.problemReporter().needImplementation(this);
314
					}
329
					}
315
					// used to store the value
330
					// used to store the value
316
					codeStream.generateEmulationForField(fieldBinding);
331
					codeStream.generateEmulationForField(codegenField);
317
					generateReceiver(codeStream);
332
					generateReceiver(codeStream);
318
333
319
					// used to retrieve the actual value
334
					// used to retrieve the actual value
320
					codeStream.dup();
335
					codeStream.dup();
321
					codeStream.generateEmulatedReadAccessForField(fieldBinding);
336
					codeStream.generateEmulatedReadAccessForField(codegenField);
322
				}
337
				}
323
			}
338
			}
324
			break;
339
			break;
325
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
340
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
326
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
341
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
327
			// using incr bytecode if possible
342
			// using incr bytecode if possible
328
			switch (localBinding.type.id) {
343
			switch (localBinding.type.id) {
329
				case T_JavaLangString :
344
				case T_JavaLangString :
Lines 387-418 Link Here
387
	// store the result back into the variable
402
	// store the result back into the variable
388
	switch (this.bits & RestrictiveFlagMASK) {
403
	switch (this.bits & RestrictiveFlagMASK) {
389
		case Binding.FIELD : // assigning to a field
404
		case Binding.FIELD : // assigning to a field
390
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
405
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
391
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
406
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
392
				fieldStore(codeStream, fieldBinding, writeAccessor, valueRequired);
407
				fieldStore(codeStream, codegenField, writeAccessor, valueRequired);
393
			} else {
408
			} else {
394
				// current stack is:
409
				// current stack is:
395
				// field receiver value
410
				// field receiver value
396
				if (valueRequired) {
411
				if (valueRequired) {
397
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
412
					switch (codegenField.type.id) {
398
						codeStream.dup2_x2();
413
						case TypeIds.T_long :
399
					} else {
414
						case TypeIds.T_double :
400
						codeStream.dup_x2();
415
							codeStream.dup2_x2();
401
					}
416
							break;
417
						default:
418
							codeStream.dup_x2();
419
							break;
420
					}					
402
				}
421
				}
403
				// current stack is:
422
				// current stack is:
404
				// value field receiver value
423
				// value field receiver value
405
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
424
				codeStream.generateEmulatedWriteAccessForField(codegenField);
406
			}
425
			}
407
			return;
426
			return;
408
		case Binding.LOCAL : // assigning to a local variable
427
		case Binding.LOCAL : // assigning to a local variable
409
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
428
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
410
			if (valueRequired) {
429
			if (valueRequired) {
411
				if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) {
430
				switch (localBinding.type.id) {
412
					codeStream.dup2();
431
					case TypeIds.T_long :
413
				} else {
432
					case TypeIds.T_double :
414
					codeStream.dup();
433
						codeStream.dup2();
415
				}
434
						break;
435
					default:
436
						codeStream.dup();
437
						break;
438
				}				
416
			}
439
			}
417
			codeStream.store(localBinding, false);
440
			codeStream.store(localBinding, false);
418
	}
441
	}
Lines 420-430 Link Here
420
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
443
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
421
	switch (this.bits & RestrictiveFlagMASK) {
444
	switch (this.bits & RestrictiveFlagMASK) {
422
		case Binding.FIELD : // assigning to a field
445
		case Binding.FIELD : // assigning to a field
423
			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
446
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
424
			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
447
			if (codegenField.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
425
				super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
448
				super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
426
			} else {
449
			} else {
427
				if (fieldBinding.isStatic()) {
450
				if (codegenField.isStatic()) {
428
					codeStream.aconst_null();
451
					codeStream.aconst_null();
429
				} else {
452
				} else {
430
					if ((this.bits & DepthMASK) != 0) {
453
					if ((this.bits & DepthMASK) != 0) {
Lines 435-474 Link Here
435
						generateReceiver(codeStream);
458
						generateReceiver(codeStream);
436
					}
459
					}
437
				}
460
				}
438
				codeStream.generateEmulatedReadAccessForField(fieldBinding);
461
				codeStream.generateEmulatedReadAccessForField(codegenField);
439
				if (valueRequired) {
462
				if (valueRequired) {
440
					if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
463
					switch (codegenField.type.id) {
441
						codeStream.dup2();
464
						case TypeIds.T_long :
442
					} else {
465
						case TypeIds.T_double :
443
						codeStream.dup();
466
							codeStream.dup2();
467
							break;
468
						default:
469
							codeStream.dup();
470
							break;
444
					}
471
					}
445
				}
472
				}
446
				codeStream.generateEmulationForField(fieldBinding);
473
				codeStream.generateEmulationForField(codegenField);
447
				if ((fieldBinding.type == TypeBinding.LONG) || (fieldBinding.type == TypeBinding.DOUBLE)) {
474
				switch (codegenField.type.id) {
448
					codeStream.dup_x2();
475
					case TypeIds.T_long :
449
					codeStream.pop();
476
					case TypeIds.T_double :
450
					if (fieldBinding.isStatic()) {
477
						codeStream.dup_x2();
451
						codeStream.aconst_null();
478
						codeStream.pop();
452
					} else {
479
						if (codegenField.isStatic()) {
453
						generateReceiver(codeStream);
480
							codeStream.aconst_null();
454
					}
481
						} else {
455
					codeStream.dup_x2();
482
							generateReceiver(codeStream);
456
					codeStream.pop();
483
						}
457
				} else {
484
						codeStream.dup_x2();
458
					codeStream.dup_x1();
485
						codeStream.pop();
486
						break;
487
					default:
488
						codeStream.dup_x1();
459
					codeStream.pop();
489
					codeStream.pop();
460
					if (fieldBinding.isStatic()) {
490
					if (codegenField.isStatic()) {
461
						codeStream.aconst_null();
491
						codeStream.aconst_null();
462
					} else {
492
					} else {
463
						generateReceiver(codeStream);
493
						generateReceiver(codeStream);
464
					}
494
					}
465
					codeStream.dup_x1();
495
					codeStream.dup_x1();
466
					codeStream.pop();
496
					codeStream.pop();
497
						break;
467
				}
498
				}
468
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
499
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
469
				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
500
				codeStream.sendOperator(postIncrement.operator, codegenField.type.id);
470
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
501
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
471
				codeStream.generateEmulatedWriteAccessForField(fieldBinding);
502
				codeStream.generateEmulatedWriteAccessForField(codegenField);
472
			}
503
			}
473
			return;
504
			return;
474
		case Binding.LOCAL : // assigning to a local variable
505
		case Binding.LOCAL : // assigning to a local variable
Lines 478-484 Link Here
478
public void generateReceiver(CodeStream codeStream) {
509
public void generateReceiver(CodeStream codeStream) {
479
	codeStream.aload_0();
510
	codeStream.aload_0();
480
	if (this.delegateThis != null) {
511
	if (this.delegateThis != null) {
481
		codeStream.getfield(this.delegateThis); // delegated field access
512
		codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access
482
	}
513
	}
483
}
514
}
484
/**
515
/**
Lines 509-544 Link Here
509
	// if field from parameterized type got found, use the original field at codegen time
540
	// if field from parameterized type got found, use the original field at codegen time
510
	if (this.binding instanceof ParameterizedFieldBinding) {
541
	if (this.binding instanceof ParameterizedFieldBinding) {
511
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
542
	    ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding;
512
	    this.codegenBinding = parameterizedField.originalField;
543
	    FieldBinding codegenField = parameterizedField.originalField;
513
	    FieldBinding fieldCodegenBinding = (FieldBinding)this.codegenBinding;
514
	    // extra cast needed if field type was type variable
544
	    // extra cast needed if field type was type variable
515
	    if ((fieldCodegenBinding.type.tagBits & TagBits.HasTypeVariable) != 0) {
545
	    if ((codegenField.type.tagBits & TagBits.HasTypeVariable) != 0) {
516
	        this.genericCast = fieldCodegenBinding.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
546
	        this.genericCast = codegenField.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case
517
	    }
547
	    }
518
	}
548
	}
519
	if ((this.bits & Binding.FIELD) != 0) {
520
		FieldBinding fieldBinding = (FieldBinding) this.binding;
521
522
		// if the binding declaring class is not visible, need special action
523
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
524
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
525
		// and not from Object or implicit static field access.
526
		if (fieldBinding.declaringClass != this.delegateThis.type
527
				&& fieldBinding.declaringClass != null // array.length
528
				&& fieldBinding.constant() == Constant.NotAConstant) {
529
			CompilerOptions options = currentScope.compilerOptions();
530
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
531
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
532
					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
533
				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
534
535
				this.codegenBinding =
536
				    currentScope.enclosingSourceType().getUpdatedFieldBinding(
537
					       (FieldBinding)this.codegenBinding,
538
					        (ReferenceBinding)this.delegateThis.type.erasure());
539
			}
540
		}
541
	}
542
}
549
}
543
/**
550
/**
544
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
551
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
Lines 551-557 Link Here
551
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
558
			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
552
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
559
			if (this.delegateThis != null){  // if not found then internal error, field should have been found
553
				// will not support innerclass emulation inside delegate
560
				// will not support innerclass emulation inside delegate
554
				this.codegenBinding = this.binding = scope.getField(this.delegateThis.type, this.token, this);
561
				this.binding = scope.getField(this.delegateThis.type, this.token, this);
555
				if (!this.binding.isValidBinding()) {
562
				if (!this.binding.isValidBinding()) {
556
					return super.reportError(scope);
563
					return super.reportError(scope);
557
				}
564
				}
Lines 569-581 Link Here
569
					if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
576
					if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
570
						// manage the access to a private field of the enclosing type
577
						// manage the access to a private field of the enclosing type
571
						CodeSnippetScope localScope = new CodeSnippetScope(scope);
578
						CodeSnippetScope localScope = new CodeSnippetScope(scope);
572
						this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
579
						this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
573
						return checkFieldAccess(scope);
580
						return checkFieldAccess(scope);
574
					} else {
581
					} else {
575
						return super.reportError(scope);
582
						return super.reportError(scope);
576
					}
583
					}
577
				}
584
				}
578
				this.codegenBinding = this.binding = fieldBinding;
585
				this.binding = fieldBinding;
579
				return checkFieldAccess(scope);
586
				return checkFieldAccess(scope);
580
			}
587
			}
581
		}
588
		}
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java (-1 / +1 lines)
Lines 74-80 Link Here
74
		// generate arguments
74
		// generate arguments
75
		generateArguments(this.binding, this.arguments, currentScope, codeStream);
75
		generateArguments(this.binding, this.arguments, currentScope, codeStream);
76
		// actual message invocation
76
		// actual message invocation
77
		TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope);
77
		TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenBinding, this.actualReceiverType, this.receiver.isImplicitThis(), this.receiverGenericCast != null);
78
		if (isStatic) {
78
		if (isStatic) {
79
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
79
			codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
80
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
80
		} else if( (this.receiver.isSuper()) || codegenBinding.isPrivate()){
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java (-1 / +2 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
13
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
14
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
14
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
15
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
15
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.impl.Constant;
16
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
17
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
18
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
Lines 58-64 Link Here
58
		int pc = codeStream.position;
59
		int pc = codeStream.position;
59
		if (valueRequired) {
60
		if (valueRequired) {
60
			codeStream.aload_0();
61
			codeStream.aload_0();
61
			codeStream.getfield(this.delegateThis);
62
			codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access
62
		}
63
		}
63
		codeStream.recordPositionsFrom(pc, this.sourceStart);
64
		codeStream.recordPositionsFrom(pc, this.sourceStart);
64
	}
65
	}
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java (-407 / +120 lines)
Lines 15-37 Link Here
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
16
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
17
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
17
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
18
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
20
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
19
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
21
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
22
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
23
import org.eclipse.jdt.internal.compiler.impl.Constant;
20
import org.eclipse.jdt.internal.compiler.impl.Constant;
24
import org.eclipse.jdt.internal.compiler.lookup.Binding;
21
import org.eclipse.jdt.internal.compiler.lookup.Binding;
25
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
23
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
27
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
27
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
32
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.Scope;
29
import org.eclipse.jdt.internal.compiler.lookup.Scope;
34
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
35
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
31
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
37
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
Lines 53-416 Link Here
53
/**
48
/**
54
 * Check and/or redirect the field access to the delegate receiver if any
49
 * Check and/or redirect the field access to the delegate receiver if any
55
 */
50
 */
56
public TypeBinding checkFieldAccess(BlockScope scope) {
57
	// check for forward references
58
	this.bits &= ~RestrictiveFlagMASK; // clear bits
59
	this.bits |= Binding.FIELD;
60
	return getOtherFieldBindings(scope);
61
}
62
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
51
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
63
52
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
64
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
65
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
53
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
66
		// the last field access is a write access
54
		super.generateAssignment(currentScope, codeStream, assignment, valueRequired);
67
		assignment.expression.generateCode(currentScope, codeStream, true);
55
		return;
68
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
56
	}
69
	} else {
57
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
70
		codeStream.generateEmulationForField(lastFieldBinding);
58
	codeStream.generateEmulationForField(lastFieldBinding);
71
		codeStream.swap();
59
	codeStream.swap();
72
		assignment.expression.generateCode(currentScope, codeStream, true);
60
	assignment.expression.generateCode(currentScope, codeStream, true);
73
		if (valueRequired) {
61
	if (valueRequired) {
74
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
62
		switch (lastFieldBinding.type.id) {
63
			case TypeIds.T_long :
64
			case TypeIds.T_double :
75
				codeStream.dup2_x2();
65
				codeStream.dup2_x2();
76
			} else {
66
				break;
67
			default :
77
				codeStream.dup_x2();
68
				codeStream.dup_x2();
78
			}
69
			break;	
79
		}
70
		}		
80
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
81
	}
71
	}
72
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
82
	if (valueRequired) {
73
	if (valueRequired) {
83
		codeStream.generateImplicitConversion(assignment.implicitConversion);
74
		codeStream.generateImplicitConversion(assignment.implicitConversion);
84
	}
75
	}
85
}
76
}
86
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
77
87
	int pc = codeStream.position;
78
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
88
	if (this.constant != Constant.NotAConstant) {
79
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
89
		if (valueRequired) {
80
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
90
			codeStream.generateConstant(this.constant, this.implicitConversion);
81
		super.generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired);
91
		}
82
		return;
83
	}
84
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
85
	if (lastFieldBinding.isStatic()){
86
		codeStream.generateEmulationForField(lastFieldBinding);
87
		codeStream.swap();
88
		codeStream.aconst_null();
89
		codeStream.swap();
90
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
92
	} else {
91
	} else {
93
		FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
92
		codeStream.generateEmulationForField(lastFieldBinding);
94
		if (valueRequired) {
93
		codeStream.swap();
95
			if (lastFieldBinding.declaringClass == null) { // array length
94
		codeStream.dup();
96
				codeStream.arraylength();
95
97
				codeStream.generateImplicitConversion(this.implicitConversion);
96
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
98
			} else {
97
	}
99
				Constant fieldConstant = lastFieldBinding.constant();
98
	// the last field access is a write access
100
				if (fieldConstant != Constant.NotAConstant) {
99
	// perform the actual compound operation
101
					if (!lastFieldBinding.isStatic()){
100
	int operationTypeID;
102
						codeStream.invokeObjectGetClass();
101
	if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
103
						codeStream.pop();
102
		codeStream.generateStringConcatenationAppend(currentScope, null, expression);
104
					}
103
	} else {
105
					// inline the last field constant
104
		// promote the array reference to the suitable operation type
106
					codeStream.generateConstant(fieldConstant, this.implicitConversion);
105
		codeStream.generateImplicitConversion(this.implicitConversion);
107
				} else {
106
		// generate the increment value (will by itself  be promoted to the operation value)
108
					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
107
		if (expression == IntLiteral.One){ // prefix operation
109
						if (lastFieldBinding.isStatic()) {
108
			codeStream.generateConstant(expression.constant, this.implicitConversion);
110
							codeStream.getstatic(lastFieldBinding);
111
						} else {
112
							codeStream.getfield(lastFieldBinding);
113
						}
114
					} else {
115
						codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
116
					}
117
					codeStream.generateImplicitConversion(this.implicitConversion);
118
				}
119
			}
120
		} else {
109
		} else {
121
			if (lastFieldBinding != null && !lastFieldBinding.isStatic()){
110
			expression.generateCode(currentScope, codeStream, true);
122
				codeStream.invokeObjectGetClass(); // perform null check
123
				codeStream.pop();
124
			}
125
		}
111
		}
112
		// perform the operation
113
		codeStream.sendOperator(operator, operationTypeID);
114
		// cast the value back to the array reference type
115
		codeStream.generateImplicitConversion(assignmentImplicitConversion);
126
	}
116
	}
127
	codeStream.recordPositionsFrom(pc, this.sourceStart);
117
	// actual assignment
128
}
129
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
130
118
131
	FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
119
	// current stack is:
132
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
120
	// field receiver value
133
		if (lastFieldBinding.isStatic()){
121
	if (valueRequired) {
134
			codeStream.getstatic(lastFieldBinding);
122
		switch (lastFieldBinding.type.id) {
135
		} else {
123
			case TypeIds.T_long :
136
			codeStream.dup();
124
			case TypeIds.T_double :
137
			codeStream.getfield(lastFieldBinding);
125
				codeStream.dup2_x2();
138
		}
139
		// the last field access is a write access
140
		// perform the actual compound operation
141
		int operationTypeID;
142
		switch(operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
143
			case T_JavaLangString :
144
			case T_JavaLangObject :
145
			case T_undefined :
146
				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
147
				break;
126
				break;
148
			default :
127
			default :
149
				// promote the array reference to the suitable operation type
150
				codeStream.generateImplicitConversion(this.implicitConversion);
151
				// generate the increment value (will by itself  be promoted to the operation value)
152
				if (expression == IntLiteral.One){ // prefix operation
153
					codeStream.generateConstant(expression.constant, this.implicitConversion);
154
				} else {
155
					expression.generateCode(currentScope, codeStream, true);
156
				}
157
				// perform the operation
158
				codeStream.sendOperator(operator, operationTypeID);
159
				// cast the value back to the array reference type
160
				codeStream.generateImplicitConversion(assignmentImplicitConversion);
161
		}
162
		// actual assignment
163
		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
164
	} else {
165
		if (lastFieldBinding.isStatic()){
166
			codeStream.generateEmulationForField(lastFieldBinding);
167
			codeStream.swap();
168
			codeStream.aconst_null();
169
			codeStream.swap();
170
171
			codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
172
		} else {
173
			codeStream.generateEmulationForField(lastFieldBinding);
174
			codeStream.swap();
175
			codeStream.dup();
176
177
			codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
178
		}
179
		// the last field access is a write access
180
		// perform the actual compound operation
181
		int operationTypeID;
182
		if ((operationTypeID = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_JavaLangString) {
183
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
184
		} else {
185
			// promote the array reference to the suitable operation type
186
			codeStream.generateImplicitConversion(this.implicitConversion);
187
			// generate the increment value (will by itself  be promoted to the operation value)
188
			if (expression == IntLiteral.One){ // prefix operation
189
				codeStream.generateConstant(expression.constant, this.implicitConversion);
190
			} else {
191
				expression.generateCode(currentScope, codeStream, true);
192
			}
193
			// perform the operation
194
			codeStream.sendOperator(operator, operationTypeID);
195
			// cast the value back to the array reference type
196
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
197
		}
198
		// actual assignment
199
200
		// current stack is:
201
		// field receiver value
202
		if (valueRequired) {
203
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
204
				codeStream.dup2_x2();
205
			} else {
206
				codeStream.dup_x2();
128
				codeStream.dup_x2();
207
			}
129
			break;	
208
		}
130
		}
209
		// current stack is:
210
		// value field receiver value
211
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
212
	}
131
	}
132
	// current stack is:
133
	// value field receiver value
134
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
213
}
135
}
214
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
136
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
215
137
    FieldBinding lastFieldBinding = this.otherBindings == null ? (FieldBinding) this.binding : this.otherBindings[this.otherBindings.length-1];
216
    FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
217
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
138
	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
218
		SyntheticMethodBinding accessor =
139
		super.generatePostIncrement(currentScope, codeStream, postIncrement, valueRequired);
219
			this.syntheticReadAccessors == null
140
		return;
220
				? null
141
	}
221
				: this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
142
	lastFieldBinding = generateReadSequence(currentScope, codeStream);
143
	codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
144
	if (valueRequired) {
145
		switch (lastFieldBinding.type.id) {
146
			case TypeIds.T_long :
147
			case TypeIds.T_double :
148
				codeStream.dup2();
149
				break;
150
			default :
151
				codeStream.dup();
152
			break;	
153
		}		
154
	}
155
	codeStream.generateEmulationForField(lastFieldBinding);
156
	if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
157
		codeStream.dup_x2();
158
		codeStream.pop();
222
		if (lastFieldBinding.isStatic()) {
159
		if (lastFieldBinding.isStatic()) {
223
			if (accessor == null) {
160
			codeStream.aconst_null();
224
				codeStream.getstatic(lastFieldBinding);
225
			} else {
226
				codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
227
			}
228
		} else {
161
		} else {
229
			codeStream.dup();
162
			generateReadSequence(currentScope, codeStream);
230
			if (accessor == null) {
231
				codeStream.getfield(lastFieldBinding);
232
			} else {
233
				codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
234
			}
235
		}
163
		}
236
164
		codeStream.dup_x2();
237
		TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
165
		codeStream.pop();
238
		if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast);
239
		codeStream.generateImplicitConversion(this.implicitConversion);
240
241
		// duplicate the old field value
242
		int operandType = this.implicitConversion & TypeIds.COMPILE_TYPE_MASK;
243
		if (valueRequired) {
244
			if (lastFieldBinding.isStatic()) {
245
				if (operandType == T_long || operandType == T_double) {
246
					codeStream.dup2();
247
				} else {
248
					codeStream.dup();
249
				}
250
			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
251
				if (operandType == T_long || operandType == T_double) {
252
					codeStream.dup2_x1();
253
				} else {
254
					codeStream.dup_x1();
255
				}
256
			}
257
		}
258
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
259
		codeStream.sendOperator(postIncrement.operator, operandType);
260
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
261
		fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false);
262
	} else {
166
	} else {
263
		codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
167
		codeStream.dup_x1();
264
		if (valueRequired) {
168
		codeStream.pop();
265
			if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
169
		if (lastFieldBinding.isStatic()) {
266
				codeStream.dup2();
170
			codeStream.aconst_null();
267
			} else {
268
				codeStream.dup();
269
			}
270
		}
271
		codeStream.generateEmulationForField(lastFieldBinding);
272
		if ((lastFieldBinding.type == TypeBinding.LONG) || (lastFieldBinding.type == TypeBinding.DOUBLE)) {
273
			codeStream.dup_x2();
274
			codeStream.pop();
275
			if (lastFieldBinding.isStatic()) {
276
				codeStream.aconst_null();
277
			} else {
278
				generateReadSequence(currentScope, codeStream);
279
			}
280
			codeStream.dup_x2();
281
			codeStream.pop();
282
		} else {
171
		} else {
283
			codeStream.dup_x1();
172
			generateReadSequence(currentScope, codeStream);
284
			codeStream.pop();
285
			if (lastFieldBinding.isStatic()) {
286
				codeStream.aconst_null();
287
			} else {
288
				generateReadSequence(currentScope, codeStream);
289
			}
290
			codeStream.dup_x1();
291
			codeStream.pop();
292
		}
173
		}
293
		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
174
		codeStream.dup_x1();
294
		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
175
		codeStream.pop();
295
		codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
296
		codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
297
	}
176
	}
298
}
177
	codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
299
/*
178
	codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
300
 * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code
179
	codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
301
 * for a read or write access.
180
	codeStream.generateEmulatedWriteAccessForField(lastFieldBinding);
302
 */
303
public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
304
305
	// determine the rank until which we now we do not need any actual value for the field access
306
	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
307
	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
308
	FieldBinding lastFieldBinding = null;
309
	TypeBinding lastGenericCast = null;
310
311
	switch (this.bits & RestrictiveFlagMASK) {
312
		case Binding.FIELD :
313
			lastFieldBinding = (FieldBinding) this.codegenBinding;
314
			lastGenericCast = this.genericCast;
315
			// if first field is actually constant, we can inline it
316
			if (lastFieldBinding.constant() != Constant.NotAConstant) {
317
				break;
318
			}
319
			if (needValue) {
320
				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
321
					if (!lastFieldBinding.isStatic()) {
322
						if ((this.bits & DepthMASK) != 0) {
323
							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
324
							Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
325
							codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
326
						} else {
327
							generateReceiver(codeStream);
328
						}
329
					}
330
				} else {
331
					if (!lastFieldBinding.isStatic()) {
332
						if ((this.bits & DepthMASK) != 0) {
333
							// internal error, per construction we should have found it
334
							// not yet supported
335
							currentScope.problemReporter().needImplementation(this);
336
						} else {
337
							generateReceiver(codeStream);
338
						}
339
					} else {
340
						codeStream.aconst_null();
341
					}
342
				}
343
			}
344
			break;
345
		case Binding.LOCAL : // reading the first local variable
346
			if (!needValue) break; // no value needed
347
			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
348
			// regular local variable read
349
			Constant localConstant = localBinding.constant();
350
			if (localConstant != Constant.NotAConstant) {
351
				codeStream.generateConstant(localConstant, 0);
352
				// no implicit conversion
353
			} else {
354
				// outer local?
355
				if ((this.bits & DepthMASK) != 0) {
356
					// outer local can be reached either through a synthetic arg or a synthetic field
357
					VariableBinding[] path = currentScope.getEmulationPath(localBinding);
358
					codeStream.generateOuterAccess(path, this, localBinding, currentScope);
359
				} else {
360
					codeStream.load(localBinding);
361
				}
362
			}
363
	}
364
365
	// all intermediate field accesses are read accesses
366
	// only the last field binding is a write access
367
	if (this.otherCodegenBindings != null) {
368
		for (int i = 0; i < otherBindingsCount; i++) {
369
			FieldBinding nextField = this.otherCodegenBindings[i];
370
			TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
371
			if (lastFieldBinding != null) {
372
				needValue = !nextField.isStatic();
373
				if (needValue) {
374
					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
375
						Constant fieldConstant = lastFieldBinding.constant();
376
						if (fieldConstant != Constant.NotAConstant) {
377
							if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
378
								codeStream.invokeObjectGetClass(); // perform null check
379
								codeStream.pop();
380
							}
381
							codeStream.generateConstant(fieldConstant, 0);
382
						} else if (lastFieldBinding.isStatic()) {
383
							codeStream.getstatic(lastFieldBinding);
384
						} else {
385
							codeStream.getfield(lastFieldBinding);
386
						}
387
					} else {
388
						codeStream.generateEmulatedReadAccessForField(lastFieldBinding);
389
					}
390
					if (lastGenericCast != null) codeStream.checkcast(lastGenericCast);
391
				} else {
392
					if (this.codegenBinding != lastFieldBinding && !lastFieldBinding.isStatic()){
393
						codeStream.invokeObjectGetClass(); // perform null check
394
						codeStream.pop();
395
					}
396
				}
397
			}
398
			lastFieldBinding = nextField;
399
			lastGenericCast = nextGenericCast;
400
			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
401
				if (lastFieldBinding.isStatic()) {
402
					codeStream.aconst_null();
403
				}
404
			}
405
		}
406
	}
407
	return lastFieldBinding;
408
}
181
}
409
182
410
public void generateReceiver(CodeStream codeStream) {
183
public void generateReceiver(CodeStream codeStream) {
411
	codeStream.aload_0();
184
	codeStream.aload_0();
412
	if (this.delegateThis != null) {
185
	if (this.delegateThis != null) {
413
		codeStream.getfield(this.delegateThis); // delegated field access
186
		codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegated field access
414
	}
187
	}
415
}
188
}
416
public TypeBinding getOtherFieldBindings(BlockScope scope) {
189
public TypeBinding getOtherFieldBindings(BlockScope scope) {
Lines 445-451 Link Here
445
218
446
	// allocation of the fieldBindings array	and its respective constants
219
	// allocation of the fieldBindings array	and its respective constants
447
	int otherBindingsLength = length - index;
220
	int otherBindingsLength = length - index;
448
	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
221
	this.otherBindings = new FieldBinding[otherBindingsLength];
449
222
450
	// fill the first constant (the one of the binding)
223
	// fill the first constant (the one of the binding)
451
	this.constant =((VariableBinding) this.binding).constant();
224
	this.constant =((VariableBinding) this.binding).constant();
Lines 466-471 Link Here
466
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
239
					if (this.delegateThis == null){  // if not found then internal error, field should have been found
467
						return super.reportError(scope);
240
						return super.reportError(scope);
468
					}
241
					}
242
					this.actualReceiverType = this.delegateThis.type;
469
				} else {
243
				} else {
470
					this.constant = Constant.NotAConstant; //don't fill other constants slots...
244
					this.constant = Constant.NotAConstant; //don't fill other constants slots...
471
					scope.problemReporter().invalidField(this, field, index, type);
245
					scope.problemReporter().invalidField(this, field, index, type);
Lines 494-576 Link Here
494
	}
268
	}
495
	return (this.otherBindings[otherBindingsLength - 1]).type;
269
	return (this.otherBindings[otherBindingsLength - 1]).type;
496
}
270
}
497
	/**
498
	 * Check and/or redirect the field access to the delegate receiver if any
499
	 */
500
	public TypeBinding getReceiverType(BlockScope currentScope) {
501
		Scope scope = currentScope.parent;
502
		while (true) {
503
				switch (scope.kind) {
504
					case Scope.CLASS_SCOPE :
505
						return ((ClassScope) scope).referenceContext.binding;
506
					default:
507
						scope = scope.parent;
508
				}
509
		}
510
	}
511
	/**
512
	 * index is <0 to denote write access emulation
513
	 */
514
	public void manageSyntheticAccessIfNecessary(
515
		BlockScope currentScope,
516
		FieldBinding fieldBinding,
517
		TypeBinding lastReceiverType,
518
		int index,
519
		FlowInfo flowInfo) {
520
521
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
522
523
		// if the binding declaring class is not visible, need special action
524
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
525
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
526
		boolean useDelegate;
527
		if (index < 0) { // write-access?
528
		    useDelegate = fieldBinding == this.binding && this.delegateThis != null;
529
		} else {
530
			useDelegate = index == 0 && this.delegateThis != null;
531
		}
532
271
533
		if (useDelegate) {
272
/**
534
			lastReceiverType = this.delegateThis.type;
273
 * Check and/or redirect the field access to the delegate receiver if any
535
		}
274
 */
536
		// if the binding declaring class is not visible, need special action
275
public TypeBinding getReceiverType(BlockScope currentScope) {
537
		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
276
	Scope scope = currentScope.parent;
538
		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
277
	while (true) {
539
		// and not from Object or implicit static field access.
278
			switch (scope.kind) {
540
		if (fieldBinding.declaringClass != lastReceiverType
279
				case Scope.CLASS_SCOPE :
541
				&& !lastReceiverType.isArrayType()
280
					return ((ClassScope) scope).referenceContext.binding;
542
				&& fieldBinding.declaringClass != null // array.length
281
				default:
543
				&& fieldBinding.constant() == Constant.NotAConstant) {
282
					scope = scope.parent;
544
			CompilerOptions options = currentScope.compilerOptions();
545
			if ((options.targetJDK >= ClassFileConstants.JDK1_2
546
					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || (index < 0 ? fieldBinding != this.binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
547
					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
548
				|| !(useDelegate
549
						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
550
						: fieldBinding.declaringClass.canBeSeenBy(currentScope))) {
551
552
			    if (index < 0) { // write-access?
553
					if (fieldBinding == this.binding){
554
						this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
555
					} else {
556
						if (this.otherCodegenBindings == this.otherBindings){
557
							int l = this.otherBindings.length;
558
							System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
559
						}
560
						this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
561
					}
562
			    } if (index == 0){
563
					this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
564
				} else {
565
					if (this.otherCodegenBindings == this.otherBindings){
566
						int l = this.otherBindings.length;
567
						System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
568
					}
569
					this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType.erasure());
570
				}
571
			}
283
			}
572
		}
573
	}
284
	}
285
}
286
	
574
/**
287
/**
575
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
288
 * Normal field binding did not work, try to bind to a field of the delegate receiver.
576
 */
289
 */
Lines 593-599 Link Here
593
			if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
306
			if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
594
				// manage the access to a private field of the enclosing type
307
				// manage the access to a private field of the enclosing type
595
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
308
				CodeSnippetScope localScope = new CodeSnippetScope(scope);
596
				this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this);
309
				this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this);
597
				if (this.binding.isValidBinding()) {
310
				if (this.binding.isValidBinding()) {
598
					return checkFieldAccess(scope);
311
					return checkFieldAccess(scope);
599
				} else {
312
				} else {
Lines 603-609 Link Here
603
				return super.reportError(scope);
316
				return super.reportError(scope);
604
			}
317
			}
605
		}
318
		}
606
		this.codegenBinding = this.binding = fieldBinding;
319
		this.binding = fieldBinding;
607
		return checkFieldAccess(scope);
320
		return checkFieldAccess(scope);
608
	}
321
	}
609
322
Lines 628-634 Link Here
628
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
341
	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField
629
342
630
	CodeSnippetScope localScope = new CodeSnippetScope(scope);
343
	CodeSnippetScope localScope = new CodeSnippetScope(scope);
631
	if ((this.codegenBinding = this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
344
	if ((this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
632
		this.bits &= ~RestrictiveFlagMASK; // clear bits
345
		this.bits &= ~RestrictiveFlagMASK; // clear bits
633
		this.bits |= Binding.FIELD;
346
		this.bits |= Binding.FIELD;
634
		return getOtherFieldBindings(scope);
347
		return getOtherFieldBindings(scope);
(-)codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java (-4 / +4 lines)
Lines 53-61 Link Here
53
53
54
	public TypeBinding resolveType(BlockScope scope) {
54
	public TypeBinding resolveType(BlockScope scope) {
55
55
56
		this.receiverType = this.receiver.resolveType(scope);
56
		this.actualReceiverType = this.receiver.resolveType(scope);
57
57
58
		if ((this.receiverType == null || !this.receiverType.isValidBinding()) && this.receiver instanceof MessageSend) {
58
		if ((this.actualReceiverType == null || !this.actualReceiverType.isValidBinding()) && this.receiver instanceof MessageSend) {
59
			MessageSend messageSend = (MessageSend) this.receiver;
59
			MessageSend messageSend = (MessageSend) this.receiver;
60
			if(messageSend.receiver instanceof ThisReference) {
60
			if(messageSend.receiver instanceof ThisReference) {
61
				Expression[] arguments = messageSend.arguments;
61
				Expression[] arguments = messageSend.arguments;
Lines 73-82 Link Here
73
			}
73
			}
74
		}
74
		}
75
75
76
		if (this.receiverType == null || this.receiverType.isBaseType() || !this.receiverType.isValidBinding())
76
		if (this.actualReceiverType == null || this.actualReceiverType.isBaseType() || !this.actualReceiverType.isValidBinding())
77
			throw new CompletionNodeFound();
77
			throw new CompletionNodeFound();
78
		else
78
		else
79
			throw new CompletionNodeFound(this, this.receiverType, scope);
79
			throw new CompletionNodeFound(this, this.actualReceiverType, scope);
80
		// array types are passed along to find the length field
80
		// array types are passed along to find the length field
81
	}
81
	}
82
}
82
}
(-)codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java (-3 / +3 lines)
Lines 93-103 Link Here
93
93
94
		// Resolve only receiver
94
		// Resolve only receiver
95
		if (this.receiver == null) {
95
		if (this.receiver == null) {
96
			this.receiverType = scope.enclosingSourceType();
96
			this.actualReceiverType = scope.enclosingSourceType();
97
		} else if (scope.kind == Scope.CLASS_SCOPE) {
97
		} else if (scope.kind == Scope.CLASS_SCOPE) {
98
			this.receiverType = this.receiver.resolveType((ClassScope) scope);
98
			this.actualReceiverType = this.receiver.resolveType((ClassScope) scope);
99
		} else {
99
		} else {
100
			this.receiverType = this.receiver.resolveType((BlockScope)scope);
100
			this.actualReceiverType = this.receiver.resolveType((BlockScope)scope);
101
		}
101
		}
102
		return null;
102
		return null;
103
	}
103
	}
(-)codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java (-4 / +4 lines)
Lines 1927-1934 Link Here
1927
				long completionPosition = fieldRef.nameSourcePosition;
1927
				long completionPosition = fieldRef.nameSourcePosition;
1928
				this.javadocTagPosition = fieldRef.tagSourceStart;
1928
				this.javadocTagPosition = fieldRef.tagSourceStart;
1929
1929
1930
				if (fieldRef.receiverType != null && fieldRef.receiverType.isValidBinding()) {
1930
				if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) {
1931
					ReferenceBinding receiverType = (ReferenceBinding) fieldRef.receiverType;
1931
					ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType;
1932
					int rangeStart = (int) (completionPosition >>> 32);
1932
					int rangeStart = (int) (completionPosition >>> 32);
1933
					if (fieldRef.receiver.isThis()) {
1933
					if (fieldRef.receiver.isThis()) {
1934
						if (fieldRef.completeInText()) {
1934
						if (fieldRef.completeInText()) {
Lines 1984-1991 Link Here
1984
							null,
1984
							null,
1985
							-1,
1985
							-1,
1986
							-1);
1986
							-1);
1987
						if (fieldRef.receiverType instanceof ReferenceBinding) {
1987
						if (fieldRef.actualReceiverType instanceof ReferenceBinding) {
1988
							ReferenceBinding refBinding = (ReferenceBinding)fieldRef.receiverType;
1988
							ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType;
1989
							if (this.completionToken == null
1989
							if (this.completionToken == null
1990
									|| CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
1990
									|| CharOperation.prefixEquals(this.completionToken, refBinding.sourceName)
1991
									|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
1991
									|| (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) {
(-)src/org/eclipse/jdt/core/tests/eval/CodeSnippetTest.java (+193 lines)
Lines 675-680 Link Here
675
		"10".toCharArray());
675
		"10".toCharArray());
676
}
676
}
677
/**
677
/**
678
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
679
 * code snippet support (see PR #1G1C0HR).
680
 */
681
public void testRunMethodInAnonymous2() {
682
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
683
		"class X {",
684
		"	public int i = 0;",
685
		"   public boolean finished = false;",
686
		"}",
687
		"final X x = new X();",
688
		"(new Thread() {",
689
		"	public void run() {",
690
		"		for (int i=0;i<10;i++) {",
691
		"			try {",
692
		"				Thread.currentThread().sleep(10);",
693
		"			} catch (InterruptedException e) {",
694
		"			}",
695
		"			++x.i;",
696
		"		}",
697
		"       x.finished = true;",
698
		"	}",
699
		"}).start();",
700
		"while (!x.finished) Thread.currentThread().sleep(100);",
701
		"x.i"}),
702
		"10".toCharArray());
703
}
704
/**
705
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
706
 * code snippet support (see PR #1G1C0HR).
707
 */
708
public void testRunMethodInAnonymous3() {
709
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
710
		"class X {",
711
		"	public int i = 0;",
712
		"   public boolean finished = false;",
713
		"}",
714
		"final X x = new X();",
715
		"(new Thread() {",
716
		"	public void run() {",
717
		"		for (int i=0;i<10;i++) {",
718
		"			try {",
719
		"				Thread.currentThread().sleep(10);",
720
		"			} catch (InterruptedException e) {",
721
		"			}",
722
		"			x.i += 1;",
723
		"		}",
724
		"       x.finished = true;",
725
		"	}",
726
		"}).start();",
727
		"while (!x.finished) Thread.currentThread().sleep(100);",
728
		"x.i"}),
729
		"10".toCharArray());
730
}
731
/**
732
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
733
 * code snippet support (see PR #1G1C0HR).
734
 */
735
public void testRunMethodInAnonymous4() {
736
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
737
		"class X {",
738
		"	public int i = 0;",
739
		"   public boolean finished = false;",
740
		"}",
741
		"final X x = new X();",
742
		"(new Thread() {",
743
		"	public void run() {",
744
		"		for (int i=0;i<10;i++) {",
745
		"			try {",
746
		"				Thread.currentThread().sleep(10);",
747
		"			} catch (InterruptedException e) {",
748
		"			}",
749
		"			x.i = x.i + 1;",
750
		"		}",
751
		"       x.finished = true;",
752
		"	}",
753
		"}).start();",
754
		"while (!x.finished) Thread.currentThread().sleep(100);",
755
		"x.i"}),
756
		"10".toCharArray());
757
}
758
/**
759
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
760
 * code snippet support (see PR #1G1C0HR).
761
 */
762
public void testRunMethodInAnonymous5() {
763
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
764
		"class X {",
765
		"	public int i = 0;",
766
		"   public boolean finished = false;",
767
		"	public X self() { return this; }",
768
		"}",
769
		"final X x = new X();",
770
		"(new Thread() {",
771
		"	public void run() {",
772
		"		for (int i=0;i<10;i++) {",
773
		"			try {",
774
		"				Thread.currentThread().sleep(10);",
775
		"			} catch (InterruptedException e) {",
776
		"			}",
777
		"			x.self().i++;",
778
		"		}",
779
		"       x.finished = true;",
780
		"	}",
781
		"}).start();",
782
		"while (!x.finished) Thread.currentThread().sleep(100);",
783
		"x.i"}),
784
		"10".toCharArray());
785
}
786
/**
787
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
788
 * code snippet support (see PR #1G1C0HR).
789
 */
790
public void testRunMethodInAnonymous6() {
791
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
792
		"class X {",
793
		"	public int i = 0;",
794
		"   public boolean finished = false;",
795
		"	public X self() { return this; }",
796
		"}",
797
		"final X x = new X();",
798
		"(new Thread() {",
799
		"	public void run() {",
800
		"		for (int i=0;i<10;i++) {",
801
		"			try {",
802
		"				Thread.currentThread().sleep(10);",
803
		"			} catch (InterruptedException e) {",
804
		"			}",
805
		"			++ (x.self().i);",
806
		"		}",
807
		"       x.finished = true;",
808
		"	}",
809
		"}).start();",
810
		"while (!x.finished) Thread.currentThread().sleep(100);",
811
		"x.i"}),
812
		"10".toCharArray());
813
}
814
/**
815
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
816
 * code snippet support (see PR #1G1C0HR).
817
 */
818
public void testRunMethodInAnonymous7() {
819
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
820
		"class X {",
821
		"	public int i = 0;",
822
		"   public boolean finished = false;",
823
		"	public X self() { return this; }",
824
		"}",
825
		"final X x = new X();",
826
		"(new Thread() {",
827
		"	public void run() {",
828
		"		for (int i=0;i<10;i++) {",
829
		"			try {",
830
		"				Thread.currentThread().sleep(10);",
831
		"			} catch (InterruptedException e) {",
832
		"			}",
833
		"			x.self().i += 1;",
834
		"		}",
835
		"       x.finished = true;",
836
		"	}",
837
		"}).start();",
838
		"while (!x.finished) Thread.currentThread().sleep(100);",
839
		"x.i"}),
840
		"10".toCharArray());
841
}
842
/**
843
 * Tests that the run() method defined in an anonymous class doesn't interfer with the
844
 * code snippet support (see PR #1G1C0HR).
845
 */
846
public void testRunMethodInAnonymous8() {
847
	evaluateWithExpectedDisplayString(buildCharArray(new String[] {
848
		"class X {",
849
		"	public int i = 0;",
850
		"   public boolean finished = false;",
851
		"	public X self() { return this; }",
852
		"}",
853
		"final X x = new X();",
854
		"(new Thread() {",
855
		"	public void run() {",
856
		"		for (int i=0;i<10;i++) {",
857
		"			try {",
858
		"				Thread.currentThread().sleep(10);",
859
		"			} catch (InterruptedException e) {",
860
		"			}",
861
		"			x.self().i = x.self().i + 1;",
862
		"		}",
863
		"       x.finished = true;",
864
		"	}",
865
		"}).start();",
866
		"while (!x.finished) Thread.currentThread().sleep(100);",
867
		"x.i"}),
868
		"10".toCharArray());
869
}
870
/**
678
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=89632
871
 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=89632
679
 */
872
 */
680
public void testFor89632() {
873
public void testFor89632() {

Return to bug 247612