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);