<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 . codegen . * ; import org . eclipse . jdt . internal . compiler . flow . * ; import org . eclipse . jdt . internal . compiler . lookup . * ; public class IfStatement extends Statement { public Expression condition ; public Statement thenStatement ; public Statement elseStatement ; int thenInitStateIndex = - 1 ; int elseInitStateIndex = - 1 ; int mergedInitStateIndex = - 1 ; public IfStatement ( Expression condition , Statement thenStatement , int sourceStart , int sourceEnd ) { this . condition = condition ; this . thenStatement = thenStatement ; if ( thenStatement instanceof EmptyStatement ) thenStatement . bits |= IsUsefulEmptyStatement ; this . sourceStart = sourceStart ; this . sourceEnd = sourceEnd ; } public IfStatement ( Expression condition , Statement thenStatement , Statement elseStatement , int sourceStart , int sourceEnd ) { this . condition = condition ; this . thenStatement = thenStatement ; if ( thenStatement instanceof EmptyStatement ) thenStatement . bits |= IsUsefulEmptyStatement ; this . elseStatement = elseStatement ; if ( elseStatement instanceof IfStatement ) elseStatement . bits |= IsElseIfStatement ; if ( elseStatement instanceof EmptyStatement ) elseStatement . bits |= IsUsefulEmptyStatement ; this . sourceStart = sourceStart ; this . sourceEnd = sourceEnd ; } public FlowInfo analyseCode ( BlockScope currentScope , FlowContext flowContext , FlowInfo flowInfo ) { FlowInfo conditionFlowInfo = this . condition . analyseCode ( currentScope , flowContext , flowInfo ) ; int initialComplaintLevel = ( flowInfo . reachMode ( ) & FlowInfo . UNREACHABLE ) != 0 ? Statement . COMPLAINED_FAKE_REACHABLE : Statement . NOT_COMPLAINED ; Constant cst = this . condition . optimizedBooleanConstant ( ) ; if ( ( this . condition . implicitConversion & TypeIds . UNBOXING ) != 0 ) { this . condition . checkNPE ( currentScope , flowContext , flowInfo ) ; } boolean isConditionOptimizedTrue = cst != Constant . NotAConstant && cst . booleanValue ( ) == true ; boolean isConditionOptimizedFalse = cst != Constant . NotAConstant && cst . booleanValue ( ) == false ; FlowInfo thenFlowInfo = conditionFlowInfo . safeInitsWhenTrue ( ) ; if ( isConditionOptimizedFalse ) { thenFlowInfo . setReachMode ( FlowInfo . UNREACHABLE_OR_DEAD ) ; } FlowInfo elseFlowInfo = conditionFlowInfo . initsWhenFalse ( ) . copy ( ) ; if ( isConditionOptimizedTrue ) { elseFlowInfo . setReachMode ( FlowInfo . UNREACHABLE_OR_DEAD ) ; } if ( ( ( flowInfo . tagBits & FlowInfo . UNREACHABLE ) == 0 ) && ( ( thenFlowInfo . tagBits & FlowInfo . UNREACHABLE ) != 0 ) ) { this . bits |= ASTNode . IsThenStatementUnreachable ; } else if ( ( ( flowInfo . tagBits & FlowInfo . UNREACHABLE ) == 0 ) && ( ( elseFlowInfo . tagBits & FlowInfo . UNREACHABLE ) != 0 ) ) { this . bits |= ASTNode . IsElseStatementUnreachable ; } boolean reportDeadCodeForKnownPattern = ! isKnowDeadCodePattern ( this . condition ) || currentScope . compilerOptions ( ) . reportDeadCodeInTrivialIfStatement ; if ( this . thenStatement != null ) { this . thenInitStateIndex = currentScope . methodScope ( ) . recordInitializationStates ( thenFlowInfo ) ; if ( isConditionOptimizedFalse || ( ( this . bits & ASTNode . IsThenStatementUnreachable ) != 0 ) ) { if ( reportDeadCodeForKnownPattern ) { this . thenStatement . complainIfUnreachable ( thenFlowInfo , currentScope , initialComplaintLevel , false ) ; } else { this . bits &= ~ ASTNode . IsThenStatementUnreachable ; } } thenFlowInfo = this . thenStatement . analyseCode ( currentScope , flowContext , thenFlowInfo ) ; } if ( ( thenFlowInfo . tagBits & FlowInfo . UNREACHABLE_OR_DEAD ) != 0 ) { this . bits |= ASTNode . ThenExit ; } if ( this . elseStatement != null ) { if ( thenFlowInfo == FlowInfo . DEAD_END && ( this . bits & IsElseIfStatement ) == 0 && ! ( this . elseStatement instanceof IfStatement ) ) { currentScope . problemReporter ( ) . unnecessaryElse ( this . elseStatement ) ; } this . elseInitStateIndex = currentScope . methodScope ( ) . recordInitializationStates ( elseFlowInfo ) ; if ( isConditionOptimizedTrue || ( ( this . bits & ASTNode . IsElseStatementUnreachable ) != 0 ) ) { if ( reportDeadCodeForKnownPattern ) { this . elseStatement . complainIfUnreachable ( elseFlowInfo , currentScope , initialComplaintLevel , false ) ; } else { this . bits &= ~ ASTNode . IsElseStatementUnreachable ; } } elseFlowInfo = this . elseStatement . analyseCode ( currentScope , flowContext , elseFlowInfo ) ; } currentScope . correlateTrackingVarsIfElse ( thenFlowInfo , elseFlowInfo ) ; FlowInfo mergedInfo = FlowInfo . mergedOptimizedBranchesIfElse ( thenFlowInfo , isConditionOptimizedTrue , elseFlowInfo , isConditionOptimizedFalse , true , flowInfo , this , reportDeadCodeForKnownPattern ) ; this . mergedInitStateIndex = currentScope . methodScope ( ) . recordInitializationStates ( mergedInfo ) ; return mergedInfo ; } public void generateCode ( BlockScope currentScope , CodeStream codeStream ) { if ( ( this . bits & IsReachable ) == 0 ) { return ; } int pc = codeStream . position ; BranchLabel endifLabel = new BranchLabel ( codeStream ) ; Constant cst ; boolean hasThenPart = ! ( ( ( cst = this . condition . optimizedBooleanConstant ( ) ) != Constant . NotAConstant && cst . booleanValue ( ) == false ) || this . thenStatement == null || this . thenStatement . isEmptyBlock ( ) ) ; boolean hasElsePart = ! ( ( cst != Constant . NotAConstant && cst . booleanValue ( ) == true ) || this . elseStatement == null || this . elseStatement . isEmptyBlock ( ) ) ; if ( hasThenPart ) { BranchLabel falseLabel = null ; if ( cst != Constant . NotAConstant && cst . booleanValue ( ) == true ) { this . condition . generateCode ( currentScope , codeStream , false ) ; } else { this . condition . generateOptimizedBoolean ( currentScope , codeStream , null , hasElsePart ? ( falseLabel = new BranchLabel ( codeStream ) ) : endifLabel , true ) ; } if ( this . thenInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . thenInitStateIndex ) ; codeStream . addDefinitelyAssignedVariables ( currentScope , this . thenInitStateIndex ) ; } this . thenStatement . generateCode ( currentScope , codeStream ) ; if ( hasElsePart ) { if ( ( this . bits & ASTNode . ThenExit ) == 0 ) { this . thenStatement . branchChainTo ( endifLabel ) ; int position = codeStream . position ; codeStream . goto_ ( endifLabel ) ; codeStream . recordPositionsFrom ( position , this . thenStatement . sourceEnd ) ; } if ( this . elseInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . elseInitStateIndex ) ; codeStream . addDefinitelyAssignedVariables ( currentScope , this . elseInitStateIndex ) ; } if ( falseLabel != null ) falseLabel . place ( ) ; this . elseStatement . generateCode ( currentScope , codeStream ) ; } } else if ( hasElsePart ) { if ( cst != Constant . NotAConstant && cst . booleanValue ( ) == false ) { this . condition . generateCode ( currentScope , codeStream , false ) ; } else { this . condition . generateOptimizedBoolean ( currentScope , codeStream , endifLabel , null , true ) ; } if ( this . elseInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . elseInitStateIndex ) ; codeStream . addDefinitelyAssignedVariables ( currentScope , this . elseInitStateIndex ) ; } this . elseStatement . generateCode ( currentScope , codeStream ) ; } else { this . condition . generateCode ( currentScope , codeStream , false ) ; codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } if ( this . mergedInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . mergedInitStateIndex ) ; codeStream . addDefinitelyAssignedVariables ( currentScope , this . mergedInitStateIndex ) ; } endifLabel . place ( ) ; codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } public StringBuffer printStatement ( int indent , StringBuffer output ) { printIndent ( indent , output ) . append ( "if (" ) ; this . condition . printExpression ( 0 , output ) . append ( ")n" ) ; this . thenStatement . printStatement ( indent + 2 , output ) ; if ( this . elseStatement != null ) { output . append ( '\n' ) ; printIndent ( indent , output ) ; output . append ( "elsen" ) ; this . elseStatement . printStatement ( indent + 2 , output ) ; } return output ; } public void resolve ( BlockScope scope ) { TypeBinding type = this . condition . resolveTypeExpecting ( scope , TypeBinding . BOOLEAN ) ; this . condition . computeConversion ( scope , type , type ) ; if ( this . thenStatement != null ) this . thenStatement . resolve ( scope ) ; if ( this . elseStatement != null ) this . elseStatement . resolve ( scope ) ; } public void traverse ( ASTVisitor visitor , BlockScope blockScope ) { if ( visitor . visit ( this , blockScope ) ) { this . condition . traverse ( visitor , blockScope ) ; if ( this . thenStatement != null ) this . thenStatement . traverse ( visitor , blockScope ) ; if ( this . elseStatement != null ) this . elseStatement . traverse ( visitor , blockScope ) ; } visitor . endVisit ( this , blockScope ) ; } } </s>