/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
 *								bug 292478 - Report potentially null across variable assignment,
 *								bug 185682 - Increment/decrement operators mark local variables as read
 *								bug 331649 - [compiler][null] consider null annotations for fields
 *								bug 383368 - [compiler][null] syntactic null analysis for field references
 *								Bug 412203 - [compiler] Internal compiler error: java.lang.IllegalArgumentException: info cannot be null
 *								Bug 458396 - NPE in CodeStream.invoke()
 *								Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
 *     Jesper S Moller - <jesper@selskabet.org>   - Contributions for
 *     							bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
 *								bug 378674 - "The method can be declared as static" is wrong
 *								bug 404657 - [1.8][compiler] Analysis for effectively final variables fails to consider loops
 *								bug 527554 - [18.3] Compiler support for JEP 286 Local-Variable Type
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticOTTargetMethod;
import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;

/**
 * OTDT changes:
 *
 * What: create access methods when a role accesses fields of its team.
 * Why:  through copy inheritance role and team may reside in different packages.
 *
 * What: Allow a static role method to access a non-static team field.
 *
 * What: wrap role type in resolveType().
 *
 */
public class SingleNameReference extends NameReference implements OperatorIds {

	public static final int READ = 0;
	public static final int WRITE = 1;
	public char[] token;
	public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
	public TypeBinding genericCast;
	public boolean isLabel;// flagging for break expression when expression is SwitchExpression - java 12 preview-feature
//{ObjectTeams: in generated out-of-scope code a name may have the privilige of a (t)this:
	public boolean isThisLike;
// SH}

public SingleNameReference(char[] source, long pos) {
	super();
	this.token = source;
	this.sourceStart = (int) (pos >>> 32);
	this.sourceEnd = (int) pos;
}

@Override
public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
	boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0;
	// compound assignment extra work
	if (isCompound) { // check the variable part is initialized if blank final
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
			case Binding.FIELD : // reading a field
				FieldBinding fieldBinding = (FieldBinding) this.binding;
				if (fieldBinding.isBlankFinal()
						&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
					FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
					if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
					}
				}
				manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
				break;
			case Binding.LOCAL : // reading a local variable
				// check if assigning a final blank field
				LocalVariableBinding localBinding;
				if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
					currentScope.problemReporter().uninitializedLocalVariable(localBinding, this, currentScope);
					// we could improve error msg here telling "cannot use compound assignment on final local variable"
				}
				if (localBinding.useFlag != LocalVariableBinding.USED) {
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
					// access from compound assignment does not prevent "unused" warning, unless unboxing is involved:
					if (isReachable && (this.implicitConversion & TypeIds.UNBOXING) != 0) {
						localBinding.useFlag = LocalVariableBinding.USED;
					} else {
						// use values < 0 to count the number of compound uses:
						if (localBinding.useFlag <= LocalVariableBinding.UNUSED)
							localBinding.useFlag--;
					}
				}
		}
	}
	if (assignment.expression != null) {
		flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
	}
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // assigning to a field
			manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);

			// check if assigning a final field
			FieldBinding fieldBinding = (FieldBinding) this.binding;
			if (fieldBinding.isFinal()) {
				// inside a context where allowed
				if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
					if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
						currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
					} else {
						flowContext.recordSettingFinal(fieldBinding, this, flowInfo);
					}
					flowInfo.markAsDefinitelyAssigned(fieldBinding);
				} else {
					currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
				}
			} else if (!isCompound && (fieldBinding.isNonNull() || fieldBinding.type.isTypeVariable())
						&& TypeBinding.equalsEquals(fieldBinding.declaringClass, currentScope.enclosingReceiverType())) { // inherited fields are not tracked here
				// record assignment for detecting uninitialized non-null fields:
				flowInfo.markAsDefinitelyAssigned(fieldBinding);
			}
			break;
		case Binding.LOCAL : // assigning to a local variable
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			final boolean isFinal = localBinding.isFinal();
			if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
				this.bits |= ASTNode.FirstAssignmentToLocal;
			} else {
				this.bits &= ~ASTNode.FirstAssignmentToLocal;
			}
			if (flowInfo.isPotentiallyAssigned(localBinding) || (this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
				localBinding.tagBits &= ~TagBits.IsEffectivelyFinal;
				if (!isFinal) {
					if ((this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
						currentScope.problemReporter().cannotReferToNonEffectivelyFinalOuterLocal(localBinding, this);
					} else if ((this.bits & ASTNode.IsUsedInPatternGuard) != 0) {
						currentScope.problemReporter().cannotReferToNonFinalLocalInGuard(localBinding, this);
					}
				}
			}
			if (! isFinal && (localBinding.tagBits & TagBits.IsEffectivelyFinal) != 0 && (localBinding.tagBits & TagBits.IsArgument) == 0) {
				flowContext.recordSettingFinal(localBinding, this, flowInfo);
			} else if (isFinal) {
				if ((this.bits & ASTNode.DepthMASK) == 0) {
					// tolerate assignment to final local in unreachable code (45674)
					if ((isReachable && isCompound) || !localBinding.isBlankFinal()){
						currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
					} else if (flowInfo.isPotentiallyAssigned(localBinding)) {
						currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
					} else if ((this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
						currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
					} else {
						flowContext.recordSettingFinal(localBinding, this, flowInfo);
					}
				} else {
					currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
				}
			}
			else /* avoid double diagnostic */ if ((localBinding.tagBits & TagBits.IsArgument) != 0) {
				currentScope.problemReporter().parameterAssignment(localBinding, this);
			}
			flowInfo.markAsDefinitelyAssigned(localBinding);
	}
	manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
	return flowInfo;
}

@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
	return analyseCode(currentScope, flowContext, flowInfo, true);
}

