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.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
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.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
20 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
24 public class LocalDeclaration extends AbstractVariableDeclaration {
26 public LocalVariableBinding binding;
28 public LocalDeclaration(
34 initialization = expr;
36 this.sourceStart = sourceStart;
37 this.sourceEnd = sourceEnd;
38 if (initialization != null) {
39 this.declarationSourceEnd = initialization.sourceEnd;
40 this.declarationEnd = initialization.sourceEnd;
42 this.declarationEnd = sourceEnd;
46 public FlowInfo analyseCode(
47 BlockScope currentScope,
48 FlowContext flowContext,
51 // record variable initialization if any
52 if (flowInfo.isReachable()) {
53 bits |= IsLocalDeclarationReachableMASK; // only set if actually reached
55 if (initialization == null)
60 .analyseCode(currentScope, flowContext, flowInfo)
61 .unconditionalInits();
63 // final int i = (i = 0);
64 // no need to complain since (i = 0) part will get the blame
65 //if (binding.isFinal() && flowInfo.isPotentiallyAssigned(binding)) {
66 // currentScope.problemReporter().duplicateInitializationOfFinalLocal(binding, this);
69 flowInfo.markAsDefinitelyAssigned(binding);
73 public void checkModifiers() {
75 //only potential valid modifier is <<final>>
76 if (((modifiers & AccJustFlag) & ~AccFinal) != 0)
77 //AccModifierProblem -> other (non-visibility problem)
78 //AccAlternateModifierProblem -> duplicate modifier
79 //AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
81 modifiers = (modifiers & ~AccAlternateModifierProblem) | AccModifierProblem;
85 * Code generation for a local declaration:
86 * normal assignment to a local variable + unused variable handling
88 // public void generateCode(BlockScope currentScope, CodeStream codeStream) {
90 // // even if not reachable, variable must be added to visible if allocated (28298)
91 // if (binding.resolvedPosition != -1) {
92 // codeStream.addVisibleLocalVariable(binding);
94 // if ((bits & IsReachableMASK) == 0) {
97 // int pc = codeStream.position;
98 // Constant inlinedValue;
100 // // something to initialize?
101 // if (initialization != null) {
102 // // initialize to constant value?
103 // if ((inlinedValue = initialization.constant) != NotAConstant) {
104 // // forget initializing unused or final locals set to constant value (final ones are inlined)
105 // if (binding.resolvedPosition != -1) { // may need to preserve variable
106 // int initPC = codeStream.position;
107 // codeStream.generateConstant(inlinedValue, initialization.implicitConversion);
108 // codeStream.recordPositionsFrom(initPC, initialization.sourceStart);
109 // codeStream.store(binding, false);
110 // binding.recordInitializationStartPC(codeStream.position);
111 // // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index
112 // // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index
114 // } else { // initializing to non-constant value
115 // initialization.generateCode(currentScope, codeStream, true);
116 // // if binding unused generate then discard the value
117 // if (binding.resolvedPosition != -1) {
118 // // 26903, need extra cast to store null in array local var
119 // if (binding.type.isArrayType()
120 // && (initialization.resolvedType == NullBinding // arrayLoc = null
121 // || ((initialization instanceof CastExpression) // arrayLoc = (type[])null
122 // && (((CastExpression)initialization).innermostCastedExpression().resolvedType == NullBinding)))){
123 // codeStream.checkcast(binding.type);
125 // codeStream.store(binding, false);
126 // if (binding.initializationCount == 0) {
127 // /* Variable may have been initialized during the code initializing it
128 // e.g. int i = (i = 1);
130 // binding.recordInitializationStartPC(codeStream.position);
131 // // codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index
132 // // codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index
135 // if ((binding.type == LongBinding) || (binding.type == DoubleBinding)) {
136 // codeStream.pop2();
143 // codeStream.recordPositionsFrom(pc, this.sourceStart);
146 public String name() {
148 return String.valueOf(name);
151 public void resolve(BlockScope scope) {
153 // create a binding and add it to the scope
154 TypeBinding tb = type.resolveType(scope);
159 if (tb == VoidBinding) {
160 scope.problemReporter().variableTypeCannotBeVoid(this);
163 if (tb.isArrayType() && ((ArrayBinding) tb).leafComponentType == VoidBinding) {
164 scope.problemReporter().variableTypeCannotBeVoidArray(this);
170 if ((binding = scope.duplicateName(name)) != null) {
171 // the name already exists... may carry on with the first binding...
172 scope.problemReporter().redefineLocal(this);
174 if ((modifiers & AccFinal)!= 0 && this.initialization == null) {
175 modifiers |= AccBlankFinal;
177 binding = new LocalVariableBinding(this, tb, modifiers, false);
178 scope.addLocalVariable(binding);
179 binding.constant = NotAConstant;
180 // allow to recursivelly target the binding....
181 // the correct constant is harmed if correctly computed at the end of this method
185 if (initialization != null)
186 initialization.resolveType(scope); // want to report all possible errors
190 // store the constant for final locals
191 if (initialization != null) {
192 if (initialization instanceof ArrayInitializer) {
193 TypeBinding initTb = initialization.resolveTypeExpecting(scope, tb);
194 if (initTb != null) {
195 ((ArrayInitializer) initialization).binding = (ArrayBinding) initTb;
196 initialization.implicitWidening(tb, initTb);
199 TypeBinding initTb = initialization.resolveType(scope);
200 if (initTb != null) {
201 if (initialization.isConstantValueOfTypeAssignableToType(initTb, tb)
202 || (tb.isBaseType() && BaseTypeBinding.isWidening(tb.id, initTb.id))
203 || initTb.isCompatibleWith(tb))
204 initialization.implicitWidening(tb, initTb);
206 scope.problemReporter().typeMismatchError(initTb, tb, this);
210 // change the constant in the binding when it is final
211 // (the optimization of the constant propagation will be done later on)
212 // cast from constant actual type to variable type
215 ? initialization.constant.castTo((tb.id << 4) + initialization.constant.typeID())
220 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
222 if (visitor.visit(this, scope)) {
223 type.traverse(visitor, scope);
224 if (initialization != null)
225 initialization.traverse(visitor, scope);
227 visitor.endVisit(this, scope);