1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
22 public class LocalDeclaration extends AbstractVariableDeclaration {
24 public LocalVariableBinding binding;
26 public LocalDeclaration(Expression expr, char[] name, int sourceStart,
29 initialization = expr;
31 this.sourceStart = sourceStart;
32 this.sourceEnd = sourceEnd;
33 if (initialization != null) {
34 this.declarationSourceEnd = initialization.sourceEnd;
35 this.declarationEnd = initialization.sourceEnd;
37 this.declarationEnd = sourceEnd;
41 public FlowInfo analyseCode(BlockScope currentScope,
42 FlowContext flowContext, FlowInfo flowInfo) {
44 // record variable initialization if any
45 if (flowInfo.isReachable()) {
46 bits |= IsLocalDeclarationReachableMASK; // only set if actually
49 if (initialization == null)
52 flowInfo = initialization.analyseCode(currentScope, flowContext,
53 flowInfo).unconditionalInits();
55 // final int i = (i = 0);
56 // no need to complain since (i = 0) part will get the blame
57 // if (binding.isFinal() && flowInfo.isPotentiallyAssigned(binding)) {
58 // currentScope.problemReporter().duplicateInitializationOfFinalLocal(binding,
62 flowInfo.markAsDefinitelyAssigned(binding);
66 public void checkModifiers() {
68 // only potential valid modifier is <<final>>
69 if (((modifiers & AccJustFlag) & ~AccFinal) != 0)
70 // AccModifierProblem -> other (non-visibility problem)
71 // AccAlternateModifierProblem -> duplicate modifier
72 // AccModifierProblem | AccAlternateModifierProblem -> visibility
75 modifiers = (modifiers & ~AccAlternateModifierProblem)
80 * Code generation for a local declaration: normal assignment to a local
81 * variable + unused variable handling
83 // public void generateCode(BlockScope currentScope, CodeStream codeStream)
86 // // even if not reachable, variable must be added to visible if allocated
88 // if (binding.resolvedPosition != -1) {
89 // codeStream.addVisibleLocalVariable(binding);
91 // if ((bits & IsReachableMASK) == 0) {
94 // int pc = codeStream.position;
95 // Constant inlinedValue;
97 // // something to initialize?
98 // if (initialization != null) {
99 // // initialize to constant value?
100 // if ((inlinedValue = initialization.constant) != NotAConstant) {
101 // // forget initializing unused or final locals set to constant value
102 // (final ones are inlined)
103 // if (binding.resolvedPosition != -1) { // may need to preserve variable
104 // int initPC = codeStream.position;
105 // codeStream.generateConstant(inlinedValue,
106 // initialization.implicitConversion);
107 // codeStream.recordPositionsFrom(initPC, initialization.sourceStart);
108 // codeStream.store(binding, false);
109 // binding.recordInitializationStartPC(codeStream.position);
110 // // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize
112 // // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add
115 // } else { // initializing to non-constant value
116 // initialization.generateCode(currentScope, codeStream, true);
117 // // if binding unused generate then discard the value
118 // if (binding.resolvedPosition != -1) {
119 // // 26903, need extra cast to store null in array local var
120 // if (binding.type.isArrayType()
121 // && (initialization.resolvedType == NullBinding // arrayLoc = null
122 // || ((initialization instanceof CastExpression) // arrayLoc = (type[])null
124 // (((CastExpression)initialization).innermostCastedExpression().resolvedType
125 // == NullBinding)))){
126 // codeStream.checkcast(binding.type);
128 // codeStream.store(binding, false);
129 // if (binding.initializationCount == 0) {
130 // /* Variable may have been initialized during the code initializing it
131 // e.g. int i = (i = 1);
133 // binding.recordInitializationStartPC(codeStream.position);
134 // // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize
136 // // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add
140 // if ((binding.type == LongBinding) || (binding.type == DoubleBinding)) {
141 // codeStream.pop2();
148 // codeStream.recordPositionsFrom(pc, this.sourceStart);
150 public String name() {
152 return String.valueOf(name);
155 public void resolve(BlockScope scope) {
157 // create a binding and add it to the scope
158 TypeBinding tb = type.resolveType(scope);
163 if (tb == VoidBinding) {
164 scope.problemReporter().variableTypeCannotBeVoid(this);
168 && ((ArrayBinding) tb).leafComponentType == VoidBinding) {
169 scope.problemReporter().variableTypeCannotBeVoidArray(this);
175 if ((binding = scope.duplicateName(name)) != null) {
176 // the name already exists... may carry on with the first binding...
177 scope.problemReporter().redefineLocal(this);
179 if ((modifiers & AccFinal) != 0 && this.initialization == null) {
180 modifiers |= AccBlankFinal;
182 binding = new LocalVariableBinding(this, tb, modifiers, false);
183 scope.addLocalVariable(binding);
184 binding.constant = NotAConstant;
185 // allow to recursivelly target the binding....
186 // the correct constant is harmed if correctly computed at the end
191 if (initialization != null)
192 initialization.resolveType(scope); // want to report all
197 // store the constant for final locals
198 if (initialization != null) {
199 if (initialization instanceof ArrayInitializer) {
200 TypeBinding initTb = initialization.resolveTypeExpecting(scope,
202 if (initTb != null) {
203 ((ArrayInitializer) initialization).binding = (ArrayBinding) initTb;
204 initialization.implicitWidening(tb, initTb);
207 TypeBinding initTb = initialization.resolveType(scope);
208 if (initTb != null) {
209 if (initialization.isConstantValueOfTypeAssignableToType(
211 || (tb.isBaseType() && BaseTypeBinding.isWidening(
213 || initTb.isCompatibleWith(tb))
214 initialization.implicitWidening(tb, initTb);
216 scope.problemReporter().typeMismatchError(initTb, tb,
221 // change the constant in the binding when it is final
222 // (the optimization of the constant propagation will be done later
224 // cast from constant actual type to variable type
225 binding.constant = binding.isFinal() ? initialization.constant
226 .castTo((tb.id << 4) + initialization.constant.typeID())
231 public void traverse(ASTVisitor visitor, BlockScope scope) {
233 if (visitor.visit(this, scope)) {
234 type.traverse(visitor, scope);
235 if (initialization != null)
236 initialization.traverse(visitor, scope);
238 visitor.endVisit(this, scope);