@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // reading a field
			if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
				manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
			}
			// check if reading a final blank field
			FieldBinding fieldBinding = (FieldBinding) this.binding;
			if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
				FlowInfo fieldInits = flowContext.getInitsForFinalBlankInitializationCheck(fieldBinding.declaringClass.original(), flowInfo);
				if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
				}
			}
			break;
		case Binding.LOCAL : // reading a local variable
			LocalVariableBinding localBinding;
			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this, currentScope);
			}
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
				localBinding.useFlag = LocalVariableBinding.USED;
			} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
				localBinding.useFlag = LocalVariableBinding.FAKE_USED;
			}
	}
	if (valueRequired) {
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
	}
	return flowInfo;
}

public TypeBinding checkFieldAccess(BlockScope scope) {
	FieldBinding fieldBinding = (FieldBinding) this.binding;
	this.constant = fieldBinding.constant(scope);

	this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
	this.bits |= Binding.FIELD;
	MethodScope methodScope = scope.methodScope();
	if (fieldBinding.isStatic()) {
		// check if accessing enum static field in initializer
		ReferenceBinding declaringClass = fieldBinding.declaringClass;
		if (declaringClass.isEnum() && scope.kind != Scope.MODULE_SCOPE) {
			SourceTypeBinding sourceType = scope.enclosingSourceType();
			if (this.constant == Constant.NotAConstant
					&& !methodScope.isStatic
					&& (TypeBinding.equalsEquals(sourceType, declaringClass) || TypeBinding.equalsEquals(sourceType.superclass, declaringClass)) // enum constant body
					&& methodScope.isInsideInitializerOrConstructor()) {
				scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
			}
		}
	} else {
		if (scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
			scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
		}
		// must check for the static status....
		if (   methodScope.isStatic
//{ObjectTeams: support non-static team field to be accessed from static role method:
				&& !TeamModel.isTeamContainingRole(fieldBinding.declaringClass, methodScope.enclosingReceiverType()))
// SH}
		{
			scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
			return fieldBinding.type;
		} else {
			scope.tagAsAccessingEnclosingInstanceStateOf(fieldBinding.declaringClass, false /* type variable access */);
		}
	}

	if (isFieldUseDeprecated(fieldBinding, scope, this.bits))
		scope.problemReporter().deprecatedField(fieldBinding, this);

	if ((this.bits & ASTNode.IsStrictlyAssigned) == 0
			&& TypeBinding.equalsEquals(methodScope.enclosingSourceType(), fieldBinding.original().declaringClass)
			&& methodScope.lastVisibleFieldID >= 0
			&& fieldBinding.id >= methodScope.lastVisibleFieldID
			&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
		scope.problemReporter().forwardReference(this, 0, fieldBinding);
		this.bits |= ASTNode.IgnoreNoEffectAssignCheck;
	}
	return fieldBinding.type;

}

@Override
public boolean checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, int ttlForFieldCheck) {
	if (!super.checkNPE(scope, flowContext, flowInfo, ttlForFieldCheck)) {
		CompilerOptions compilerOptions = scope.compilerOptions();
		if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
			if (this.binding instanceof FieldBinding) {
				return checkNullableFieldDereference(scope, (FieldBinding) this.binding, ((long)this.sourceStart<<32)+this.sourceEnd, flowContext, ttlForFieldCheck);
			}
		}
	}
	return false;
}

/**
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
 */
