1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *     Stephan Herrmann - Contribution for
11  *								bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
12  *******************************************************************************/
13 package org.eclipse.jdt.internal.compiler.ast;
14 
15 import org.eclipse.jdt.internal.compiler.ASTVisitor;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18 
19 public class BreakStatement extends BranchStatement {
20 
BreakStatement(char[] label, int sourceStart, int e)21 public BreakStatement(char[] label, int sourceStart, int e) {
22 	super(label, sourceStart, e);
23 }
24 
analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo)25 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
26 
27 	// here requires to generate a sequence of finally blocks invocations depending corresponding
28 	// to each of the traversed try statements, so that execution will terminate properly.
29 
30 	// lookup the label, this should answer the returnContext
31 	FlowContext targetContext = (this.label == null)
32 		? flowContext.getTargetContextForDefaultBreak()
33 		: flowContext.getTargetContextForBreakLabel(this.label);
34 
35 	if (targetContext == null) {
36 		if (this.label == null) {
37 			currentScope.problemReporter().invalidBreak(this);
38 		} else {
39 			currentScope.problemReporter().undefinedLabel(this);
40 		}
41 		return flowInfo; // pretend it did not break since no actual target
42 	}
43 
44 	targetContext.recordAbruptExit();
45 
46 	this.initStateIndex =
47 		currentScope.methodScope().recordInitializationStates(flowInfo);
48 
49 	this.targetLabel = targetContext.breakLabel();
50 	FlowContext traversedContext = flowContext;
51 	int subCount = 0;
52 	this.subroutines = new SubRoutineStatement[5];
53 
54 	do {
55 		SubRoutineStatement sub;
56 		if ((sub = traversedContext.subroutine()) != null) {
57 			if (subCount == this.subroutines.length) {
58 				System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
59 			}
60 			this.subroutines[subCount++] = sub;
61 			if (sub.isSubRoutineEscaping()) {
62 				break;
63 			}
64 		}
65 		traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
66 		traversedContext.recordBreakTo(targetContext);
67 
68 		if (traversedContext instanceof InsideSubRoutineFlowContext) {
69 			ASTNode node = traversedContext.associatedNode;
70 			if (node instanceof TryStatement) {
71 				TryStatement tryStatement = (TryStatement) node;
72 				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
73 			}
74 		} else if (traversedContext == targetContext) {
75 			// only record break info once accumulated through subroutines, and only against target context
76 			targetContext.recordBreakFrom(flowInfo);
77 			break;
78 		}
79 	} while ((traversedContext = traversedContext.getLocalParent()) != null);
80 
81 	// resize subroutines
82 	if (subCount != this.subroutines.length) {
83 		System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
84 	}
85 	return FlowInfo.DEAD_END;
86 }
87 
printStatement(int tab, StringBuffer output)88 public StringBuffer printStatement(int tab, StringBuffer output) {
89 	printIndent(tab, output).append("break"); //$NON-NLS-1$
90 	if (this.label != null) output.append(' ').append(this.label);
91 	return output.append(';');
92 }
93 
traverse(ASTVisitor visitor, BlockScope blockscope)94 public void traverse(ASTVisitor visitor, BlockScope blockscope) {
95 	visitor.visit(this, blockscope);
96 	visitor.endVisit(this, blockscope);
97 }
98 }
99