1 11 package org.eclipse.jdt.internal.compiler.ast; 12 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.*; 18 19 public class IfStatement extends Statement { 20 21 24 public Expression condition; 25 public Statement thenStatement; 26 public Statement elseStatement; 27 28 int thenInitStateIndex = -1; 30 int elseInitStateIndex = -1; 31 int mergedInitStateIndex = -1; 32 33 public IfStatement(Expression condition, Statement thenStatement, int sourceStart, int sourceEnd) { 34 35 this.condition = condition; 36 this.thenStatement = thenStatement; 37 if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement; 39 this.sourceStart = sourceStart; 40 this.sourceEnd = sourceEnd; 41 } 42 43 public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement, int sourceStart, int sourceEnd) { 44 45 this.condition = condition; 46 this.thenStatement = thenStatement; 47 if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatement; 49 this.elseStatement = elseStatement; 50 if (elseStatement instanceof IfStatement) elseStatement.bits |= IsElseIfStatement; 51 if (elseStatement instanceof EmptyStatement) elseStatement.bits |= IsUsefulEmptyStatement; 52 this.sourceStart = sourceStart; 53 this.sourceEnd = sourceEnd; 54 } 55 56 public FlowInfo analyseCode( 57 BlockScope currentScope, 58 FlowContext flowContext, 59 FlowInfo flowInfo) { 60 61 FlowInfo conditionFlowInfo = 63 condition.analyseCode(currentScope, flowContext, flowInfo); 64 65 Constant cst = this.condition.optimizedBooleanConstant(); 66 boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true; 67 boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false; 68 69 FlowInfo thenFlowInfo = conditionFlowInfo.safeInitsWhenTrue(); 71 if (isConditionOptimizedFalse) { 72 thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 73 } 74 FlowInfo elseFlowInfo = conditionFlowInfo.initsWhenFalse(); 75 if (isConditionOptimizedTrue) { 76 elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 77 } 78 if (this.thenStatement != null) { 79 thenInitStateIndex = 81 currentScope.methodScope().recordInitializationStates(thenFlowInfo); 82 if (!thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) { 83 thenFlowInfo = 84 thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo); 85 } 86 } 87 if ((thenFlowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) { 89 this.bits |= ASTNode.ThenExit; 90 } 91 92 if (this.elseStatement != null) { 94 if (thenFlowInfo == FlowInfo.DEAD_END 96 && (this.bits & IsElseIfStatement) == 0 && !(this.elseStatement instanceof IfStatement)) { 98 currentScope.problemReporter().unnecessaryElse(this.elseStatement); 99 } 100 elseInitStateIndex = 102 currentScope.methodScope().recordInitializationStates(elseFlowInfo); 103 if (!elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) { 104 elseFlowInfo = 105 elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo); 106 } 107 } 108 109 FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches( 111 thenFlowInfo, 112 isConditionOptimizedTrue, 113 elseFlowInfo, 114 isConditionOptimizedFalse, 115 true ); 116 mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo); 117 return mergedInfo; 118 } 119 120 126 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 127 128 if ((this.bits & IsReachable) == 0) { 129 return; 130 } 131 int pc = codeStream.position; 132 BranchLabel endifLabel = new BranchLabel(codeStream); 133 134 Constant cst; 136 boolean hasThenPart = 137 !(((cst = this.condition.optimizedBooleanConstant()) != Constant.NotAConstant 138 && cst.booleanValue() == false) 139 || this.thenStatement == null 140 || this.thenStatement.isEmptyBlock()); 141 boolean hasElsePart = 142 !((cst != Constant.NotAConstant && cst.booleanValue() == true) 143 || this.elseStatement == null 144 || this.elseStatement.isEmptyBlock()); 145 if (hasThenPart) { 146 BranchLabel falseLabel = null; 147 this.condition.generateOptimizedBoolean( 149 currentScope, 150 codeStream, 151 null, 152 hasElsePart ? (falseLabel = new BranchLabel(codeStream)) : endifLabel, 153 true); 154 if (thenInitStateIndex != -1) { 156 codeStream.removeNotDefinitelyAssignedVariables(currentScope, thenInitStateIndex); 157 codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex); 158 } 159 this.thenStatement.generateCode(currentScope, codeStream); 161 if (hasElsePart) { 163 if ((this.bits & ASTNode.ThenExit) == 0) { 164 this.thenStatement.branchChainTo(endifLabel); 165 int position = codeStream.position; 166 codeStream.goto_(endifLabel); 167 codeStream.updateLastRecordedEndPC((this.thenStatement instanceof Block) ? ((Block) this.thenStatement).scope : currentScope, position); 169 } 171 if (elseInitStateIndex != -1) { 173 codeStream.removeNotDefinitelyAssignedVariables( 174 currentScope, 175 elseInitStateIndex); 176 codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex); 177 } 178 if (falseLabel != null) falseLabel.place(); 179 this.elseStatement.generateCode(currentScope, codeStream); 180 } 181 } else if (hasElsePart) { 182 this.condition.generateOptimizedBoolean( 184 currentScope, 185 codeStream, 186 endifLabel, 187 null, 188 true); 189 if (elseInitStateIndex != -1) { 192 codeStream.removeNotDefinitelyAssignedVariables( 193 currentScope, 194 elseInitStateIndex); 195 codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex); 196 } 197 this.elseStatement.generateCode(currentScope, codeStream); 198 } else { 199 this.condition.generateCode(currentScope, codeStream, false); 201 codeStream.recordPositionsFrom(pc, this.sourceStart); 202 } 203 if (mergedInitStateIndex != -1) { 205 codeStream.removeNotDefinitelyAssignedVariables( 206 currentScope, 207 mergedInitStateIndex); 208 codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex); 209 } 210 endifLabel.place(); 211 codeStream.recordPositionsFrom(pc, this.sourceStart); 212 } 213 214 public StringBuffer printStatement(int indent, StringBuffer output) { 215 216 printIndent(indent, output).append("if ("); condition.printExpression(0, output).append(")\n"); thenStatement.printStatement(indent + 2, output); 219 if (elseStatement != null) { 220 output.append('\n'); 221 printIndent(indent, output); 222 output.append("else\n"); elseStatement.printStatement(indent + 2, output); 224 } 225 return output; 226 } 227 228 public void resolve(BlockScope scope) { 229 230 TypeBinding type = condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); 231 condition.computeConversion(scope, type, type); 232 if (thenStatement != null) 233 thenStatement.resolve(scope); 234 if (elseStatement != null) 235 elseStatement.resolve(scope); 236 } 237 238 public void traverse( 239 ASTVisitor visitor, 240 BlockScope blockScope) { 241 242 if (visitor.visit(this, blockScope)) { 243 condition.traverse(visitor, blockScope); 244 if (thenStatement != null) 245 thenStatement.traverse(visitor, blockScope); 246 if (elseStatement != null) 247 elseStatement.traverse(visitor, blockScope); 248 } 249 visitor.endVisit(this, blockScope); 250 } 251 } 252 | Popular Tags |