@Override
public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
	if (runtimeTimeType == null || compileTimeType == null)
		return;
	if (this.binding != null && this.binding.isValidBinding()) {
		TypeBinding originalType = null;
		if ((this.bits & Binding.FIELD) != 0) {
			// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
			FieldBinding field = (FieldBinding) this.binding;
			FieldBinding originalBinding = field.original();
			originalType = originalBinding.type;
		} else if ((this.bits & Binding.LOCAL) != 0) {
			LocalVariableBinding local = (LocalVariableBinding) this.binding;
			originalType = local.type;
		}
		// extra cast needed if field/local type is type variable
		if (originalType != null && originalType.leafComponentType().isTypeVariable()) {
			TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
					? compileTimeType  // unboxing: checkcast before conversion
							: runtimeTimeType;
			this.genericCast = originalType.genericCast(scope.boxing(targetType));
			if (this.genericCast instanceof ReferenceBinding) {
				ReferenceBinding referenceCast = (ReferenceBinding) this.genericCast;
				if (!referenceCast.canBeSeenBy(scope)) {
					scope.problemReporter().invalidType(this,
							new ProblemReferenceBinding(
									CharOperation.splitOn('.', referenceCast.shortReadableName()),
									referenceCast,
									ProblemReasons.NotVisible));
				}
			}
		}
	}
	super.computeConversion(scope, runtimeTimeType, compileTimeType);
}

@Override
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
	// optimizing assignment like: i = i + 1 or i = 1 + i
	if (assignment.expression.isCompactableOperation()) {
		BinaryExpression operation = (BinaryExpression) assignment.expression;
		int operator = (operation.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
		SingleNameReference variableReference;
		if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) {
			// i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.right, operator, operation.implicitConversion, valueRequired);
			if (valueRequired) {
				codeStream.generateImplicitConversion(assignment.implicitConversion);
			}
			return;
		}
		if ((operation.right instanceof SingleNameReference)
				&& ((operator == OperatorIds.PLUS) || (operator == OperatorIds.MULTIPLY)) // only commutative operations
				&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
				&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
				&& (((operation.left.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.T_JavaLangString) // exclude string concatenation which would occur backwards
				&& (((operation.right.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.T_JavaLangString)) { // exclude string concatenation which would occur backwards
			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.left, operator, operation.implicitConversion, valueRequired);
			if (valueRequired) {
				codeStream.generateImplicitConversion(assignment.implicitConversion);
			}
			return;
		}
	}
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // assigning to a field
			int pc = codeStream.position;
			FieldBinding codegenBinding = ((FieldBinding) this.binding).original();
//{ObjectTeams: inferred callout-to-static-field??
			checkGeneratedSynthArgsForFieldAccess(this.syntheticAccessors, codeStream, currentScope);
// SH}
			if (!codegenBinding.isStatic()) { // need a receiver?
				if ((this.bits & ASTNode.DepthMASK) != 0) {
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
				} else {
					generateReceiver(codeStream);
				}
			}
			codeStream.recordPositionsFrom(pc, this.sourceStart);
			assignment.expression.generateCode(currentScope, codeStream, true);
			fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, valueRequired);
			if (valueRequired) {
				codeStream.generateImplicitConversion(assignment.implicitConversion);
			}
			// no need for generic cast as value got dupped
			return;
		case Binding.LOCAL : // assigning to a local variable
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			if (localBinding.resolvedPosition != -1) {
				assignment.expression.generateCode(currentScope, codeStream, true);
			} else {
				if (assignment.expression.constant != Constant.NotAConstant) {
					// assigning an unused local to a constant value = no actual assignment is necessary
					if (valueRequired) {
						codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
					}
				} else {
					assignment.expression.generateCode(currentScope, codeStream, true);
					/* Even though the value may not be required, we force it to be produced, and discard it later
					on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3.	*/
					if (valueRequired) {
						codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
					} else {
						switch(localBinding.type.id) {
							case TypeIds.T_long :
							case TypeIds.T_double :
								codeStream.pop2();
								break;
							default :
								codeStream.pop();
								break;
						}
					}
				}
				return;
			}
			// 26903, need extra cast to store null in array local var
			if (localBinding.type.isArrayType()
				&& ((assignment.expression instanceof CastExpression)	// arrayLoc = (type[])null
						&& (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL))){
				codeStream.checkcast(localBinding.type);
			}

			// normal local assignment (since cannot store in outer local which are final locations)
			codeStream.store(localBinding, valueRequired);
			if ((this.bits & ASTNode.IsSecretYieldValueUsage) != 0) {
				localBinding.recordInitializationStartPC(codeStream.position);
			}
			if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { // for local variable debug attributes
				localBinding.recordInitializationStartPC(codeStream.position);
			}
			// implicit conversion
			if (valueRequired) {
				codeStream.generateImplicitConversion(assignment.implicitConversion);
			}
	}
}

