/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     Stephan Herrmann - Contributions for
 *								bug 186342 - [compiler][null] Using annotations for null checking
 *								bug 331649 - [compiler][null] consider null annotations for fields
 *								bug 383368 - [compiler][null] syntactic null analysis for field references
 *								bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
 *								bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;

public class EqualExpression extends BinaryExpression {

//{ObjectTeams:
	public boolean isGenerated;
	@Override
	public boolean isGenerated() {
		return this.isGenerated;
	}
//SH}

	public EqualExpression(Expression left, Expression right,int operator) {
		super(left,right,operator);
	}
	private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) {

		// collect null status of child nodes:
		int rightStatus = this.right.nullStatus(flowInfo, flowContext);
		int leftStatus = this.left.nullStatus(flowInfo, flowContext);

		boolean leftNonNullChecked = false;
		boolean rightNonNullChecked = false;

		// check if either is a non-local expression known to be nonnull and compared to null, candidates are
		// - method/field annotated @NonNull
		// - allocation expression, some literals, this reference (see inside expressionNonNullComparison(..))
		// these checks do not leverage the flowInfo.
		boolean checkEquality = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
		if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING_MASK) == 0) {
			if (leftStatus == FlowInfo.NON_NULL && rightStatus == FlowInfo.NULL) {
				leftNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.left, checkEquality);
			} else if (leftStatus == FlowInfo.NULL && rightStatus == FlowInfo.NON_NULL) {
				rightNonNullChecked = scope.problemReporter().expressionNonNullComparison(this.right, checkEquality);
			}
		}
		
		boolean contextualCheckEquality = checkEquality ^ ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) != 0);
		// perform flowInfo-based checks for variables and record info for syntactic null analysis for fields:
		if (!leftNonNullChecked) {
			LocalVariableBinding local = this.left.localVariableBinding();
			if (local != null) {
				if ((local.type.tagBits & TagBits.IsBaseType) == 0) {
					checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, rightStatus, this.left);
				}
			} else if (this.left instanceof Reference
							&& ((!contextualCheckEquality && rightStatus == FlowInfo.NULL) 
									|| (contextualCheckEquality && rightStatus == FlowInfo.NON_NULL))
							&& scope.compilerOptions().enableSyntacticNullAnalysisForFields)
			{
				FieldBinding field = ((Reference)this.left).lastFieldBinding();
				if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) {
					flowContext.recordNullCheckedFieldReference((Reference) this.left, 1);
				}
			}
		}
		if (!rightNonNullChecked) {
			LocalVariableBinding local = this.right.localVariableBinding();
			if (local != null) { 
				if ((local.type.tagBits & TagBits.IsBaseType) == 0) {
					checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, leftStatus, this.right);
				}
			} else if (this.right instanceof Reference
							&& ((!contextualCheckEquality && leftStatus == FlowInfo.NULL) 
									|| (contextualCheckEquality && leftStatus == FlowInfo.NON_NULL))
							&& scope.compilerOptions().enableSyntacticNullAnalysisForFields) 
			{
				FieldBinding field = ((Reference)this.right).lastFieldBinding();
				if (field != null && (field.type.tagBits & TagBits.IsBaseType) == 0) {
					flowContext.recordNullCheckedFieldReference((Reference) this.right, 1);
				}				
			}
		}

		// handle reachability:
		if (leftNonNullChecked || rightNonNullChecked) {
			// above checks have not propagated unreachable into the corresponding branch, do it now:
			if (checkEquality) {
				initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
			} else {
				initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
			}
		}
	}
