public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { if (this.expression != null) { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo); } // compute the return sequence (running the finally blocks) FlowContext traversedContext = flowContext; int subCount = 0; boolean saveValueNeeded = false; boolean hasValueToSave = this.expression != null && this.expression.constant == Constant.NotAConstant && !(this.expression instanceof NullLiteral); do { SubRoutineStatement sub; if ((sub = traversedContext.subroutine()) != null) { if (this.subroutines == null) { this.subroutines = new SubRoutineStatement[5]; } if (subCount == this.subroutines.length) { System.arraycopy( this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount * 2]), 0, subCount); // grow } this.subroutines[subCount++] = sub; if (sub.isSubRoutineEscaping()) { saveValueNeeded = false; this.bits |= ASTNode.IsAnySubRoutineEscaping; break; } } traversedContext.recordReturnFrom(flowInfo.unconditionalInits()); if (traversedContext instanceof InsideSubRoutineFlowContext) { ASTNode node = traversedContext.associatedNode; if (node instanceof TryStatement) { TryStatement tryStatement = (TryStatement) node; flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits if (hasValueToSave) { if (this.saveValueVariable == null) { // closest subroutine secret variable is used prepareSaveValueLocation(tryStatement); } saveValueNeeded = true; } } } else if (traversedContext instanceof InitializationFlowContext) { currentScope.problemReporter().cannotReturnOutsideFunction(this); return FlowInfo.DEAD_END; } } while ((traversedContext = traversedContext.parent) != null); // resize subroutines if ((this.subroutines != null) && (subCount != this.subroutines.length)) { System.arraycopy( this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount); } // secret local variable for return value (note that this can only occur in a real method) if (saveValueNeeded) { if (this.saveValueVariable != null) { this.saveValueVariable.useFlag = LocalVariableBinding.USED; } } else { this.saveValueVariable = null; if (this.expression != null && this.expression.resolvedType == TypeBinding.BOOLEAN) { this.expression.bits |= ASTNode.IsReturnedValue; } } return FlowInfo.DEAD_END; }
public void exitAnyExceptionHandler() { if (this.subRoutineStartLabel == null) return; super.exitAnyExceptionHandler(); }