@Override
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
	int pc = codeStream.position;
	if (this.constant != Constant.NotAConstant) {
		if (valueRequired) {
			codeStream.generateConstant(this.constant, this.implicitConversion);
		}
		codeStream.recordPositionsFrom(pc, this.sourceStart);
		return;
	} else {
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
			case Binding.FIELD : // reading a field
				FieldBinding codegenField = ((FieldBinding) this.binding).original();
				Constant fieldConstant = codegenField.constant();
				if (fieldConstant != Constant.NotAConstant) {
					// directly use inlined value for constant fields
					if (valueRequired) {
						codeStream.generateConstant(fieldConstant, this.implicitConversion);
					}
					codeStream.recordPositionsFrom(pc, this.sourceStart);
					return;
				}
				if (codegenField.isStatic()) {
					if (!valueRequired
							// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class
							&& TypeBinding.equalsEquals(((FieldBinding)this.binding).original().declaringClass, this.actualReceiverType.erasure())
							&& ((this.implicitConversion & TypeIds.UNBOXING) == 0)
							&& this.genericCast == null) {
						// if no valueRequired, optimize out entire gen
						codeStream.recordPositionsFrom(pc, this.sourceStart);
						return;
					}
					// managing private access
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
						codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
					} else {
//{ObjectTeams: inferred callout-to-static-field??
						SyntheticMethodBinding syntheticMethodBinding = (SyntheticMethodBinding)this.syntheticAccessors[SingleNameReference.READ];
						if (syntheticMethodBinding.purpose == SyntheticMethodBinding.InferredCalloutToField)
							syntheticMethodBinding.generateStaticCTFArgs(codeStream, currentScope, this, (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
// SH}
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
					}
				} else {
					if (!valueRequired
							&& (this.implicitConversion & TypeIds.UNBOXING) == 0
							&& this.genericCast == null) {
						// if no valueRequired, optimize out entire gen
						codeStream.recordPositionsFrom(pc, this.sourceStart);
						return;
					}
					// managing enclosing instance access
					if ((this.bits & ASTNode.DepthMASK) != 0) {
						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
					} else {
						generateReceiver(codeStream);
					}
					// managing private access
					if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
						TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
						codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
					} else {
						codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
					}
				}
				break;
			case Binding.LOCAL : // reading a local
				LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
				if (localBinding.resolvedPosition == -1) {
					if (valueRequired) {
						// restart code gen
						localBinding.useFlag = LocalVariableBinding.USED;
						throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
					}
					codeStream.recordPositionsFrom(pc, this.sourceStart);
					return;
				}
				if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
					// if no valueRequired, optimize out entire gen
					codeStream.recordPositionsFrom(pc, this.sourceStart);
					return;
				}
				// checkEffectiveFinality() returns if it's outer local
				if (checkEffectiveFinality(localBinding, currentScope)) {
					// outer local can be reached either through a synthetic arg or a synthetic field
					VariableBinding[] path = currentScope.getEmulationPath(localBinding);
					codeStream.generateOuterAccess(path, this, localBinding, currentScope);
				} else {
					// regular local variable read
					codeStream.load(localBinding);
				}
				break;
			default: // type
				codeStream.recordPositionsFrom(pc, this.sourceStart);
				return;
		}
	}
	// required cast must occur even if no value is required
	if (this.genericCast != null) codeStream.checkcast(this.genericCast);
	if (valueRequired) {
		codeStream.generateImplicitConversion(this.implicitConversion);
	} else {
		boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
		// conversion only generated if unboxing
		if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
		switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) {
			case T_long :
			case T_double :
				codeStream.pop2();
				break;
			default :
				codeStream.pop();
		}
	}
	codeStream.recordPositionsFrom(pc, this.sourceStart);
}

/*
 * Regular API for compound assignment, relies on the fact that there is only one reference to the
 * variable, which carries both synthetic read/write accessors.
 * The APIs with an extra argument is used whenever there are two references to the same variable which
 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
 */
@Override
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.LOCAL:
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			// check if compound assignment is the only usage of this local
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
			break;
		case Binding.FIELD:
			// check if compound assignment is the only usage of a private field
			reportOnlyUselesslyReadPrivateField(currentScope, (FieldBinding)this.binding, valueRequired);
	}
	this.generateCompoundAssignment(
		currentScope,
		codeStream,
		this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE],
		expression,
		operator,
		assignmentImplicitConversion,
		valueRequired);
}

