KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > LocalDeclaration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16 import org.eclipse.jdt.internal.compiler.codegen.*;
17 import org.eclipse.jdt.internal.compiler.flow.*;
18 import org.eclipse.jdt.internal.compiler.lookup.*;
19
20 public class LocalDeclaration extends AbstractVariableDeclaration {
21
22     public LocalVariableBinding binding;
23     
24     public LocalDeclaration(
25         char[] name,
26         int sourceStart,
27         int sourceEnd) {
28
29         this.name = name;
30         this.sourceStart = sourceStart;
31         this.sourceEnd = sourceEnd;
32         this.declarationEnd = sourceEnd;
33     }
34
35 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
36     // record variable initialization if any
37
if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
38         bits |= ASTNode.IsLocalDeclarationReachable; // only set if actually reached
39
}
40     if (this.initialization == null) {
41         return flowInfo;
42     }
43     int nullStatus = this.initialization.nullStatus(flowInfo);
44     flowInfo =
45         this.initialization
46             .analyseCode(currentScope, flowContext, flowInfo)
47             .unconditionalInits();
48     if (!flowInfo.isDefinitelyAssigned(this.binding)){// for local variable debug attributes
49
this.bits |= FirstAssignmentToLocal;
50     } else {
51         this.bits &= ~FirstAssignmentToLocal; // int i = (i = 0);
52
}
53     flowInfo.markAsDefinitelyAssigned(binding);
54     if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
55         switch(nullStatus) {
56             case FlowInfo.NULL :
57                 flowInfo.markAsDefinitelyNull(this.binding);
58                 break;
59             case FlowInfo.NON_NULL :
60                 flowInfo.markAsDefinitelyNonNull(this.binding);
61                 break;
62             default:
63                 flowInfo.markAsDefinitelyUnknown(this.binding);
64         }
65         // no need to inform enclosing try block since its locals won't get
66
// known by the finally block
67
}
68     return flowInfo;
69 }
70
71     public void checkModifiers() {
72
73         //only potential valid modifier is <<final>>
74
if (((modifiers & ExtraCompilerModifiers.AccJustFlag) & ~ClassFileConstants.AccFinal) != 0)
75             //AccModifierProblem -> other (non-visibility problem)
76
//AccAlternateModifierProblem -> duplicate modifier
77
//AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
78

79             modifiers = (modifiers & ~ExtraCompilerModifiers.AccAlternateModifierProblem) | ExtraCompilerModifiers.AccModifierProblem;
80     }
81
82     /**
83      * Code generation for a local declaration:
84      * i.e.&nbsp;normal assignment to a local variable + unused variable handling
85      */