//{ObjectTeams: make overridable:
/* orig:
 	private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
  :giro */
	protected void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) {
// SH}
		switch (nullStatus) {
			case FlowInfo.NULL :
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
					flowContext.recordUsingNullReference(scope, local, reference,
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
					initsWhenTrue.markAsComparedEqualToNull(local); // from thereon it is set
					initsWhenFalse.markAsComparedEqualToNonNull(local); // from thereon it is set
				} else {
					flowContext.recordUsingNullReference(scope, local, reference,
							FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
					initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set
					initsWhenFalse.markAsComparedEqualToNull(local); // from thereon it is set
				}
				break;
			case FlowInfo.NON_NULL :
				if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
					flowContext.recordUsingNullReference(scope, local, reference,
							FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo);
					initsWhenTrue.markAsComparedEqualToNonNull(local); // from thereon it is set
				} else {
					flowContext.recordUsingNullReference(scope, local, reference,
							FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo);
				}
				break;
		}
		// we do not impact enclosing try context because this kind of protection
		// does not preclude the variable from being null in an enclosing scope
	}
	private void analyzeLocalVariable(Expression exp, FlowInfo flowInfo) {
		if (exp instanceof SingleNameReference && (exp.bits & Binding.LOCAL) != 0 ) {
			LocalVariableBinding localBinding = (LocalVariableBinding) ((SingleNameReference ) exp).binding;
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
				localBinding.useFlag = LocalVariableBinding.USED;
			} else if (localBinding.useFlag == LocalVariableBinding.UNUSED ) {
				localBinding.useFlag = LocalVariableBinding.FAKE_USED;
			}
	}
	}
	@Override
	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
		FlowInfo result;
		if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
			if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == T_boolean)) {
				if (this.left.constant.booleanValue()) { //  true == anything
					//  this is equivalent to the right argument inits
					result = this.right.analyseCode(currentScope, flowContext, flowInfo);
				} else { // false == anything
					//  this is equivalent to the right argument inits negated
					result = this.right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
					analyzeLocalVariable(this.left, flowInfo);
				}
			}
			else if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == T_boolean)) {
				if (this.right.constant.booleanValue()) { //  anything == true
					//  this is equivalent to the left argument inits
					result = this.left.analyseCode(currentScope, flowContext, flowInfo);
				} else { // anything == false
					//  this is equivalent to the right argument inits negated
					result = this.left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
					analyzeLocalVariable(this.right, flowInfo);
				}
			}
			else {
				result = this.right.analyseCode(
					currentScope, flowContext,
					this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
			}
		} else { //NOT_EQUAL :
			if ((this.left.constant != Constant.NotAConstant) && (this.left.constant.typeID() == T_boolean)) {
				if (!this.left.constant.booleanValue()) { //  false != anything
					//  this is equivalent to the right argument inits
					result = this.right.analyseCode(currentScope, flowContext, flowInfo);
					analyzeLocalVariable(this.left, flowInfo);
				} else { // true != anything
					//  this is equivalent to the right argument inits negated
					result = this.right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
				}
			}
			else if ((this.right.constant != Constant.NotAConstant) && (this.right.constant.typeID() == T_boolean)) {
				if (!this.right.constant.booleanValue()) { //  anything != false
					//  this is equivalent to the right argument inits
					result = this.left.analyseCode(currentScope, flowContext, flowInfo);
					analyzeLocalVariable(this.right, flowInfo);
				} else { // anything != true
					//  this is equivalent to the right argument inits negated
					result = this.left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
				}
			}
			else {
				result = this.right.analyseCode(
					currentScope, flowContext,
					this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).
					/* unneeded since we flatten it: asNegatedCondition(). */
					unconditionalInits();
			}
		}
		if (result instanceof UnconditionalFlowInfo &&
				(result.tagBits & FlowInfo.UNREACHABLE) == 0) { // the flow info is flat
			result = FlowInfo.conditional(result.copy(), result.copy());
			// TODO (maxime) check, reintroduced copy
		}
		checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse());
		return result;
	}

	public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
		if ((this.left.constant != Constant.NotAConstant) && (this.right.constant != Constant.NotAConstant)) {
			this.constant =
				Constant.computeConstantOperationEQUAL_EQUAL(
					this.left.constant,
					leftType.id,
					this.right.constant,
					rightType.id);
			if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
				this.constant = BooleanConstant.fromValue(!this.constant.booleanValue());
		} else {
			this.constant = Constant.NotAConstant;
			// no optimization for null == null
		}
	}
	/**
	 * Normal == or != code generation.
	 *
	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
	 * @param valueRequired boolean
	 */
	@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;
		}

		if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
			generateBooleanEqual(currentScope, codeStream, valueRequired);
		} else {
			generateNonBooleanEqual(currentScope, codeStream, valueRequired);
		}
		if (valueRequired) {
			codeStream.generateImplicitConversion(this.implicitConversion);
		}
		codeStream.recordPositionsFrom(pc, this.sourceStart);
	}
	/**
	 * Boolean operator code generation
	 *	Optimized operations are: == and !=
	 */
	@Override
	public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) {

		if (this.constant != Constant.NotAConstant) {
			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
			return;
		}
		if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
			if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
				generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
			} else {
				generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
			}
		} else {
			if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
				generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
			} else {
				generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
			}
		}
	}

	/**
	 * Boolean generation for == with boolean operands
	 *
	 * Note this code does not optimize conditional constants !!!!
	 */
	public void generateBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

		// optimized cases: <something equivalent to true> == x, <something equivalent to false> == x,
		// optimized cases: <something equivalent to false> != x, <something equivalent to true> != x,
		boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
		Constant cst = this.left.optimizedBooleanConstant();
		if (cst != Constant.NotAConstant) {
			Constant rightCst = this.right.optimizedBooleanConstant();
			if (rightCst != Constant.NotAConstant) {
				// <something equivalent to true> == <something equivalent to true>, <something equivalent to false> != <something equivalent to true>
				// <something equivalent to true> == <something equivalent to false>, <something equivalent to false> != <something equivalent to false>
				this.left.generateCode(currentScope, codeStream, false);
				this.right.generateCode(currentScope, codeStream, false);
				if (valueRequired) {
					boolean leftBool = cst.booleanValue();
					boolean rightBool = rightCst.booleanValue();
					if (isEqualOperator) {
						if (leftBool == rightBool) {
							codeStream.iconst_1();
						} else {
							codeStream.iconst_0();
						}
					} else {
						if (leftBool != rightBool) {
							codeStream.iconst_1();
						} else {
							codeStream.iconst_0();
						}
					}
				}
			} else if (cst.booleanValue() == isEqualOperator) {
				// <something equivalent to true> == x, <something equivalent to false> != x
				this.left.generateCode(currentScope, codeStream, false);
				this.right.generateCode(currentScope, codeStream, valueRequired);
			} else {
				// <something equivalent to false> == x, <something equivalent to true> != x
				if (valueRequired) {
					BranchLabel falseLabel = new BranchLabel(codeStream);
					this.left.generateCode(currentScope, codeStream, false);
					this.right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
					// comparison is TRUE
					codeStream.iconst_0();
					if ((this.bits & IsReturnedValue) != 0){
						codeStream.generateImplicitConversion(this.implicitConversion);
						codeStream.generateReturnBytecode(this);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_1();
					} else {
						BranchLabel endLabel = new BranchLabel(codeStream);
						codeStream.goto_(endLabel);
						codeStream.decrStackSize(1);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_1();
						endLabel.place();
					}
				} else {
					this.left.generateCode(currentScope, codeStream, false);
					this.right.generateCode(currentScope, codeStream, false);
				}
//				left.generateCode(currentScope, codeStream, false);
//				right.generateCode(currentScope, codeStream, valueRequired);
//				if (valueRequired) {
//					codeStream.iconst_1();
//					codeStream.ixor(); // negate
//				}
			}
			return;
		}
		cst = this.right.optimizedBooleanConstant();
		if (cst != Constant.NotAConstant) {
			if (cst.booleanValue() == isEqualOperator) {
				// x == <something equivalent to true>, x != <something equivalent to false>
				this.left.generateCode(currentScope, codeStream, valueRequired);
				this.right.generateCode(currentScope, codeStream, false);
			} else {
				// x == <something equivalent to false>, x != <something equivalent to true>
				if (valueRequired) {
					BranchLabel falseLabel = new BranchLabel(codeStream);
					this.left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
					this.right.generateCode(currentScope, codeStream, false);
					// comparison is TRUE
					codeStream.iconst_0();
					if ((this.bits & IsReturnedValue) != 0){
						codeStream.generateImplicitConversion(this.implicitConversion);
						codeStream.generateReturnBytecode(this);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_1();
					} else {
						BranchLabel endLabel = new BranchLabel(codeStream);
						codeStream.goto_(endLabel);
						codeStream.decrStackSize(1);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_1();
						endLabel.place();
					}
				} else {
					this.left.generateCode(currentScope, codeStream, false);
					this.right.generateCode(currentScope, codeStream, false);
				}
//				left.generateCode(currentScope, codeStream, valueRequired);
//				right.generateCode(currentScope, codeStream, false);
//				if (valueRequired) {
//					codeStream.iconst_1();
//					codeStream.ixor(); // negate
//				}
			}
			return;
		}
		// default case
		this.left.generateCode(currentScope, codeStream, valueRequired);
		this.right.generateCode(currentScope, codeStream, valueRequired);

		if (valueRequired) {
			if (isEqualOperator) {
				BranchLabel falseLabel;
				codeStream.if_icmpne(falseLabel = new BranchLabel(codeStream));
				// comparison is TRUE
				codeStream.iconst_1();
				if ((this.bits & IsReturnedValue) != 0){
					codeStream.generateImplicitConversion(this.implicitConversion);
					codeStream.generateReturnBytecode(this);
					// comparison is FALSE
					falseLabel.place();
					codeStream.iconst_0();
				} else {
					BranchLabel endLabel = new BranchLabel(codeStream);
					codeStream.goto_(endLabel);
					codeStream.decrStackSize(1);
					// comparison is FALSE
					falseLabel.place();
					codeStream.iconst_0();
					endLabel.place();
				}
			} else {
				codeStream.ixor();
			}
		}
	}

	/**
	 * Boolean generation for == with boolean operands
	 *
	 * Note this code does not optimize conditional constants !!!!
	 */
	public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) {

		// optimized cases: true == x, false == x
		if (this.left.constant != Constant.NotAConstant) {
			boolean inline = this.left.constant.booleanValue();
			this.right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
			return;
		} // optimized cases: x == true, x == false
		if (this.right.constant != Constant.NotAConstant) {
			boolean inline = this.right.constant.booleanValue();
			this.left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
			return;
		}
		// default case
		this.left.generateCode(currentScope, codeStream, valueRequired);
		this.right.generateCode(currentScope, codeStream, valueRequired);
		int pc = codeStream.position;
		if (valueRequired) {
			if (falseLabel == null) {
				if (trueLabel != null) {
					// implicit falling through the FALSE case
					codeStream.if_icmpeq(trueLabel);
				}
			} else {
				// implicit falling through the TRUE case
				if (trueLabel == null) {
					codeStream.if_icmpne(falseLabel);
				} else {
					// no implicit fall through TRUE/FALSE --> should never occur
				}
			}
		}
		codeStream.recordPositionsFrom(pc, this.sourceEnd);
	}
	/**
	 * Boolean generation for == with non-boolean operands
	 *
	 */
	public void generateNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

		boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
		if (((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) {
			Constant cst;
			if ((cst = this.left.constant) != Constant.NotAConstant && cst.intValue() == 0) {
				// optimized case: 0 == x, 0 != x
				this.right.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					BranchLabel falseLabel = new BranchLabel(codeStream);
					if (isEqualOperator) {
						codeStream.ifne(falseLabel);
					} else {
						codeStream.ifeq(falseLabel);
					}
					// comparison is TRUE
					codeStream.iconst_1();
					if ((this.bits & IsReturnedValue) != 0){
						codeStream.generateImplicitConversion(this.implicitConversion);
						codeStream.generateReturnBytecode(this);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
					} else {
						BranchLabel endLabel = new BranchLabel(codeStream);
						codeStream.goto_(endLabel);
						codeStream.decrStackSize(1);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
						endLabel.place();
					}
				}
				return;
			}
			if ((cst = this.right.constant) != Constant.NotAConstant && cst.intValue() == 0) {
				// optimized case: x == 0, x != 0
				this.left.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					BranchLabel falseLabel = new BranchLabel(codeStream);
					if (isEqualOperator) {
						codeStream.ifne(falseLabel);
					} else {
						codeStream.ifeq(falseLabel);
					}
					// comparison is TRUE
					codeStream.iconst_1();
					if ((this.bits & IsReturnedValue) != 0){
						codeStream.generateImplicitConversion(this.implicitConversion);
						codeStream.generateReturnBytecode(this);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
					} else {
						BranchLabel endLabel = new BranchLabel(codeStream);
						codeStream.goto_(endLabel);
						codeStream.decrStackSize(1);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
						endLabel.place();
					}
				}
				return;
			}
		}

		// null cases
		if (this.right instanceof NullLiteral) {
			if (this.left instanceof NullLiteral) {
				// null == null, null != null
				if (valueRequired) {
					if (isEqualOperator) {
						codeStream.iconst_1();
					} else {
						codeStream.iconst_0();
					}
				}
			} else {
				// x == null, x != null
				this.left.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					BranchLabel falseLabel = new BranchLabel(codeStream);
					if (isEqualOperator) {
						codeStream.ifnonnull(falseLabel);
					} else {
						codeStream.ifnull(falseLabel);
					}
					// comparison is TRUE
					codeStream.iconst_1();
					if ((this.bits & IsReturnedValue) != 0){
						codeStream.generateImplicitConversion(this.implicitConversion);
						codeStream.generateReturnBytecode(this);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
					} else {
						BranchLabel endLabel = new BranchLabel(codeStream);
						codeStream.goto_(endLabel);
						codeStream.decrStackSize(1);
						// comparison is FALSE
						falseLabel.place();
						codeStream.iconst_0();
						endLabel.place();
					}
				}
			}
			return;
		} else if (this.left instanceof NullLiteral) {
			// null = x, null != x
			this.right.generateCode(currentScope, codeStream, valueRequired);
			if (valueRequired) {
				BranchLabel falseLabel = new BranchLabel(codeStream);
				if (isEqualOperator) {
					codeStream.ifnonnull(falseLabel);
				} else {
					codeStream.ifnull(falseLabel);
				}
				// comparison is TRUE
				codeStream.iconst_1();
				if ((this.bits & IsReturnedValue) != 0){
					codeStream.generateImplicitConversion(this.implicitConversion);
					codeStream.generateReturnBytecode(this);
					// comparison is FALSE
					falseLabel.place();
					codeStream.iconst_0();
				} else {
					BranchLabel endLabel = new BranchLabel(codeStream);
					codeStream.goto_(endLabel);
					codeStream.decrStackSize(1);
					// comparison is FALSE
					falseLabel.place();
					codeStream.iconst_0();
					endLabel.place();
				}
			}
			return;
		}

		// default case
		this.left.generateCode(currentScope, codeStream, valueRequired);
		this.right.generateCode(currentScope, codeStream, valueRequired);
		if (valueRequired) {
			BranchLabel falseLabel = new BranchLabel(codeStream);
			if (isEqualOperator) {
				switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
					case T_int :
						codeStream.if_icmpne(falseLabel);
						break;
					case T_float :
						codeStream.fcmpl();
						codeStream.ifne(falseLabel);
						break;
					case T_long :
						codeStream.lcmp();
						codeStream.ifne(falseLabel);
						break;
					case T_double :
						codeStream.dcmpl();
						codeStream.ifne(falseLabel);
						break;
					default :
						codeStream.if_acmpne(falseLabel);
				}
			} else {
				switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
					case T_int :
						codeStream.if_icmpeq(falseLabel);
						break;
					case T_float :
						codeStream.fcmpl();
						codeStream.ifeq(falseLabel);
						break;
					case T_long :
						codeStream.lcmp();
						codeStream.ifeq(falseLabel);
						break;
					case T_double :
						codeStream.dcmpl();
						codeStream.ifeq(falseLabel);
						break;
					default :
						codeStream.if_acmpeq(falseLabel);
				}
			}
			// comparison is TRUE
			codeStream.iconst_1();
			if ((this.bits & IsReturnedValue) != 0){
				codeStream.generateImplicitConversion(this.implicitConversion);
				codeStream.generateReturnBytecode(this);
				// comparison is FALSE
				falseLabel.place();
				codeStream.iconst_0();
			} else {
				BranchLabel endLabel = new BranchLabel(codeStream);
				codeStream.goto_(endLabel);
				codeStream.decrStackSize(1);
				// comparison is FALSE
				falseLabel.place();
				codeStream.iconst_0();
				endLabel.place();
			}
		}
	}

	/**
	 * Boolean generation for == with non-boolean operands
	 *
	 */
	public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) {

		int pc = codeStream.position;
		Constant inline;
		if ((inline = this.right.constant) != Constant.NotAConstant) {
			// optimized case: x == 0
			if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) {
				this.left.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					if (falseLabel == null) {
						if (trueLabel != null) {
							// implicit falling through the FALSE case
							codeStream.ifeq(trueLabel);
						}
					} else {
						// implicit falling through the TRUE case
						if (trueLabel == null) {
							codeStream.ifne(falseLabel);
						} else {
							// no implicit fall through TRUE/FALSE --> should never occur
						}
					}
				}
				codeStream.recordPositionsFrom(pc, this.sourceStart);
				return;
			}
		}
		if ((inline = this.left.constant) != Constant.NotAConstant) {
			// optimized case: 0 == x
			if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
				&& (inline.intValue() == 0)) {
				this.right.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					if (falseLabel == null) {
						if (trueLabel != null) {
							// implicit falling through the FALSE case
							codeStream.ifeq(trueLabel);
						}
					} else {
						// implicit falling through the TRUE case
						if (trueLabel == null) {
							codeStream.ifne(falseLabel);
						} else {
							// no implicit fall through TRUE/FALSE --> should never occur
						}
					}
				}
				codeStream.recordPositionsFrom(pc, this.sourceStart);
				return;
			}
		}
		// null cases
		// optimized case: x == null
		if (this.right instanceof NullLiteral) {
			if (this.left instanceof NullLiteral) {
				// null == null
				if (valueRequired) {
					if (falseLabel == null) {
						// implicit falling through the FALSE case
						if (trueLabel != null) {
							codeStream.goto_(trueLabel);
						}
					}
				}
			} else {
				this.left.generateCode(currentScope, codeStream, valueRequired);
				if (valueRequired) {
					if (falseLabel == null) {
						if (trueLabel != null) {
							// implicit falling through the FALSE case
							codeStream.ifnull(trueLabel);
						}
					} else {
						// implicit falling through the TRUE case
						if (trueLabel == null) {
							codeStream.ifnonnull(falseLabel);
						} else {
							// no implicit fall through TRUE/FALSE --> should never occur
						}
					}
				}
			}
			codeStream.recordPositionsFrom(pc, this.sourceStart);
			return;
		} else if (this.left instanceof NullLiteral) { // optimized case: null == x
			this.right.generateCode(currentScope, codeStream, valueRequired);
			if (valueRequired) {
				if (falseLabel == null) {
					if (trueLabel != null) {
						// implicit falling through the FALSE case
						codeStream.ifnull(trueLabel);
					}
				} else {
					// implicit falling through the TRUE case
					if (trueLabel == null) {
						codeStream.ifnonnull(falseLabel);
					} else {
						// no implicit fall through TRUE/FALSE --> should never occur
					}
				}
			}
			codeStream.recordPositionsFrom(pc, this.sourceStart);
			return;
		}

		// default case
		this.left.generateCode(currentScope, codeStream, valueRequired);
		this.right.generateCode(currentScope, codeStream, valueRequired);
		if (valueRequired) {
			if (falseLabel == null) {
				if (trueLabel != null) {
					// implicit falling through the FALSE case
					switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
						case T_int :
							codeStream.if_icmpeq(trueLabel);
							break;
						case T_float :
							codeStream.fcmpl();
							codeStream.ifeq(trueLabel);
							break;
						case T_long :
							codeStream.lcmp();
							codeStream.ifeq(trueLabel);
							break;
						case T_double :
							codeStream.dcmpl();
							codeStream.ifeq(trueLabel);
							break;
						default :
							codeStream.if_acmpeq(trueLabel);
					}
				}
			} else {
				// implicit falling through the TRUE case
				if (trueLabel == null) {
					switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
						case T_int :
							codeStream.if_icmpne(falseLabel);
							break;
						case T_float :
							codeStream.fcmpl();
							codeStream.ifne(falseLabel);
							break;
						case T_long :
							codeStream.lcmp();
							codeStream.ifne(falseLabel);
							break;
						case T_double :
							codeStream.dcmpl();
							codeStream.ifne(falseLabel);
							break;
						default :
							codeStream.if_acmpne(falseLabel);
					}
				} else {
					// no implicit fall through TRUE/FALSE --> should never occur
				}
			}
		}
		codeStream.recordPositionsFrom(pc, this.sourceStart);
	}
	@Override
	public boolean isCompactableOperation() {
		return false;
	}
	@Override
	public TypeBinding resolveType(BlockScope scope) {

			boolean leftIsCast, rightIsCast;
			if ((leftIsCast = this.left instanceof CastExpression) == true) this.left.bits |= DisableUnnecessaryCastCheck; // will check later on
			TypeBinding originalLeftType = this.left.resolveType(scope);

			if ((rightIsCast = this.right instanceof CastExpression) == true) this.right.bits |= DisableUnnecessaryCastCheck; // will check later on
			TypeBinding originalRightType = this.right.resolveType(scope);

		// always return BooleanBinding
		if (originalLeftType == null || originalRightType == null){
			this.constant = Constant.NotAConstant;
			return null;
		}

		final CompilerOptions compilerOptions = scope.compilerOptions();
		if (compilerOptions.complainOnUninternedIdentityComparison && originalRightType.hasTypeBit(TypeIds.BitUninternedType) && originalLeftType.hasTypeBit(TypeIds.BitUninternedType))
			scope.problemReporter().uninternedIdentityComparison(this, originalLeftType, originalRightType, scope.referenceCompilationUnit());

		// autoboxing support
		boolean use15specifics = compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5;
		TypeBinding leftType = originalLeftType, rightType = originalRightType;
		if (use15specifics) {
			if (leftType != TypeBinding.NULL && leftType.isBaseType()) {
				if (!rightType.isBaseType()) {
					rightType = scope.environment().computeBoxingType(rightType);
				}
			} else {
				if (rightType != TypeBinding.NULL && rightType.isBaseType()) {
					leftType = scope.environment().computeBoxingType(leftType);
				}
			}
		}
		// both base type
		if (leftType.isBaseType() && rightType.isBaseType()) {
			int leftTypeID = leftType.id;
			int rightTypeID = rightType.id;

			// the code is an int
			// (cast)  left   == (cast)  right --> result
			//  0000   0000       0000   0000      0000
			//  <<16   <<12       <<8    <<4       <<0
			int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftTypeID << 4) + rightTypeID];
			this.left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), originalLeftType);
			this.right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), originalRightType);
			this.bits |= operatorSignature & 0xF;
			if ((operatorSignature & 0x0000F) == T_undefined) {
				this.constant = Constant.NotAConstant;
				scope.problemReporter().invalidOperator(this, leftType, rightType);
				return null;
			}
			// check need for operand cast
			if (leftIsCast || rightIsCast) {
				CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, this.left, leftType.id, leftIsCast, this.right, rightType.id, rightIsCast);
			}
			computeConstant(leftType, rightType);

			// check whether comparing identical expressions
			Binding leftDirect = Expression.getDirectBinding(this.left);
			if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) {
				if (leftTypeID != TypeIds.T_double && leftTypeID != TypeIds.T_float
						&&(!(this.right instanceof Assignment))) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=281776
					scope.problemReporter().comparingIdenticalExpressions(this);
			} else if (this.constant != Constant.NotAConstant) {
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=276740
				int operator = (this.bits & OperatorMASK) >> OperatorSHIFT;
				if ((operator == EQUAL_EQUAL && this.constant == BooleanConstant.fromValue(true))
						|| (operator == NOT_EQUAL && this.constant == BooleanConstant.fromValue(false)))
					scope.problemReporter().comparingIdenticalExpressions(this);
			}
			return this.resolvedType = TypeBinding.BOOLEAN;
		}

		// Object references
		// spec 15.20.3
		if ((!leftType.isBaseType() || leftType == TypeBinding.NULL) // cannot compare: Object == (int)0
				&& (!rightType.isBaseType() || rightType == TypeBinding.NULL)
				&& (checkCastTypesCompatibility(scope, leftType, rightType, null)
						|| checkCastTypesCompatibility(scope, rightType, leftType, null))) {

			// (special case for String)
			if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) {
				computeConstant(leftType, rightType);
			} else {
				this.constant = Constant.NotAConstant;
			}
			TypeBinding objectType = scope.getJavaLangObject();
			this.left.computeConversion(scope, objectType, leftType);
			this.right.computeConversion(scope, objectType, rightType);
			// check need for operand cast
			boolean unnecessaryLeftCast = (this.left.bits & UnnecessaryCast) != 0;
			boolean unnecessaryRightCast = (this.right.bits & UnnecessaryCast) != 0;
			if (unnecessaryLeftCast || unnecessaryRightCast) {
				TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)this.left).expression.resolvedType : leftType;
				TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)this.right).expression.resolvedType : rightType;
				// Bug 543727 - check if either cast is really needed
				if (!isCastNeeded(alternateLeftType, alternateRightType)) {
					if (checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null)
							|| checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) {
						if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)this.left);
						if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)this.right);
					}
				}
			}
			// check whether comparing identical expressions
			Binding leftDirect = Expression.getDirectBinding(this.left);
			if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) {
				if (!(this.right instanceof Assignment)) {
					scope.problemReporter().comparingIdenticalExpressions(this);
				}
			}
			return this.resolvedType = TypeBinding.BOOLEAN;
		}
		this.constant = Constant.NotAConstant;
		scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
		return null;
	}

	private boolean isCastNeeded(TypeBinding leftType, TypeBinding rightType) {
		// Bug 543727 - if either type is parameterized and the other is a base type,
		// a cast is necessary, even if boxing the base type will result in a compatible
		// type.
		if (leftType.isParameterizedType()) {
			return rightType.isBaseType();
		}
		if (rightType.isParameterizedType()) {
			return leftType.isBaseType();
		}
		return false;
	}

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