/*
 * The APIs with an extra argument is used whenever there are two references to the same variable which
 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
 */
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // assigning to a field
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
			if (codegenField.isStatic()) {
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
				} else {
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
				}
			} else {
				if ((this.bits & ASTNode.DepthMASK) != 0) {
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
				} else {
					codeStream.aload_0();
				}
				codeStream.dup();
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
				} else {
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
				}
			}
			break;
		case Binding.LOCAL : // assigning to a local variable (cannot assign to outer local)
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			// using incr bytecode if possible
			Constant assignConstant;
			switch (localBinding.type.id) {
				case T_JavaLangString :
					codeStream.generateStringConcatenationAppend(currentScope, this, expression);
					if (valueRequired) {
						codeStream.dup();
					}
					codeStream.store(localBinding, false);
					return;
				case T_int :
					assignConstant = expression.constant;
					if (localBinding.resolvedPosition == -1) {
						if (valueRequired) {
							/*
							 * restart code gen because we either:
							 * - need the value
							 * - the constant can have potential side-effect
							 */
							localBinding.useFlag = LocalVariableBinding.USED;
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
						} else if (assignConstant == Constant.NotAConstant) {
							// we only need to generate the value of the expression's constant if it is not a constant expression
							expression.generateCode(currentScope, codeStream, false);
						}
						return;
					}
					if ((assignConstant != Constant.NotAConstant)
							&& (assignConstant.typeID() != TypeIds.T_float) // only for integral types
							&& (assignConstant.typeID() != TypeIds.T_double)) { // TODO (philippe) is this test needed ?
						switch (operator) {
							case PLUS :
								int increment  = assignConstant.intValue();
								if (increment != (short) increment) break; // not representable as a 16-bits value
								codeStream.iinc(localBinding.resolvedPosition, increment);
								if (valueRequired) {
									codeStream.load(localBinding);
								}
								return;
							case MINUS :
								increment  = -assignConstant.intValue();
								if (increment != (short) increment) break; // not representable as a 16-bits value
								codeStream.iinc(localBinding.resolvedPosition, increment);
								if (valueRequired) {
									codeStream.load(localBinding);
								}
								return;
						}
					}
					//$FALL-THROUGH$
				default :
					if (localBinding.resolvedPosition == -1) {
						assignConstant = expression.constant;
						if (valueRequired) {
							/*
							 * restart code gen because we either:
							 * - need the value
							 * - the constant can have potential side-effect
							 */
							localBinding.useFlag = LocalVariableBinding.USED;
							throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
						} else if (assignConstant == Constant.NotAConstant) {
							// we only need to generate the value of the expression's constant if it is not a constant expression
							expression.generateCode(currentScope, codeStream, false);
						}
						return;
					}
					codeStream.load(localBinding);
			}
	}
	// perform the actual compound operation
	int operationTypeID;
	switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
		case T_JavaLangString :
		case T_JavaLangObject :
		case T_undefined :
			// we enter here if the single name reference is a field of type java.lang.String or if the type of the
			// operation is java.lang.Object
			// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
			// no need for generic cast on previous #getfield since using Object string buffer methods.
			break;
		default :
			// promote the array reference to the suitable operation type
			if (this.genericCast != null)
				codeStream.checkcast(this.genericCast);
			codeStream.generateImplicitConversion(this.implicitConversion);
			// generate the increment value (will by itself  be promoted to the operation value)
			if (expression == IntLiteral.One){ // prefix operation
				codeStream.generateConstant(expression.constant, this.implicitConversion);
			} else {
				expression.generateCode(currentScope, codeStream, true);
			}
			// perform the operation
			codeStream.sendOperator(operator, operationTypeID);
			// cast the value back to the array reference type
			codeStream.generateImplicitConversion(assignmentImplicitConversion);
	}
	// store the result back into the variable
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // assigning to a field
			FieldBinding codegenField = ((FieldBinding) this.binding).original();
			fieldStore(currentScope, codeStream, codegenField, writeAccessor, this.actualReceiverType, true /* implicit this*/, valueRequired);
			// no need for generic cast as value got dupped
			return;
		case Binding.LOCAL : // assigning to a local variable
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			if (valueRequired) {
				switch (localBinding.type.id) {
					case TypeIds.T_long :
					case TypeIds.T_double :
						codeStream.dup2();
						break;
					default:
						codeStream.dup();
						break;
				}
			}
			codeStream.store(localBinding, false);
	}
}

