<s> 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 { 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 ) { int rightStatus = this . right . nullStatus ( flowInfo ) ; int leftStatus = this . left . nullStatus ( flowInfo ) ; if ( leftStatus == FlowInfo . NON_NULL && rightStatus == FlowInfo . NULL ) { if ( this . left instanceof MessageSend ) { scope . problemReporter ( ) . messageSendRedundantCheckOnNonNull ( ( ( MessageSend ) this . left ) . binding , this . left ) ; } } else if ( leftStatus == FlowInfo . NULL && rightStatus == FlowInfo . NON_NULL ) { if ( this . right instanceof MessageSend ) { scope . problemReporter ( ) . messageSendRedundantCheckOnNonNull ( ( ( MessageSend ) this . right ) . binding , this . right ) ; } } LocalVariableBinding local = this . left . localVariableBinding ( ) ; if ( local != null && ( local . type . tagBits & TagBits . IsBaseType ) == 0 ) { checkVariableComparison ( scope , flowContext , flowInfo , initsWhenTrue , initsWhenFalse , local , rightStatus , this . left ) ; } local = this . right . localVariableBinding ( ) ; if ( local != null && ( local . type . tagBits & TagBits . IsBaseType ) == 0 ) { checkVariableComparison ( scope , flowContext , flowInfo , initsWhenTrue , initsWhenFalse , local , leftStatus , this . right ) ; } } private void checkVariableComparison ( BlockScope scope , FlowContext flowContext , FlowInfo flowInfo , FlowInfo initsWhenTrue , FlowInfo initsWhenFalse , LocalVariableBinding local , int nullStatus , Expression reference ) { 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 ) ; initsWhenFalse . markAsComparedEqualToNonNull ( local ) ; } else { flowContext . recordUsingNullReference ( scope , local , reference , FlowContext . CAN_ONLY_NULL_NON_NULL | FlowContext . IN_COMPARISON_NON_NULL , flowInfo ) ; initsWhenTrue . markAsComparedEqualToNonNull ( local ) ; initsWhenFalse . markAsComparedEqualToNull ( local ) ; } 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 ) ; } else { flowContext . recordUsingNullReference ( scope , local , reference , FlowContext . CAN_ONLY_NULL | FlowContext . IN_COMPARISON_NULL , flowInfo ) ; } break ; } } 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 ( ) ) { result = this . right . analyseCode ( currentScope , flowContext , flowInfo ) ; } else { 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 ( ) ) { result = this . left . analyseCode ( currentScope , flowContext , flowInfo ) ; } else { result = this . left . analyseCode ( currentScope , flowContext , flowInfo ) . asNegatedCondition ( ) ; } } else { result = this . right . analyseCode ( currentScope , flowContext , this . left . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ) . unconditionalInits ( ) ; } } else { if ( ( this . left . constant != Constant . NotAConstant ) && ( this . left . constant . typeID ( ) == T_boolean ) ) { if ( ! this . left . constant . booleanValue ( ) ) { result = this . right . analyseCode ( currentScope , flowContext , flowInfo ) ; } else { 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 ( ) ) { result = this . left . analyseCode ( currentScope , flowContext , flowInfo ) ; } else { result = this . left . analyseCode ( currentScope , flowContext , flowInfo ) . asNegatedCondition ( ) ; } } else { result = this . right . analyseCode ( currentScope , flowContext , this . left . analyseCode ( currentScope , flowContext , flowInfo ) . unconditionalInits ( ) ) . unconditionalInits ( ) ; } } if ( result instanceof UnconditionalFlowInfo && ( result . tagBits & FlowInfo . UNREACHABLE ) == 0 ) { result = FlowInfo . conditional ( result . copy ( ) , result . 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 ; } } 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 ) == T_boolean ) { generateBooleanEqual ( currentScope , codeStream , valueRequired ) ; } else { generateNonBooleanEqual ( currentScope , codeStream , valueRequired ) ; } if ( valueRequired ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } 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 ) == T_boolean ) { generateOptimizedBooleanEqual ( currentScope , codeStream , trueLabel , falseLabel , valueRequired ) ; } else { generateOptimizedNonBooleanEqual ( currentScope , codeStream , trueLabel , falseLabel , valueRequired ) ; } } else { if ( ( this . left . implicitConversion & COMPILE_TYPE_MASK ) == T_boolean ) { generateOptimizedBooleanEqual ( currentScope , codeStream , falseLabel , trueLabel , valueRequired ) ; } else { generateOptimizedNonBooleanEqual ( currentScope , codeStream , falseLabel , trueLabel , valueRequired ) ; } } } public void generateBooleanEqual ( BlockScope currentScope , CodeStream codeStream , boolean valueRequired ) { 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 ) { 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 ) { this . left . generateCode ( currentScope , codeStream , false ) ; this . right . generateCode ( currentScope , codeStream , valueRequired ) ; } else { if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; this . left . generateCode ( currentScope , codeStream , false ) ; this . right . generateOptimizedBoolean ( currentScope , codeStream , null , falseLabel , valueRequired ) ; codeStream . iconst_0 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_1 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_1 ( ) ; endLabel . place ( ) ; } } else { this . left . generateCode ( currentScope , codeStream , false ) ; this . right . generateCode ( currentScope , codeStream , false ) ; } } return ; } cst = this . right . optimizedBooleanConstant ( ) ; if ( cst != Constant . NotAConstant ) { if ( cst . booleanValue ( ) == isEqualOperator ) { this . left . generateCode ( currentScope , codeStream , valueRequired ) ; this . right . generateCode ( currentScope , codeStream , false ) ; } else { if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; this . left . generateOptimizedBoolean ( currentScope , codeStream , null , falseLabel , valueRequired ) ; this . right . generateCode ( currentScope , codeStream , false ) ; codeStream . iconst_0 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_1 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_1 ( ) ; endLabel . place ( ) ; } } else { this . left . generateCode ( currentScope , codeStream , false ) ; this . right . generateCode ( currentScope , codeStream , false ) ; } } return ; } 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 ) ) ; codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } else { codeStream . ixor ( ) ; } } } public void generateOptimizedBooleanEqual ( BlockScope currentScope , CodeStream codeStream , BranchLabel trueLabel , BranchLabel falseLabel , boolean valueRequired ) { 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 ; } 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 ; } this . left . generateCode ( currentScope , codeStream , valueRequired ) ; this . right . generateCode ( currentScope , codeStream , valueRequired ) ; int pc = codeStream . position ; if ( valueRequired ) { if ( falseLabel == null ) { if ( trueLabel != null ) { codeStream . if_icmpeq ( trueLabel ) ; } } else { if ( trueLabel == null ) { codeStream . if_icmpne ( falseLabel ) ; } else { } } } codeStream . recordPositionsFrom ( pc , this . sourceEnd ) ; } 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 ) { this . right . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; if ( isEqualOperator ) { codeStream . ifne ( falseLabel ) ; } else { codeStream . ifeq ( falseLabel ) ; } codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } return ; } if ( ( cst = this . right . constant ) != Constant . NotAConstant && cst . intValue ( ) == 0 ) { this . left . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; if ( isEqualOperator ) { codeStream . ifne ( falseLabel ) ; } else { codeStream . ifeq ( falseLabel ) ; } codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } return ; } } if ( this . right instanceof NullLiteral ) { if ( this . left instanceof NullLiteral ) { if ( valueRequired ) { if ( isEqualOperator ) { codeStream . iconst_1 ( ) ; } else { codeStream . iconst_0 ( ) ; } } } else { this . left . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; if ( isEqualOperator ) { codeStream . ifnonnull ( falseLabel ) ; } else { codeStream . ifnull ( falseLabel ) ; } codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } } return ; } else if ( this . left instanceof NullLiteral ) { this . right . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { BranchLabel falseLabel = new BranchLabel ( codeStream ) ; if ( isEqualOperator ) { codeStream . ifnonnull ( falseLabel ) ; } else { codeStream . ifnull ( falseLabel ) ; } codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } return ; } 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 ) { 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 ) { 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 ) ; } } codeStream . iconst_1 ( ) ; if ( ( this . bits & IsReturnedValue ) != 0 ) { codeStream . generateImplicitConversion ( this . implicitConversion ) ; codeStream . generateReturnBytecode ( this ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; } else { BranchLabel endLabel = new BranchLabel ( codeStream ) ; codeStream . goto_ ( endLabel ) ; codeStream . decrStackSize ( 1 ) ; falseLabel . place ( ) ; codeStream . iconst_0 ( ) ; endLabel . place ( ) ; } } } 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 ) { 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 ) { codeStream . ifeq ( trueLabel ) ; } } else { if ( trueLabel == null ) { codeStream . ifne ( falseLabel ) ; } else { } } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; return ; } } if ( ( inline = this . left . constant ) != Constant . NotAConstant ) { 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 ) { codeStream . ifeq ( trueLabel ) ; } } else { if ( trueLabel == null ) { codeStream . ifne ( falseLabel ) ; } else { } } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; return ; } } if ( this . right instanceof NullLiteral ) { if ( this . left instanceof NullLiteral ) { if ( valueRequired ) { if ( falseLabel == null ) { if ( trueLabel != null ) { codeStream . goto_ ( trueLabel ) ; } } } } else { this . left . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { if ( falseLabel == null ) { if ( trueLabel != null ) { codeStream . ifnull ( trueLabel ) ; } } else { if ( trueLabel == null ) { codeStream . ifnonnull ( falseLabel ) ; } else { } } } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; return ; } else if ( this . left instanceof NullLiteral ) { this . right . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { if ( falseLabel == null ) { if ( trueLabel != null ) { codeStream . ifnull ( trueLabel ) ; } } else { if ( trueLabel == null ) { codeStream . ifnonnull ( falseLabel ) ; } else { } } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; return ; } this . left . generateCode ( currentScope , codeStream , valueRequired ) ; this . right . generateCode ( currentScope , codeStream , valueRequired ) ; if ( valueRequired ) { if ( falseLabel == null ) { if ( trueLabel != null ) { switch ( ( this . left . implicitConversion & IMPLICIT_CONVERSION_MASK ) >> 4 ) { 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 { if ( trueLabel == null ) { switch ( ( this . left . implicitConversion & IMPLICIT_CONVERSION_MASK ) >> 4 ) { 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 { } } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } public boolean isCompactableOperation ( ) { return false ; } public TypeBinding resolveType ( BlockScope scope ) { boolean leftIsCast , rightIsCast ; if ( ( leftIsCast = this . left instanceof CastExpression ) == true ) this . left . bits |= DisableUnnecessaryCastCheck ; TypeBinding originalLeftType = this . left . resolveType ( scope ) ; if ( ( rightIsCast = this . right instanceof CastExpression ) == true ) this . right . bits |= DisableUnnecessaryCastCheck ; TypeBinding originalRightType = this . right . resolveType ( scope ) ; if ( originalLeftType == null || originalRightType == null ) { this . constant = Constant . NotAConstant ; return null ; } boolean use15specifics = scope . 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 ) ; } } } if ( leftType . isBaseType ( ) && rightType . isBaseType ( ) ) { int leftTypeID = leftType . id ; int rightTypeID = rightType . id ; 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 ; } if ( leftIsCast || rightIsCast ) { CastExpression . checkNeedForArgumentCasts ( scope , EQUAL_EQUAL , operatorSignature , this . left , leftType . id , leftIsCast , this . right , rightType . id , rightIsCast ) ; } computeConstant ( leftType , rightType ) ; 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 ) ) ) scope . problemReporter ( ) . comparingIdenticalExpressions ( this ) ; } else if ( this . constant != Constant . NotAConstant ) { 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 ; } if ( ( ! leftType . isBaseType ( ) || leftType == TypeBinding . NULL ) && ( ! rightType . isBaseType ( ) || rightType == TypeBinding . NULL ) && ( checkCastTypesCompatibility ( scope , leftType , rightType , null ) || checkCastTypesCompatibility ( scope , rightType , leftType , null ) ) ) { 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 ) ; 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 ; 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 ) ; } } 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 ; } 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 ) ; } } </s>