Lines 12-22
Link Here
|
12 |
|
12 |
|
13 |
import org.eclipse.jdt.core.compiler.CharOperation; |
13 |
import org.eclipse.jdt.core.compiler.CharOperation; |
14 |
import org.eclipse.jdt.internal.compiler.ASTVisitor; |
14 |
import org.eclipse.jdt.internal.compiler.ASTVisitor; |
15 |
import org.eclipse.jdt.internal.compiler.impl.*; |
|
|
16 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
15 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
17 |
import org.eclipse.jdt.internal.compiler.codegen.*; |
16 |
import org.eclipse.jdt.internal.compiler.codegen.CodeStream; |
18 |
import org.eclipse.jdt.internal.compiler.flow.*; |
17 |
import org.eclipse.jdt.internal.compiler.flow.FlowContext; |
19 |
import org.eclipse.jdt.internal.compiler.lookup.*; |
18 |
import org.eclipse.jdt.internal.compiler.flow.FlowInfo; |
|
|
19 |
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
20 |
import org.eclipse.jdt.internal.compiler.impl.Constant; |
21 |
import org.eclipse.jdt.internal.compiler.lookup.Binding; |
22 |
import org.eclipse.jdt.internal.compiler.lookup.BlockScope; |
23 |
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; |
24 |
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; |
25 |
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; |
26 |
import org.eclipse.jdt.internal.compiler.lookup.MethodScope; |
27 |
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; |
28 |
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; |
29 |
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
30 |
import org.eclipse.jdt.internal.compiler.lookup.Scope; |
31 |
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; |
32 |
import org.eclipse.jdt.internal.compiler.lookup.TagBits; |
33 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
34 |
import org.eclipse.jdt.internal.compiler.lookup.TypeIds; |
20 |
|
35 |
|
21 |
public class FieldReference extends Reference implements InvocationSite { |
36 |
public class FieldReference extends Reference implements InvocationSite { |
22 |
|
37 |
|
Lines 33-62
Link Here
|
33 |
public TypeBinding genericCast; |
48 |
public TypeBinding genericCast; |
34 |
|
49 |
|
35 |
public FieldReference(char[] source, long pos) { |
50 |
public FieldReference(char[] source, long pos) { |
36 |
token = source; |
51 |
this.token = source; |
37 |
nameSourcePosition = pos; |
52 |
this.nameSourcePosition = pos; |
38 |
//by default the position are the one of the field (not true for super access) |
53 |
//by default the position are the one of the field (not true for super access) |
39 |
sourceStart = (int) (pos >>> 32); |
54 |
this.sourceStart = (int) (pos >>> 32); |
40 |
sourceEnd = (int) (pos & 0x00000000FFFFFFFFL); |
55 |
this.sourceEnd = (int) (pos & 0x00000000FFFFFFFFL); |
41 |
bits |= Binding.FIELD; |
56 |
this.bits |= Binding.FIELD; |
42 |
|
57 |
|
43 |
} |
58 |
} |
44 |
|
59 |
|
45 |
public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { |
60 |
public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { |
46 |
// compound assignment extra work |
61 |
// compound assignment extra work |
47 |
if (isCompound) { // check the variable part is initialized if blank final |
62 |
if (isCompound) { // check the variable part is initialized if blank final |
48 |
if (binding.isBlankFinal() |
63 |
if (this.binding.isBlankFinal() |
49 |
&& receiver.isThis() |
64 |
&& this.receiver.isThis() |
50 |
&& currentScope.needBlankFinalFieldInitializationCheck(binding) |
65 |
&& currentScope.needBlankFinalFieldInitializationCheck(this.binding) |
51 |
&& (!flowInfo.isDefinitelyAssigned(binding))) { |
66 |
&& (!flowInfo.isDefinitelyAssigned(this.binding))) { |
52 |
currentScope.problemReporter().uninitializedBlankFinalField(binding, this); |
67 |
currentScope.problemReporter().uninitializedBlankFinalField(this.binding, this); |
53 |
// we could improve error msg here telling "cannot use compound assignment on final blank field" |
68 |
// we could improve error msg here telling "cannot use compound assignment on final blank field" |
54 |
} |
69 |
} |
55 |
manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); |
70 |
manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); |
56 |
} |
71 |
} |
57 |
flowInfo = |
72 |
flowInfo = |
58 |
receiver |
73 |
this.receiver |
59 |
.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic()) |
74 |
.analyseCode(currentScope, flowContext, flowInfo, !this.binding.isStatic()) |
60 |
.unconditionalInits(); |
75 |
.unconditionalInits(); |
61 |
if (assignment.expression != null) { |
76 |
if (assignment.expression != null) { |
62 |
flowInfo = |
77 |
flowInfo = |
Lines 68-92
Link Here
|
68 |
manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); |
83 |
manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); |
69 |
|
84 |
|
70 |
// check if assigning a final field |
85 |
// check if assigning a final field |
71 |
if (binding.isFinal()) { |
86 |
if (this.binding.isFinal()) { |
72 |
// in a context where it can be assigned? |
87 |
// in a context where it can be assigned? |
73 |
if (binding.isBlankFinal() |
88 |
if (this.binding.isBlankFinal() |
74 |
&& !isCompound |
89 |
&& !isCompound |
75 |
&& receiver.isThis() |
90 |
&& this.receiver.isThis() |
76 |
&& !(receiver instanceof QualifiedThisReference) |
91 |
&& !(this.receiver instanceof QualifiedThisReference) |
77 |
&& ((receiver.bits & ParenthesizedMASK) == 0) // (this).x is forbidden |
92 |
&& ((this.receiver.bits & ASTNode.ParenthesizedMASK) == 0) // (this).x is forbidden |
78 |
&& currentScope.allowBlankFinalFieldAssignment(binding)) { |
93 |
&& currentScope.allowBlankFinalFieldAssignment(this.binding)) { |
79 |
if (flowInfo.isPotentiallyAssigned(binding)) { |
94 |
if (flowInfo.isPotentiallyAssigned(this.binding)) { |
80 |
currentScope.problemReporter().duplicateInitializationOfBlankFinalField( |
95 |
currentScope.problemReporter().duplicateInitializationOfBlankFinalField( |
81 |
binding, |
96 |
this.binding, |
82 |
this); |
97 |
this); |
83 |
} else { |
98 |
} else { |
84 |
flowContext.recordSettingFinal(binding, this, flowInfo); |
99 |
flowContext.recordSettingFinal(this.binding, this, flowInfo); |
85 |
} |
100 |
} |
86 |
flowInfo.markAsDefinitelyAssigned(binding); |
101 |
flowInfo.markAsDefinitelyAssigned(this.binding); |
87 |
} else { |
102 |
} else { |
88 |
// assigning a final field outside an initializer or constructor or wrong reference |
103 |
// assigning a final field outside an initializer or constructor or wrong reference |
89 |
currentScope.problemReporter().cannotAssignToFinalField(binding, this); |
104 |
currentScope.problemReporter().cannotAssignToFinalField(this.binding, this); |
90 |
} |
105 |
} |
91 |
} |
106 |
} |
92 |
return flowInfo; |
107 |
return flowInfo; |
Lines 97-106
Link Here
|
97 |
} |
112 |
} |
98 |
|
113 |
|
99 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { |
114 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { |
100 |
boolean nonStatic = !binding.isStatic(); |
115 |
boolean nonStatic = !this.binding.isStatic(); |
101 |
receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic); |
116 |
this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic); |
102 |
if (nonStatic) { |
117 |
if (nonStatic) { |
103 |
receiver.checkNPE(currentScope, flowContext, flowInfo); |
118 |
this.receiver.checkNPE(currentScope, flowContext, flowInfo); |
104 |
} |
119 |
} |
105 |
|
120 |
|
106 |
if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { |
121 |
if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { |
Lines 122-128
Link Here
|
122 |
// extra cast needed if method return type is type variable |
137 |
// extra cast needed if method return type is type variable |
123 |
if (originalBinding != this.binding |
138 |
if (originalBinding != this.binding |
124 |
&& originalType != this.binding.type |
139 |
&& originalType != this.binding.type |
125 |
&& runtimeTimeType.id != T_JavaLangObject |
140 |
&& runtimeTimeType.id != TypeIds.T_JavaLangObject |
126 |
&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) { |
141 |
&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) { |
127 |
TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) |
142 |
TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) |
128 |
? compileTimeType // unboxing: checkcast before conversion |
143 |
? compileTimeType // unboxing: checkcast before conversion |
Lines 144-155
Link Here
|
144 |
} |
159 |
} |
145 |
|
160 |
|
146 |
public FieldBinding fieldBinding() { |
161 |
public FieldBinding fieldBinding() { |
147 |
return binding; |
162 |
return this.binding; |
148 |
} |
163 |
} |
149 |
|
164 |
|
150 |
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { |
165 |
public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { |
151 |
int pc = codeStream.position; |
166 |
int pc = codeStream.position; |
152 |
receiver.generateCode( |
167 |
this.receiver.generateCode( |
153 |
currentScope, |
168 |
currentScope, |
154 |
codeStream, |
169 |
codeStream, |
155 |
!this.codegenBinding.isStatic()); |
170 |
!this.codegenBinding.isStatic()); |
Lines 158-164
Link Here
|
158 |
fieldStore( |
173 |
fieldStore( |
159 |
codeStream, |
174 |
codeStream, |
160 |
this.codegenBinding, |
175 |
this.codegenBinding, |
161 |
syntheticAccessors == null ? null : syntheticAccessors[WRITE], |
176 |
this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], |
162 |
valueRequired); |
177 |
valueRequired); |
163 |
if (valueRequired) { |
178 |
if (valueRequired) { |
164 |
codeStream.generateImplicitConversion(assignment.implicitConversion); |
179 |
codeStream.generateImplicitConversion(assignment.implicitConversion); |
Lines 175-183
Link Here
|
175 |
*/ |
190 |
*/ |
176 |
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { |
191 |
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { |
177 |
int pc = codeStream.position; |
192 |
int pc = codeStream.position; |
178 |
if (constant != Constant.NotAConstant) { |
193 |
if (this.constant != Constant.NotAConstant) { |
179 |
if (valueRequired) { |
194 |
if (valueRequired) { |
180 |
codeStream.generateConstant(constant, implicitConversion); |
195 |
codeStream.generateConstant(this.constant, this.implicitConversion); |
181 |
} |
196 |
} |
182 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
197 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
183 |
return; |
198 |
return; |
Lines 187-236
Link Here
|
187 |
Constant fieldConstant = this.codegenBinding.constant(); |
202 |
Constant fieldConstant = this.codegenBinding.constant(); |
188 |
if (fieldConstant != Constant.NotAConstant) { |
203 |
if (fieldConstant != Constant.NotAConstant) { |
189 |
if (!isThisReceiver) { |
204 |
if (!isThisReceiver) { |
190 |
receiver.generateCode(currentScope, codeStream, !isStatic); |
205 |
this.receiver.generateCode(currentScope, codeStream, !isStatic); |
191 |
if (!isStatic){ |
206 |
if (!isStatic){ |
192 |
codeStream.invokeObjectGetClass(); |
207 |
codeStream.invokeObjectGetClass(); |
193 |
codeStream.pop(); |
208 |
codeStream.pop(); |
194 |
} |
209 |
} |
195 |
} |
210 |
} |
196 |
if (valueRequired) { |
211 |
if (valueRequired) { |
197 |
codeStream.generateConstant(fieldConstant, implicitConversion); |
212 |
codeStream.generateConstant(fieldConstant, this.implicitConversion); |
198 |
} |
213 |
} |
199 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
214 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
200 |
return; |
215 |
return; |
201 |
} |
216 |
} |
202 |
if (valueRequired |
217 |
if (valueRequired |
203 |
|| (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) |
218 |
|| (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) |
204 |
|| ((implicitConversion & TypeIds.UNBOXING) != 0) |
219 |
|| ((this.implicitConversion & TypeIds.UNBOXING) != 0) |
205 |
|| (this.genericCast != null)) { |
220 |
|| (this.genericCast != null)) { |
206 |
receiver.generateCode(currentScope, codeStream, !isStatic); |
221 |
this.receiver.generateCode(currentScope, codeStream, !isStatic); |
207 |
pc = codeStream.position; |
222 |
pc = codeStream.position; |
208 |
if (this.codegenBinding.declaringClass == null) { // array length |
223 |
if (this.codegenBinding.declaringClass == null) { // array length |
209 |
codeStream.arraylength(); |
224 |
codeStream.arraylength(); |
210 |
if (valueRequired) { |
225 |
if (valueRequired) { |
211 |
codeStream.generateImplicitConversion(implicitConversion); |
226 |
codeStream.generateImplicitConversion(this.implicitConversion); |
212 |
} else { |
227 |
} else { |
213 |
// could occur if !valueRequired but compliance >= 1.4 |
228 |
// could occur if !valueRequired but compliance >= 1.4 |
214 |
codeStream.pop(); |
229 |
codeStream.pop(); |
215 |
} |
230 |
} |
216 |
} else { |
231 |
} else { |
217 |
if (syntheticAccessors == null || syntheticAccessors[READ] == null) { |
232 |
if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { |
218 |
if (isStatic) { |
233 |
if (isStatic) { |
219 |
codeStream.getstatic(this.codegenBinding); |
234 |
codeStream.getstatic(this.codegenBinding); |
220 |
} else { |
235 |
} else { |
221 |
codeStream.getfield(this.codegenBinding); |
236 |
codeStream.getfield(this.codegenBinding); |
222 |
} |
237 |
} |
223 |
} else { |
238 |
} else { |
224 |
codeStream.invokestatic(syntheticAccessors[READ]); |
239 |
codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); |
225 |
} |
240 |
} |
226 |
// required cast must occur even if no value is required |
241 |
// required cast must occur even if no value is required |
227 |
if (this.genericCast != null) codeStream.checkcast(this.genericCast); |
242 |
if (this.genericCast != null) codeStream.checkcast(this.genericCast); |
228 |
if (valueRequired) { |
243 |
if (valueRequired) { |
229 |
codeStream.generateImplicitConversion(implicitConversion); |
244 |
codeStream.generateImplicitConversion(this.implicitConversion); |
230 |
} else { |
245 |
} else { |
231 |
boolean isUnboxing = (implicitConversion & TypeIds.UNBOXING) != 0; |
246 |
boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; |
232 |
// conversion only generated if unboxing |
247 |
// conversion only generated if unboxing |
233 |
if (isUnboxing) codeStream.generateImplicitConversion(implicitConversion); |
248 |
if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); |
234 |
switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.type.id) { |
249 |
switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.type.id) { |
235 |
case T_long : |
250 |
case T_long : |
236 |
case T_double : |
251 |
case T_double : |
Lines 246-252
Link Here
|
246 |
if (isStatic){ |
261 |
if (isStatic){ |
247 |
// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class |
262 |
// if no valueRequired, still need possible side-effects of <clinit> invocation, if field belongs to different class |
248 |
if (this.binding.original().declaringClass != this.receiverType.erasure()) { |
263 |
if (this.binding.original().declaringClass != this.receiverType.erasure()) { |
249 |
MethodBinding accessor = syntheticAccessors == null ? null : syntheticAccessors[READ]; |
264 |
MethodBinding accessor = this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.READ]; |
250 |
if (accessor == null) { |
265 |
if (accessor == null) { |
251 |
codeStream.getstatic(this.codegenBinding); |
266 |
codeStream.getstatic(this.codegenBinding); |
252 |
} else { |
267 |
} else { |
Lines 263-269
Link Here
|
263 |
} |
278 |
} |
264 |
} |
279 |
} |
265 |
} else { |
280 |
} else { |
266 |
receiver.generateCode(currentScope, codeStream, !isStatic); |
281 |
this.receiver.generateCode(currentScope, codeStream, !isStatic); |
267 |
if (!isStatic){ |
282 |
if (!isStatic){ |
268 |
codeStream.invokeObjectGetClass(); // perform null check |
283 |
codeStream.invokeObjectGetClass(); // perform null check |
269 |
codeStream.pop(); |
284 |
codeStream.pop(); |
Lines 275-300
Link Here
|
275 |
|
290 |
|
276 |
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { |
291 |
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { |
277 |
boolean isStatic; |
292 |
boolean isStatic; |
278 |
receiver.generateCode( |
293 |
this.receiver.generateCode( |
279 |
currentScope, |
294 |
currentScope, |
280 |
codeStream, |
295 |
codeStream, |
281 |
!(isStatic = this.codegenBinding.isStatic())); |
296 |
!(isStatic = this.codegenBinding.isStatic())); |
282 |
if (isStatic) { |
297 |
if (isStatic) { |
283 |
if (syntheticAccessors == null || syntheticAccessors[READ] == null) { |
298 |
if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { |
284 |
codeStream.getstatic(this.codegenBinding); |
299 |
codeStream.getstatic(this.codegenBinding); |
285 |
} else { |
300 |
} else { |
286 |
codeStream.invokestatic(syntheticAccessors[READ]); |
301 |
codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); |
287 |
} |
302 |
} |
288 |
} else { |
303 |
} else { |
289 |
codeStream.dup(); |
304 |
codeStream.dup(); |
290 |
if (syntheticAccessors == null || syntheticAccessors[READ] == null) { |
305 |
if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { |
291 |
codeStream.getfield(this.codegenBinding); |
306 |
codeStream.getfield(this.codegenBinding); |
292 |
} else { |
307 |
} else { |
293 |
codeStream.invokestatic(syntheticAccessors[READ]); |
308 |
codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); |
294 |
} |
309 |
} |
295 |
} |
310 |
} |
296 |
int operationTypeID; |
311 |
int operationTypeID; |
297 |
switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { |
312 |
switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) { |
298 |
case T_JavaLangString : |
313 |
case T_JavaLangString : |
299 |
case T_JavaLangObject : |
314 |
case T_JavaLangObject : |
300 |
case T_undefined : |
315 |
case T_undefined : |
Lines 304-313
Link Here
|
304 |
if (this.genericCast != null) |
319 |
if (this.genericCast != null) |
305 |
codeStream.checkcast(this.genericCast); |
320 |
codeStream.checkcast(this.genericCast); |
306 |
// promote the array reference to the suitable operation type |
321 |
// promote the array reference to the suitable operation type |
307 |
codeStream.generateImplicitConversion(implicitConversion); |
322 |
codeStream.generateImplicitConversion(this.implicitConversion); |
308 |
// generate the increment value (will by itself be promoted to the operation value) |
323 |
// generate the increment value (will by itself be promoted to the operation value) |
309 |
if (expression == IntLiteral.One) { // prefix operation |
324 |
if (expression == IntLiteral.One) { // prefix operation |
310 |
codeStream.generateConstant(expression.constant, implicitConversion); |
325 |
codeStream.generateConstant(expression.constant, this.implicitConversion); |
311 |
} else { |
326 |
} else { |
312 |
expression.generateCode(currentScope, codeStream, true); |
327 |
expression.generateCode(currentScope, codeStream, true); |
313 |
} |
328 |
} |
Lines 319-347
Link Here
|
319 |
fieldStore( |
334 |
fieldStore( |
320 |
codeStream, |
335 |
codeStream, |
321 |
this.codegenBinding, |
336 |
this.codegenBinding, |
322 |
syntheticAccessors == null ? null : syntheticAccessors[WRITE], |
337 |
this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], |
323 |
valueRequired); |
338 |
valueRequired); |
324 |
// no need for generic cast as value got dupped |
339 |
// no need for generic cast as value got dupped |
325 |
} |
340 |
} |
326 |
|
341 |
|
327 |
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { |
342 |
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { |
328 |
boolean isStatic; |
343 |
boolean isStatic; |
329 |
receiver.generateCode( |
344 |
this.receiver.generateCode( |
330 |
currentScope, |
345 |
currentScope, |
331 |
codeStream, |
346 |
codeStream, |
332 |
!(isStatic = this.codegenBinding.isStatic())); |
347 |
!(isStatic = this.codegenBinding.isStatic())); |
333 |
if (isStatic) { |
348 |
if (isStatic) { |
334 |
if (syntheticAccessors == null || syntheticAccessors[READ] == null) { |
349 |
if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { |
335 |
codeStream.getstatic(this.codegenBinding); |
350 |
codeStream.getstatic(this.codegenBinding); |
336 |
} else { |
351 |
} else { |
337 |
codeStream.invokestatic(syntheticAccessors[READ]); |
352 |
codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); |
338 |
} |
353 |
} |
339 |
} else { |
354 |
} else { |
340 |
codeStream.dup(); |
355 |
codeStream.dup(); |
341 |
if (syntheticAccessors == null || syntheticAccessors[READ] == null) { |
356 |
if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { |
342 |
codeStream.getfield(this.codegenBinding); |
357 |
codeStream.getfield(this.codegenBinding); |
343 |
} else { |
358 |
} else { |
344 |
codeStream.invokestatic(syntheticAccessors[READ]); |
359 |
codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); |
345 |
} |
360 |
} |
346 |
} |
361 |
} |
347 |
if (valueRequired) { |
362 |
if (valueRequired) { |
Lines 367-376
Link Here
|
367 |
codeStream.generateConstant( |
382 |
codeStream.generateConstant( |
368 |
postIncrement.expression.constant, |
383 |
postIncrement.expression.constant, |
369 |
this.implicitConversion); |
384 |
this.implicitConversion); |
370 |
codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK); |
385 |
codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); |
371 |
codeStream.generateImplicitConversion( |
386 |
codeStream.generateImplicitConversion( |
372 |
postIncrement.preAssignImplicitConversion); |
387 |
postIncrement.preAssignImplicitConversion); |
373 |
fieldStore(codeStream, this.codegenBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false); |
388 |
fieldStore(codeStream, this.codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE], false); |
374 |
} |
389 |
} |
375 |
|
390 |
|
376 |
/** |
391 |
/** |
Lines 380-390
Link Here
|
380 |
return null; |
395 |
return null; |
381 |
} |
396 |
} |
382 |
public boolean isSuperAccess() { |
397 |
public boolean isSuperAccess() { |
383 |
return receiver.isSuper(); |
398 |
return this.receiver.isSuper(); |
384 |
} |
399 |
} |
385 |
|
400 |
|
386 |
public boolean isTypeAccess() { |
401 |
public boolean isTypeAccess() { |
387 |
return receiver != null && receiver.isTypeReference(); |
402 |
return this.receiver != null && this.receiver.isTypeReference(); |
388 |
} |
403 |
} |
389 |
|
404 |
|
390 |
/* |
405 |
/* |
Lines 396-437
Link Here
|
396 |
// if field from parameterized type got found, use the original field at codegen time |
411 |
// if field from parameterized type got found, use the original field at codegen time |
397 |
this.codegenBinding = this.binding.original(); |
412 |
this.codegenBinding = this.binding.original(); |
398 |
|
413 |
|
399 |
if (binding.isPrivate()) { |
414 |
if (this.binding.isPrivate()) { |
400 |
if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) |
415 |
if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) |
401 |
&& binding.constant() == Constant.NotAConstant) { |
416 |
&& this.binding.constant() == Constant.NotAConstant) { |
402 |
if (syntheticAccessors == null) |
417 |
if (this.syntheticAccessors == null) |
403 |
syntheticAccessors = new MethodBinding[2]; |
418 |
this.syntheticAccessors = new MethodBinding[2]; |
404 |
syntheticAccessors[isReadAccess ? READ : WRITE] = |
419 |
this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = |
405 |
((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess); |
420 |
((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess); |
406 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
421 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
407 |
return; |
422 |
return; |
408 |
} |
423 |
} |
409 |
|
424 |
|
410 |
} else if (receiver instanceof QualifiedSuperReference) { // qualified super |
425 |
} else if (this.receiver instanceof QualifiedSuperReference) { // qualified super |
411 |
|
426 |
|
412 |
// qualified super need emulation always |
427 |
// qualified super need emulation always |
413 |
SourceTypeBinding destinationType = |
428 |
SourceTypeBinding destinationType = |
414 |
(SourceTypeBinding) (((QualifiedSuperReference) receiver) |
429 |
(SourceTypeBinding) (((QualifiedSuperReference) this.receiver) |
415 |
.currentCompatibleType); |
430 |
.currentCompatibleType); |
416 |
if (syntheticAccessors == null) |
431 |
if (this.syntheticAccessors == null) |
417 |
syntheticAccessors = new MethodBinding[2]; |
432 |
this.syntheticAccessors = new MethodBinding[2]; |
418 |
syntheticAccessors[isReadAccess ? READ : WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess); |
433 |
this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess); |
419 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
434 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
420 |
return; |
435 |
return; |
421 |
|
436 |
|
422 |
} else if (binding.isProtected()) { |
437 |
} else if (this.binding.isProtected()) { |
423 |
|
438 |
|
424 |
SourceTypeBinding enclosingSourceType; |
439 |
SourceTypeBinding enclosingSourceType; |
425 |
if (((bits & DepthMASK) != 0) |
440 |
if (((this.bits & ASTNode.DepthMASK) != 0) |
426 |
&& binding.declaringClass.getPackage() |
441 |
&& this.binding.declaringClass.getPackage() |
427 |
!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) { |
442 |
!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) { |
428 |
|
443 |
|
429 |
SourceTypeBinding currentCompatibleType = |
444 |
SourceTypeBinding currentCompatibleType = |
430 |
(SourceTypeBinding) enclosingSourceType.enclosingTypeAt( |
445 |
(SourceTypeBinding) enclosingSourceType.enclosingTypeAt( |
431 |
(bits & DepthMASK) >> DepthSHIFT); |
446 |
(this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); |
432 |
if (syntheticAccessors == null) |
447 |
if (this.syntheticAccessors == null) |
433 |
syntheticAccessors = new MethodBinding[2]; |
448 |
this.syntheticAccessors = new MethodBinding[2]; |
434 |
syntheticAccessors[isReadAccess ? READ : WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess); |
449 |
this.syntheticAccessors[isReadAccess ? FieldReference.READ : FieldReference.WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess); |
435 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
450 |
currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess); |
436 |
return; |
451 |
return; |
437 |
} |
452 |
} |
Lines 446-453
Link Here
|
446 |
&& this.binding.constant() == Constant.NotAConstant) { |
461 |
&& this.binding.constant() == Constant.NotAConstant) { |
447 |
CompilerOptions options = currentScope.compilerOptions(); |
462 |
CompilerOptions options = currentScope.compilerOptions(); |
448 |
if ((options.targetJDK >= ClassFileConstants.JDK1_2 |
463 |
if ((options.targetJDK >= ClassFileConstants.JDK1_2 |
449 |
&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(receiver.isImplicitThis() && this.codegenBinding.isStatic())) |
464 |
&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic())) |
450 |
&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields |
465 |
&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object fields |
451 |
|| !this.binding.declaringClass.canBeSeenBy(currentScope)) { |
466 |
|| !this.binding.declaringClass.canBeSeenBy(currentScope)) { |
452 |
|
467 |
|
453 |
this.codegenBinding = |
468 |
this.codegenBinding = |
Lines 479-485
Link Here
|
479 |
TypeBinding convertedType = this.resolvedType; |
494 |
TypeBinding convertedType = this.resolvedType; |
480 |
if (this.genericCast != null) |
495 |
if (this.genericCast != null) |
481 |
convertedType = this.genericCast; |
496 |
convertedType = this.genericCast; |
482 |
int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4; |
497 |
int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; |
483 |
switch (runtimeType) { |
498 |
switch (runtimeType) { |
484 |
case T_boolean : |
499 |
case T_boolean : |
485 |
convertedType = TypeBinding.BOOLEAN; |
500 |
convertedType = TypeBinding.BOOLEAN; |
Lines 507-520
Link Here
|
507 |
break; |
522 |
break; |
508 |
default : |
523 |
default : |
509 |
} |
524 |
} |
510 |
if ((this.implicitConversion & BOXING) != 0) { |
525 |
if ((this.implicitConversion & TypeIds.BOXING) != 0) { |
511 |
convertedType = scope.environment().computeBoxingType(convertedType); |
526 |
convertedType = scope.environment().computeBoxingType(convertedType); |
512 |
} |
527 |
} |
513 |
return convertedType; |
528 |
return convertedType; |
514 |
} |
529 |
} |
515 |
|
530 |
|
516 |
public StringBuffer printExpression(int indent, StringBuffer output) { |
531 |
public StringBuffer printExpression(int indent, StringBuffer output) { |
517 |
return receiver.printExpression(0, output).append('.').append(token); |
532 |
return this.receiver.printExpression(0, output).append('.').append(this.token); |
518 |
} |
533 |
} |
519 |
|
534 |
|
520 |
public TypeBinding resolveType(BlockScope scope) { |
535 |
public TypeBinding resolveType(BlockScope scope) { |
Lines 525-536
Link Here
|
525 |
//always ignore receiver cast, since may affect constant pool reference |
540 |
//always ignore receiver cast, since may affect constant pool reference |
526 |
boolean receiverCast = false; |
541 |
boolean receiverCast = false; |
527 |
if (this.receiver instanceof CastExpression) { |
542 |
if (this.receiver instanceof CastExpression) { |
528 |
this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on |
543 |
this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on |
529 |
receiverCast = true; |
544 |
receiverCast = true; |
530 |
} |
545 |
} |
531 |
this.receiverType = this.receiver.resolveType(scope); |
546 |
this.receiverType = this.receiver.resolveType(scope); |
532 |
if (this.receiverType == null) { |
547 |
if (this.receiverType == null) { |
533 |
constant = Constant.NotAConstant; |
548 |
this.constant = Constant.NotAConstant; |
534 |
return null; |
549 |
return null; |
535 |
} |
550 |
} |
536 |
if (receiverCast) { |
551 |
if (receiverCast) { |
Lines 540-548
Link Here
|
540 |
} |
555 |
} |
541 |
} |
556 |
} |
542 |
// the case receiverType.isArrayType and token = 'length' is handled by the scope API |
557 |
// the case receiverType.isArrayType and token = 'length' is handled by the scope API |
543 |
FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, token, this); |
558 |
FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this); |
544 |
if (!fieldBinding.isValidBinding()) { |
559 |
if (!fieldBinding.isValidBinding()) { |
545 |
constant = Constant.NotAConstant; |
560 |
this.constant = Constant.NotAConstant; |
546 |
if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { |
561 |
if (this.receiver.resolvedType instanceof ProblemReferenceBinding) { |
547 |
// problem already got signaled on receiver, do not report secondary problem |
562 |
// problem already got signaled on receiver, do not report secondary problem |
548 |
return null; |
563 |
return null; |
Lines 557-583
Link Here
|
557 |
} |
572 |
} |
558 |
} |
573 |
} |
559 |
this.receiver.computeConversion(scope, this.receiverType, this.receiverType); |
574 |
this.receiver.computeConversion(scope, this.receiverType, this.receiverType); |
560 |
if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) { |
575 |
if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0)) { |
561 |
scope.problemReporter().deprecatedField(fieldBinding, this); |
576 |
scope.problemReporter().deprecatedField(fieldBinding, this); |
562 |
} |
577 |
} |
563 |
boolean isImplicitThisRcv = receiver.isImplicitThis(); |
578 |
boolean isImplicitThisRcv = this.receiver.isImplicitThis(); |
564 |
constant = isImplicitThisRcv ? fieldBinding.constant() : Constant.NotAConstant; |
579 |
this.constant = isImplicitThisRcv ? fieldBinding.constant() : Constant.NotAConstant; |
565 |
if (fieldBinding.isStatic()) { |
580 |
if (fieldBinding.isStatic()) { |
566 |
// static field accessed through receiver? legal but unoptimal (optional warning) |
581 |
// static field accessed through receiver? legal but unoptimal (optional warning) |
567 |
if (!(isImplicitThisRcv |
582 |
if (!(isImplicitThisRcv |
568 |
|| (receiver instanceof NameReference |
583 |
|| (this.receiver instanceof NameReference |
569 |
&& (((NameReference) receiver).bits & Binding.TYPE) != 0))) { |
584 |
&& (((NameReference) this.receiver).bits & Binding.TYPE) != 0))) { |
570 |
scope.problemReporter().nonStaticAccessToStaticField(this, fieldBinding); |
585 |
scope.problemReporter().nonStaticAccessToStaticField(this, fieldBinding); |
571 |
} |
586 |
} |
|
|
587 |
ReferenceBinding declaringClass = this.binding.declaringClass; |
572 |
if (!isImplicitThisRcv |
588 |
if (!isImplicitThisRcv |
573 |
&& fieldBinding.declaringClass != receiverType |
589 |
&& declaringClass != this.receiverType |
574 |
&& fieldBinding.declaringClass.canBeSeenBy(scope)) { |
590 |
&& declaringClass.canBeSeenBy(scope)) { |
575 |
scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); |
591 |
scope.problemReporter().indirectAccessToStaticField(this, fieldBinding); |
576 |
} |
592 |
} |
|
|
593 |
// check if accessing enum static field in initializer |
594 |
if (declaringClass.isEnum()) { |
595 |
MethodScope methodScope = scope.methodScope(); |
596 |
SourceTypeBinding sourceType = scope.enclosingSourceType(); |
597 |
if (this.constant == Constant.NotAConstant |
598 |
&& !methodScope.isStatic |
599 |
&& (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body |
600 |
&& methodScope.isInsideInitializerOrConstructor()) { |
601 |
scope.problemReporter().enumStaticFieldUsedDuringInitialization(this.binding, this); |
602 |
} |
603 |
} |
577 |
} |
604 |
} |
578 |
TypeBinding fieldType = fieldBinding.type; |
605 |
TypeBinding fieldType = fieldBinding.type; |
579 |
if (fieldType != null) { |
606 |
if (fieldType != null) { |
580 |
if ((this.bits & IsStrictlyAssigned) == 0) { |
607 |
if ((this.bits & ASTNode.IsStrictlyAssigned) == 0) { |
581 |
fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access |
608 |
fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access |
582 |
} |
609 |
} |
583 |
this.resolvedType = fieldType; |
610 |
this.resolvedType = fieldType; |
Lines 594-602
Link Here
|
594 |
} |
621 |
} |
595 |
|
622 |
|
596 |
public void setDepth(int depth) { |
623 |
public void setDepth(int depth) { |
597 |
bits &= ~DepthMASK; // flush previous depth if any |
624 |
this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any |
598 |
if (depth > 0) { |
625 |
if (depth > 0) { |
599 |
bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits |
626 |
this.bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits |
600 |
} |
627 |
} |
601 |
} |
628 |
} |
602 |
|
629 |
|
Lines 606-612
Link Here
|
606 |
|
633 |
|
607 |
public void traverse(ASTVisitor visitor, BlockScope scope) { |
634 |
public void traverse(ASTVisitor visitor, BlockScope scope) { |
608 |
if (visitor.visit(this, scope)) { |
635 |
if (visitor.visit(this, scope)) { |
609 |
receiver.traverse(visitor, scope); |
636 |
this.receiver.traverse(visitor, scope); |
610 |
} |
637 |
} |
611 |
visitor.endVisit(this, scope); |
638 |
visitor.endVisit(this, scope); |
612 |
} |
639 |
} |