@Override
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // assigning to a field
			FieldBinding fieldBinding = (FieldBinding)this.binding;
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
			// check if postIncrement is the only usage of a private field
			reportOnlyUselesslyReadPrivateField(currentScope, fieldBinding, valueRequired);
			FieldBinding codegenField = fieldBinding.original();
			if (codegenField.isStatic()) {
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
					codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenField, constantPoolDeclaringClass);
				} else {
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
				}
			} else {
				if ((this.bits & ASTNode.DepthMASK) != 0) {
					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
				} else {
					codeStream.aload_0();
				}
				codeStream.dup();
				if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) {
					TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, codegenField, this.actualReceiverType, true /* implicit this */);
					codeStream.fieldAccess(Opcodes.OPC_getfield, codegenField, constantPoolDeclaringClass);
				} else {
					codeStream.invoke(Opcodes.OPC_invokestatic, this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */);
				}
			}
			TypeBinding operandType;
			if (this.genericCast != null) {
				codeStream.checkcast(this.genericCast);
				operandType = this.genericCast;
			} else {
				operandType = codegenField.type;
			}
			if (valueRequired) {
				if (codegenField.isStatic()) {
					switch (operandType.id) {
						case TypeIds.T_long :
						case TypeIds.T_double :
							codeStream.dup2();
							break;
						default:
							codeStream.dup();
							break;
					}
				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
					switch (operandType.id) {
						case TypeIds.T_long :
						case TypeIds.T_double :
							codeStream.dup2_x1();
							break;
						default:
							codeStream.dup_x1();
							break;
					}
				}
			}
			codeStream.generateImplicitConversion(this.implicitConversion);
			codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
			codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
			codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
			fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false);
			// no need for generic cast
			return;
		case Binding.LOCAL : // assigning to a local variable
			LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
			// check if postIncrement is the only usage of this local
			Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
			if (localBinding.resolvedPosition == -1) {
				if (valueRequired) {
					// restart code gen
					localBinding.useFlag = LocalVariableBinding.USED;
					throw new AbortMethod(CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE, null);
				}
				return;
			}

			// using incr bytecode if possible
			if (TypeBinding.equalsEquals(localBinding.type, TypeBinding.INT)) {
				if (valueRequired) {
					codeStream.load(localBinding);
				}
				if (postIncrement.operator == OperatorIds.PLUS) {
					codeStream.iinc(localBinding.resolvedPosition, 1);
				} else {
					codeStream.iinc(localBinding.resolvedPosition, -1);
				}
			} else {
				codeStream.load(localBinding);
				if (valueRequired){
					switch (localBinding.type.id) {
						case TypeIds.T_long :
						case TypeIds.T_double :
							codeStream.dup2();
							break;
						default:
							codeStream.dup();
							break;
					}
				}
				codeStream.generateImplicitConversion(this.implicitConversion);
				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
				codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
				codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
				codeStream.store(localBinding, false);
			}
	}
}

public void generateReceiver(CodeStream codeStream) {
	codeStream.aload_0();
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
 */
@Override
public TypeBinding[] genericTypeArguments() {
	return null;
}

@Override
public boolean isEquivalent(Reference reference) {
	char[] otherToken = null;
	if (reference instanceof SingleNameReference) {
		otherToken = ((SingleNameReference) reference).token;
	} else if (reference instanceof FieldReference) {
		// test for comparison "f1" vs. "this.f1":
		FieldReference fr = (FieldReference) reference;
		if (fr.receiver.isThis() && !(fr.receiver instanceof QualifiedThisReference))
			otherToken = fr.token;
	}
	return otherToken != null && CharOperation.equals(this.token, otherToken);
}

/**
 * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference)
 * or thru a cast expression etc...
 */
@Override
public LocalVariableBinding localVariableBinding() {
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // reading a field
			break;
		case Binding.LOCAL : // reading a local variable
			return (LocalVariableBinding) this.binding;
	}
	return null;
}

@Override
public VariableBinding nullAnnotatedVariableBinding(boolean supportTypeAnnotations) {
	switch (this.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // reading a field
		case Binding.LOCAL : // reading a local variable
			if (supportTypeAnnotations
					|| (((VariableBinding)this.binding).tagBits & TagBits.AnnotationNullMASK) != 0)
				return (VariableBinding) this.binding;
	}
	return null;
}

@Override
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
	if ((this.implicitConversion & TypeIds.BOXING) != 0)
		return FlowInfo.NON_NULL;
	LocalVariableBinding local = localVariableBinding();
	if (local != null) {
		return flowInfo.nullStatus(local);
	}
	return super.nullStatus(flowInfo, flowContext);
}

public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
	//If inlinable field, forget the access emulation, the code gen will directly target it
	if (((this.bits & ASTNode.DepthMASK) == 0 && (this.bits & ASTNode.IsCapturedOuterLocal) == 0) || (this.constant != Constant.NotAConstant)) {
		return;
	}
	if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) {
		LocalVariableBinding localVariableBinding = (LocalVariableBinding) this.binding;
		if (localVariableBinding != null) {
			if (localVariableBinding.isUninitializedIn(currentScope)) {
				// local was tagged as uninitialized
				return;
			}
			if ((localVariableBinding.tagBits & TagBits.IsEffectivelyFinal) == 0) {
				// local was tagged as not effectively final
				return;
			}
			switch(localVariableBinding.useFlag) {
				case LocalVariableBinding.FAKE_USED :
				case LocalVariableBinding.USED :
					currentScope.emulateOuterAccess(localVariableBinding);
			}
		}
	}
}

