+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-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 {
-
- //this class represents the case of only one statement in
- //either else and/or then branches.
-
- public Expression condition;
- public Statement thenStatement;
- public Statement elseStatement;
-
- boolean thenExit;
-
- // for local variables table attributes
- 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;
- // remember useful empty statement
- if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
- this.sourceStart = sourceStart;
- this.sourceEnd = sourceEnd;
- }
-
- public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement, int sourceStart, int sourceEnd) {
-
- this.condition = condition;
- this.thenStatement = thenStatement;
- // remember useful empty statement
- if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
- this.elseStatement = elseStatement;
- if (elseStatement instanceof IfStatement) elseStatement.bits |= IsElseIfStatement;
- this.sourceStart = sourceStart;
- this.sourceEnd = sourceEnd;
- }
-
- public FlowInfo analyseCode(
- BlockScope currentScope,
- FlowContext flowContext,
- FlowInfo flowInfo) {
-
- // process the condition
- flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
-
- Constant cst = this.condition.optimizedBooleanConstant();
- boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
- boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
-
- // process the THEN part
- FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
- if (isConditionOptimizedFalse) {
- thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
- }
- if (this.thenStatement != null) {
- // Save info for code gen
- thenInitStateIndex =
- currentScope.methodScope().recordInitializationStates(thenFlowInfo);
- if (!thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) {
- thenFlowInfo =
- thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
- }
- }
- // code gen: optimizing the jump around the ELSE part
- this.thenExit = !thenFlowInfo.isReachable();
-
- // process the ELSE part
- FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
- if (isConditionOptimizedTrue) {
- elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
- }
- if (this.elseStatement != null) {
- // signal else clause unnecessarily nested, tolerate else-if code pattern
- if (thenFlowInfo == FlowInfo.DEAD_END
- && (this.bits & IsElseIfStatement) == 0 // else of an else-if
- && !(this.elseStatement instanceof IfStatement)) {
- currentScope.problemReporter().unnecessaryElse(this.elseStatement);
- }
- // Save info for code gen
- elseInitStateIndex =
- currentScope.methodScope().recordInitializationStates(elseFlowInfo);
- if (!elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) {
- elseFlowInfo =
- elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
- }
- }
-
- // merge THEN & ELSE initializations
- FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
- thenFlowInfo,
- isConditionOptimizedTrue,
- elseFlowInfo,
- isConditionOptimizedFalse,
- true /*if(true){ return; } fake-reachable(); */);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- }
-
- /**
- * If code generation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- */
- public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
- if ((this.bits & IsReachableMASK) == 0) {
- return;
- }
- int pc = codeStream.position;
- Label endifLabel = new Label(codeStream);
-
- // optimizing the then/else part code gen
- Constant cst;
- boolean hasThenPart =
- !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
- && cst.booleanValue() == false)
- || this.thenStatement == null
- || this.thenStatement.isEmptyBlock());
- boolean hasElsePart =
- !((cst != NotAConstant && cst.booleanValue() == true)
- || this.elseStatement == null
- || this.elseStatement.isEmptyBlock());
-
- if (hasThenPart) {
- Label falseLabel;
- // generate boolean condition
- this.condition.generateOptimizedBoolean(
- currentScope,
- codeStream,
- null,
- (falseLabel = new Label(codeStream)),
- true);
- // May loose some local variable initializations : affecting the local variable attributes
- if (thenInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- thenInitStateIndex);
- codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
- }
- // generate then statement
- this.thenStatement.generateCode(currentScope, codeStream);
- // jump around the else statement
- if (hasElsePart && !thenExit) {
- this.thenStatement.branchChainTo(endifLabel);
- int position = codeStream.position;
- codeStream.goto_(endifLabel);
- codeStream.updateLastRecordedEndPC(position);
- //goto is tagged as part of the thenAction block
- }
- falseLabel.place();
- } else {
- if (hasElsePart) {
- // generate boolean condition
- this.condition.generateOptimizedBoolean(
- currentScope,
- codeStream,
- endifLabel,
- null,
- true);
- } else {
- // generate condition side-effects
- this.condition.generateCode(currentScope, codeStream, false);
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- }
- }
- // generate else statement
- if (hasElsePart) {
- // May loose some local variable initializations : affecting the local variable attributes
- if (elseInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- elseInitStateIndex);
- codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
- }
- this.elseStatement.generateCode(currentScope, codeStream);
- }
- endifLabel.place();
- // May loose some local variable initializations : affecting the local variable attributes
- if (mergedInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- mergedInitStateIndex);
- }
- codeStream.recordPositionsFrom(pc, this.sourceStart);
- }
-
- public StringBuffer printStatement(int indent, StringBuffer output) {
-
- printIndent(indent, output).append("if ("); //$NON-NLS-1$
- condition.printExpression(0, output).append(")\n"); //$NON-NLS-1$
- thenStatement.printStatement(indent + 2, output);
- if (elseStatement != null) {
- output.append('\n');
- printIndent(indent, output);
- output.append("else\n"); //$NON-NLS-1$
- elseStatement.printStatement(indent + 2, output);
- }
- return output;
- }
-
- public void resolve(BlockScope scope) {
-
- TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
- condition.implicitWidening(type, type);
- if (thenStatement != null)
- thenStatement.resolve(scope);
- if (elseStatement != null)
- elseStatement.resolve(scope);
- }
-
- public void traverse(
- ASTVisitor visitor,
- BlockScope blockScope) {
-
- if (visitor.visit(this, blockScope)) {
- condition.traverse(visitor, blockScope);
- if (thenStatement != null)
- thenStatement.traverse(visitor, blockScope);
- if (elseStatement != null)
- elseStatement.traverse(visitor, blockScope);
- }
- visitor.endVisit(this, blockScope);
- }
-}