001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.internal.compiler.ASTVisitor;
013: import org.eclipse.jdt.internal.compiler.codegen.*;
014: import org.eclipse.jdt.internal.compiler.flow.*;
015: import org.eclipse.jdt.internal.compiler.lookup.*;
016:
017: public class LabeledStatement extends Statement {
018:
019: public Statement statement;
020: public char[] label;
021: public BranchLabel targetLabel;
022: public int labelEnd;
023:
024: // for local variables table attributes
025: int mergedInitStateIndex = -1;
026:
027: /**
028: * LabeledStatement constructor comment.
029: */
030: public LabeledStatement(char[] label, Statement statement,
031: long labelPosition, int sourceEnd) {
032:
033: this .statement = statement;
034: // remember useful empty statement
035: if (statement instanceof EmptyStatement)
036: statement.bits |= IsUsefulEmptyStatement;
037: this .label = label;
038: this .sourceStart = (int) (labelPosition >>> 32);
039: this .labelEnd = (int) labelPosition;
040: this .sourceEnd = sourceEnd;
041: }
042:
043: public FlowInfo analyseCode(BlockScope currentScope,
044: FlowContext flowContext, FlowInfo flowInfo) {
045:
046: // need to stack a context to store explicit label, answer inits in case of normal completion merged
047: // with those relative to the exit path from break statement occurring inside the labeled statement.
048: if (statement == null) {
049: return flowInfo;
050: } else {
051: LabelFlowContext labelContext;
052: FlowInfo statementInfo, mergedInfo;
053: if (((statementInfo = statement.analyseCode(currentScope,
054: (labelContext = new LabelFlowContext(flowContext,
055: this , label,
056: (targetLabel = new BranchLabel()),
057: currentScope)), flowInfo)).tagBits & FlowInfo.UNREACHABLE) != 0) {
058: if ((labelContext.initsOnBreak.tagBits & FlowInfo.UNREACHABLE) == 0) {
059: // an embedded loop has had no chance to reinject forgotten null info
060: mergedInfo = flowInfo.unconditionalCopy()
061: .addInitializationsFrom(
062: labelContext.initsOnBreak);
063: } else {
064: mergedInfo = labelContext.initsOnBreak;
065: }
066: } else {
067: mergedInfo = statementInfo
068: .mergedWith(labelContext.initsOnBreak);
069: }
070: mergedInitStateIndex = currentScope.methodScope()
071: .recordInitializationStates(mergedInfo);
072: if ((this .bits & ASTNode.LabelUsed) == 0) {
073: currentScope.problemReporter().unusedLabel(this );
074: }
075: return mergedInfo;
076: }
077: }
078:
079: public ASTNode concreteStatement() {
080:
081: // return statement.concreteStatement(); // for supporting nested labels: a:b:c: someStatement (see 21912)
082: return statement;
083: }
084:
085: /**
086: * Code generation for labeled statement
087: *
088: * may not need actual source positions recording
089: *
090: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
091: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
092: */
093: public void generateCode(BlockScope currentScope,
094: CodeStream codeStream) {
095:
096: if ((bits & IsReachable) == 0) {
097: return;
098: }
099: int pc = codeStream.position;
100: if (targetLabel != null) {
101: targetLabel.initialize(codeStream);
102: if (statement != null) {
103: statement.generateCode(currentScope, codeStream);
104: }
105: targetLabel.place();
106: }
107: // May loose some local variable initializations : affecting the local variable attributes
108: if (mergedInitStateIndex != -1) {
109: codeStream.removeNotDefinitelyAssignedVariables(
110: currentScope, mergedInitStateIndex);
111: codeStream.addDefinitelyAssignedVariables(currentScope,
112: mergedInitStateIndex);
113: }
114: codeStream.recordPositionsFrom(pc, this .sourceStart);
115: }
116:
117: public StringBuffer printStatement(int tab, StringBuffer output) {
118:
119: printIndent(tab, output).append(label).append(": "); //$NON-NLS-1$
120: if (this .statement == null)
121: output.append(';');
122: else
123: this .statement.printStatement(0, output);
124: return output;
125: }
126:
127: public void resolve(BlockScope scope) {
128:
129: if (this .statement != null) {
130: this .statement.resolve(scope);
131: }
132: }
133:
134: public void traverse(ASTVisitor visitor, BlockScope blockScope) {
135:
136: if (visitor.visit(this, blockScope)) {
137: if (this.statement != null)
138: this.statement.traverse(visitor, blockScope);
139: }
140: visitor.endVisit(this, blockScope);
141: }
142: }
|