public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0)	return;

	//If inlinable field, forget the access emulation, the code gen will directly target it
	if (this.constant != Constant.NotAConstant)
		return;

	if ((this.bits & Binding.FIELD) != 0) {
		FieldBinding fieldBinding = (FieldBinding) this.binding;
		FieldBinding codegenField = fieldBinding.original();
//{ObjectTeams: references to the enclosing team need accessor, too:
/* orig:
		if (((this.bits & ASTNode.DepthMASK) != 0)
			&& ((codegenField.isPrivate() // private access
					&& !currentScope.enclosingSourceType().isNestmateOf(codegenField.declaringClass) )
				|| (codegenField.isProtected() // implicit protected access
						&& codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) {
			if (this.syntheticAccessors == null)
				this.syntheticAccessors = new MethodBinding[2];
			this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] =
			    ((SourceTypeBinding)currentScope.enclosingSourceType().
					enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess, false /*not super access* /);
  :giro */
		SourceTypeBinding enclosingSourceType = currentScope.enclosingSourceType();
		int depth = getDepthForSynthFieldAccess(fieldBinding, enclosingSourceType);

		if (depth > 0 && !currentScope.enclosingSourceType().isNestmateOf(codegenField.declaringClass)) {
			if (this.syntheticAccessors == null)
				this.syntheticAccessors = new MethodBinding[2];
			// check pre-set accessor (inferred callout-to-field)
			if (this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] != null)
				return;
			this.syntheticAccessors[isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] =
				((SourceTypeBinding)enclosingSourceType.
					enclosingTypeAt(depth)).addSyntheticMethod(fieldBinding, isReadAccess, false/*not super access*/, false/*externalizedReceiver*/);
// SH}
			currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
			return;
		}
	}
}

	/**
 * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
 */
@Override
public TypeBinding postConversionType(Scope scope) {
	TypeBinding convertedType = this.resolvedType;
	if (this.genericCast != null)
		convertedType = this.genericCast;
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
	switch (runtimeType) {
		case T_boolean :
			convertedType = TypeBinding.BOOLEAN;
			break;
		case T_byte :
			convertedType = TypeBinding.BYTE;
			break;
		case T_short :
			convertedType = TypeBinding.SHORT;
			break;
		case T_char :
			convertedType = TypeBinding.CHAR;
			break;
		case T_int :
			convertedType = TypeBinding.INT;
			break;
		case T_float :
			convertedType = TypeBinding.FLOAT;
			break;
		case T_long :
			convertedType = TypeBinding.LONG;
			break;
		case T_double :
			convertedType = TypeBinding.DOUBLE;
			break;
		default :
	}
	if ((this.implicitConversion & TypeIds.BOXING) != 0) {
		convertedType = scope.environment().computeBoxingType(convertedType);
	}
	return convertedType;
}

@Override
public StringBuffer printExpression(int indent, StringBuffer output){
	return output.append(this.token);
}
public TypeBinding reportError(BlockScope scope) {
	//=====error cases=======
	this.constant = Constant.NotAConstant;
	if (this.binding instanceof ProblemFieldBinding) {
		scope.problemReporter().invalidField(this, (FieldBinding) this.binding);
	} else if (this.binding instanceof ProblemReferenceBinding || this.binding instanceof MissingTypeBinding) {
		scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
	} else {
		scope.problemReporter().unresolvableReference(this, this.binding);
	}
	return null;
}