86     public void generateCode(BlockScope currentScope, CodeStream codeStream) {
87
88         // even if not reachable, variable must be added to visible if allocated (28298)
89
if (binding.resolvedPosition != -1) {
90             codeStream.addVisibleLocalVariable(binding);
91         }
92         if ((bits & IsReachable) == 0) {
93             return;
94         }
95         int pc = codeStream.position;
96
97         // something to initialize?
98
generateInit: {
99             if (this.initialization == null)
100                 break generateInit;
101             // forget initializing unused or final locals set to constant value (final ones are inlined)
102
if (binding.resolvedPosition < 0) {
103                 if (initialization.constant != Constant.NotAConstant)
104                     break generateInit;
105                 // if binding unused generate then discard the value
106
initialization.generateCode(currentScope, codeStream, false);
107                 break generateInit;
108             }
109             initialization.generateCode(currentScope, codeStream, true);
110             // 26903, need extra cast to store null in array local var
111
if (binding.type.isArrayType()
112                 && (initialization.resolvedType == TypeBinding.NULL // arrayLoc = null
113
|| ((initialization instanceof CastExpression) // arrayLoc = (type[])null
114
&& (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){
115                 codeStream.checkcast(binding.type);
116             }
117             codeStream.store(binding, false);
118             if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) {
119                 /* Variable may have been initialized during the code initializing it
120                     e.g. int i = (i = 1);
121                 */

122                 binding.recordInitializationStartPC(codeStream.position);
123             }
124         }
125         codeStream.recordPositionsFrom(pc, this.sourceStart);
126     }
127
128     /**
129      * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
130      */

131     public int getKind() {
132         return LOCAL_VARIABLE;
133     }
134     
135     public void resolve(BlockScope scope) {
136
137         // create a binding and add it to the scope
138
TypeBinding variableType = type.resolveType(scope, true /* check bounds*/);
139
140         checkModifiers();
141         if (variableType != null) {
142             if (variableType == TypeBinding.VOID) {
143                 scope.problemReporter().variableTypeCannotBeVoid(this);
144                 return;
145             }
146             if (variableType.isArrayType() && ((ArrayBinding) variableType).leafComponentType == TypeBinding.VOID) {
147                 scope.problemReporter().variableTypeCannotBeVoidArray(this);
148                 return;
149             }
150         }
151         
152         Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
153         if (existingVariable != null && existingVariable.isValidBinding()){
154             if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
155                 scope.problemReporter().redefineLocal(this);
156             } else {
157                 scope.problemReporter().localVariableHiding(this, existingVariable, false);
158             }
159         }
160                 
161         if ((modifiers & ClassFileConstants.AccFinal)!= 0 && this.initialization == null) {
162             modifiers |= ExtraCompilerModifiers.AccBlankFinal;
163         }
164         this.binding = new LocalVariableBinding(this, variableType, modifiers, false);
165         scope.addLocalVariable(binding);
166         this.binding.setConstant(Constant.NotAConstant);
167         // allow to recursivelly target the binding....
168
// the correct constant is harmed if correctly computed at the end of this method
169

170         if (variableType == null) {
171             if (initialization != null)
172                 initialization.resolveType(scope); // want to report all possible errors
173
return;
174         }
175
176         // store the constant for final locals
177
if (initialization != null) {
178             if (initialization instanceof ArrayInitializer) {
179                 TypeBinding initializationType = initialization.resolveTypeExpecting(scope, variableType);
180                 if (initializationType != null) {
181                     ((ArrayInitializer) initialization).binding = (ArrayBinding) initializationType;
182                     initialization.computeConversion(scope, variableType, initializationType);
183                 }
184             } else {
185                 this.initialization.setExpectedType(variableType);
186                 TypeBinding initializationType = this.initialization.resolveType(scope);
187                 if (initializationType != null) {
188                     if (variableType != initializationType) // must call before computeConversion() and typeMismatchError()
189
scope.compilationUnitScope().recordTypeConversion(variableType, initializationType);
190                     if (initialization.isConstantValueOfTypeAssignableToType(initializationType, variableType)
191                         || (variableType.isBaseType() && BaseTypeBinding.isWidening(variableType.id, initializationType.id))
192                         || initializationType.isCompatibleWith(variableType)) {
193                         this.initialization.computeConversion(scope, variableType, initializationType);
194                         if (initializationType.needsUncheckedConversion(variableType)) {
195                             scope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, variableType);
196                         }
197                         if (this.initialization instanceof CastExpression
198                                 && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
199                             CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization);
200                         }
201                     } else if (scope.isBoxingCompatibleWith(initializationType, variableType)
202                                         || (initializationType.isBaseType() // narrowing then boxing ?
203
&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 // autoboxing
204
&& !variableType.isBaseType()
205                                                 && initialization.isConstantValueOfTypeAssignableToType(initializationType, scope.environment().computeBoxingType(variableType)))) {
206                         this.initialization.computeConversion(scope, variableType, initializationType);
207                         if (this.initialization instanceof CastExpression
208                                 && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) {
209                             CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization);
210                         }
211                     } else {
212                         scope.problemReporter().typeMismatchError(initializationType, variableType, this.initialization);
213                     }
214                 }
215             }
216             // check for assignment with no effect
217
if (this.binding == Assignment.getDirectBinding(this.initialization)) {
218                 scope.problemReporter().assignmentHasNoEffect(this, this.name);
219             }
220             // change the constant in the binding when it is final
221
// (the optimization of the constant propagation will be done later on)
222
// cast from constant actual type to variable type
223
binding.setConstant(
224                 binding.isFinal()
225                     ? initialization.constant.castTo((variableType.id << 4) + initialization.constant.typeID())
226                     : Constant.NotAConstant);
227         }
228         // only resolve annotation at the end, for constant to be positionned before (96991)
229
resolveAnnotations(scope, this.annotations, this.binding);
230     }
231
232     public void traverse(ASTVisitor visitor, BlockScope scope) {
233
234         if (visitor.visit(this, scope)) {
235             if (this.annotations != null) {
236                 int annotationsLength = this.annotations.length;
237                 for (int i = 0; i < annotationsLength; i++)
238                     this.annotations[i].traverse(visitor, scope);
239             }
240             type.traverse(visitor, scope);
241             if (initialization != null)
242                 initialization.traverse(visitor, scope);
243         }
244         visitor.endVisit(this, scope);
245     }
246 }
247
Popular Tags