1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
19 public class DoStatement extends Statement {
21 public Expression condition;
22 public Statement action;
24 private Label breakLabel, continueLabel;
26 // for local variables table attributes
27 int mergedInitStateIndex = -1;
29 public DoStatement(Expression condition, Statement action, int s, int e) {
33 this.condition = condition;
35 // remember useful empty statement
36 if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
39 public FlowInfo analyseCode(
40 BlockScope currentScope,
41 FlowContext flowContext,
44 breakLabel = new Label();
45 continueLabel = new Label();
46 LoopingFlowContext loopingContext =
47 new LoopingFlowContext(
54 Constant cst = condition.constant;
55 boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
56 cst = condition.optimizedBooleanConstant();
57 boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
58 boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
60 int previousMode = flowInfo.reachMode();
62 if ((action != null) && !action.isEmptyBlock()) {
63 flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
65 // code generation can be optimized when no need to continue in the loop
66 if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
70 /* Reset reach mode, to address following scenario.
72 * do { if (true) break; else blank = 0; } while(false);
73 * blank = 1; // may be initialized already
75 flowInfo.setReachMode(previousMode);
78 condition.analyseCode(
83 : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
84 if (!isConditionOptimizedFalse && continueLabel != null) {
85 loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
89 FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
90 loopingContext.initsOnBreak,
91 isConditionOptimizedTrue,
92 flowInfo.initsWhenFalse(),
93 false, // never consider opt false case for DO loop, since break can always occur (47776)
94 !isConditionTrue /*do{}while(true); unreachable(); */);
95 mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
100 * Do statement code generation
103 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
105 if ((bits & IsReachableMASK) == 0) {
108 int pc = codeStream.position;
111 Label actionLabel = new Label(codeStream);
113 breakLabel.initialize(codeStream);
114 if (continueLabel != null) {
115 continueLabel.initialize(codeStream);
119 if (action != null) {
120 action.generateCode(currentScope, codeStream);
122 // generate condition
123 if (continueLabel != null) {
124 continueLabel.place();
125 condition.generateOptimizedBoolean(
134 // May loose some local variable initializations : affecting the local variable attributes
135 if (mergedInitStateIndex != -1) {
136 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
137 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
139 codeStream.recordPositionsFrom(pc, this.sourceStart);
143 public StringBuffer printStatement(int indent, StringBuffer output) {
145 printIndent(indent, output).append("do"); //$NON-NLS-1$
147 output.append(" ;\n"); //$NON-NLS-1$
150 action.printStatement(indent + 1, output).append('\n');
152 output.append("while ("); //$NON-NLS-1$
153 return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
155 public void resolve(BlockScope scope) {
157 TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
158 condition.implicitWidening(type, type);
160 action.resolve(scope);
163 public void traverse(ASTVisitor visitor, BlockScope scope) {
165 if (visitor.visit(this, scope)) {
166 if (action != null) {
167 action.traverse(visitor, scope);
169 condition.traverse(visitor, scope);
171 visitor.endVisit(this, scope);