@Override
public TypeBinding resolveType(BlockScope scope) {
//{ObjectTeams: no double resolve (parameter mappings for multiple base methods may share the same AST!)
	if (this.binding != null && this.resolvedType != null)
		return this.resolvedType;
// SH}
	// for code gen, harm the restrictiveFlag

	if (this.actualReceiverType != null) {
		this.binding = scope.getField(this.actualReceiverType, this.token, this);
	} else {
		this.actualReceiverType = scope.enclosingSourceType();
		this.binding = scope.getBinding(this.token, this.bits & ASTNode.RestrictiveFlagMASK, this, true /*resolve*/);
	}
	if (this.binding.isValidBinding()) {
		switch (this.bits & ASTNode.RestrictiveFlagMASK) {
			case Binding.VARIABLE : // =========only variable============
			case Binding.VARIABLE | Binding.TYPE : //====both variable and type============
				if (this.binding instanceof VariableBinding) {
					VariableBinding variable = (VariableBinding) this.binding;
					TypeBinding variableType;
					if (this.binding instanceof LocalVariableBinding) {
						this.bits &= ~ASTNode.RestrictiveFlagMASK;  // clear bits
						this.bits |= Binding.LOCAL;
						((LocalVariableBinding) this.binding).markReferenced();
						if (!variable.isFinal() && (this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
							if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) // for 8, defer till effective finality could be ascertained.
								scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this);
						}
						checkLocalStaticClassVariables(scope, variable);
						variableType = variable.type;
						this.constant = (this.bits & ASTNode.IsStrictlyAssigned) == 0 ? variable.constant(scope) : Constant.NotAConstant;
					} else {
						// a field
						variableType = checkFieldAccess(scope);
					}
					// perform capture conversion if read access
					if (variableType != null) {
//{ObjectTeams: wrap role type:
		                variableType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(variableType, scope, this);
// SH}
						this.resolvedType = variableType = (((this.bits & ASTNode.IsStrictlyAssigned) == 0)
								? variableType.capture(scope, this.sourceStart, this.sourceEnd)
								: variableType);
						if ((variableType.tagBits & TagBits.HasMissingType) != 0) {
							if ((this.bits & Binding.LOCAL) == 0) {
								// only complain if field reference (for local, its type got flagged already)
								scope.problemReporter().invalidType(this, variableType);
							}
							return null;
						}
					}
					return variableType;
				}

				// thus it was a type
				this.bits &= ~ASTNode.RestrictiveFlagMASK;  // clear bits
				this.bits |= Binding.TYPE;
				//$FALL-THROUGH$
			case Binding.TYPE : //========only type==============
				this.constant = Constant.NotAConstant;
				//deprecated test
				TypeBinding type = (TypeBinding)this.binding;
				if (isTypeUseDeprecated(type, scope))
					scope.problemReporter().deprecatedType(type, this);
				type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/);
				return this.resolvedType = type;
		}
	}
//{ObjectTeams: one more chance: inferred use of callout-to-field:
	boolean isSetter = ((this.bits & IsStrictlyAssigned) != 0);
	CalloutMappingDeclaration callout = CalloutImplementor.inferCalloutAccess(scope, null/*receiver*/, this, this.token, isSetter, this.expectedType);
	if (callout != null) {
		if (this.syntheticAccessors == null)
			this.syntheticAccessors = new MethodBinding[2];
		this.syntheticAccessors[isSetter ? FieldReference.WRITE : FieldReference.READ] =
						new SyntheticOTTargetMethod.CalloutToField(callout.roleMethodSpec.resolvedMethod);
		FieldBinding baseField = ((FieldAccessSpec)callout.baseMethodSpec).resolvedField;
		// update resolved information:
		this.binding = baseField;
		this.constant = Constant.NotAConstant;
		this.bits &= ~RestrictiveFlagMASK;
		this.bits |= Binding.FIELD;
		setDepth(baseField.isStatic() ? 1 : 0); // static c-t-f needs to pass the enclosing team
		if (((FieldAccessSpec)callout.baseMethodSpec).isSetter())
			this.resolvedType = callout.roleMethodSpec.resolvedParameters()[0];
		else
			this.resolvedType = callout.roleMethodSpec.resolvedType();
		return this.resolvedType;
	}
// SH}
	// error scenario
	return this.resolvedType = reportError(scope);
}

private void checkLocalStaticClassVariables(BlockScope scope, VariableBinding variable) {
	if (this.actualReceiverType.isStatic() && this.actualReceiverType.isLocalType()) {
		if ((variable.modifiers & ClassFileConstants.AccStatic) == 0 &&
				(this.bits & ASTNode.IsCapturedOuterLocal) != 0) {
			BlockScope declaringScope = ((LocalVariableBinding) this.binding).declaringScope;
			MethodScope declaringMethodScope = declaringScope instanceof MethodScope ? (MethodScope)declaringScope :
				declaringScope.enclosingMethodScope();
			MethodScope currentMethodScope = scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
			ClassScope declaringClassScope = declaringMethodScope != null ? declaringMethodScope.classScope() : null;
			ClassScope currentClassScope = currentMethodScope != null ? currentMethodScope.classScope() : null;
			if (declaringClassScope != currentClassScope)
			scope.problemReporter().recordStaticReferenceToOuterLocalVariable((LocalVariableBinding)variable, this);
		}
	}
}

@Override
public void traverse(ASTVisitor visitor, BlockScope scope) {
	visitor.visit(this, scope);
	visitor.endVisit(this, scope);
}

@Override
public void traverse(ASTVisitor visitor, ClassScope scope) {
	visitor.visit(this, scope);
	visitor.endVisit(this, scope);
}

@Override
public String unboundReferenceErrorName(){
	return new String(this.token);
}

@Override
public char[][] getName() {
	return new char[][] {this.token};
}
}
