1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.CodeStream; 16 import org.eclipse.jdt.internal.compiler.flow.FlowContext; 17 import org.eclipse.jdt.internal.compiler.flow.FlowInfo; 18 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 19 import org.eclipse.jdt.internal.compiler.impl.Constant; 20 import org.eclipse.jdt.internal.compiler.lookup.Binding; 21 import org.eclipse.jdt.internal.compiler.lookup.BlockScope; 22 import org.eclipse.jdt.internal.compiler.lookup.ClassScope; 23 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 24 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; 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.ProblemFieldBinding; 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.SyntheticMethodBinding; 33 import org.eclipse.jdt.internal.compiler.lookup.TagBits; 34 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 35 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 36 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; 37 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; 38 39 public class QualifiedNameReference extends NameReference { 40 41 public char[][] tokens; 42 public long[] sourcePositions; 43 public FieldBinding[] otherBindings, otherCodegenBindings; 44 int[] otherDepths; 45 public int indexOfFirstFieldBinding; SyntheticMethodBinding syntheticWriteAccessor; 47 SyntheticMethodBinding[] syntheticReadAccessors; 48 public TypeBinding genericCast; 49 public TypeBinding[] otherGenericCasts; 50 51 public QualifiedNameReference( char[][] tokens, long[] positions, int sourceStart, int sourceEnd) { 52 this.tokens = tokens; 53 this.sourcePositions = positions; 54 this.sourceStart = sourceStart; 55 this.sourceEnd = sourceEnd; 56 } 57 58 public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { 59 int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; 61 boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); 62 boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; 63 FieldBinding lastFieldBinding = null; 64 switch (this.bits & ASTNode.RestrictiveFlagMASK) { 65 case Binding.FIELD : lastFieldBinding = (FieldBinding) this.binding; 67 if (needValue || complyTo14) { 68 manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo); 69 } 70 if (this.indexOfFirstFieldBinding == 1) { ReferenceBinding declaringClass = lastFieldBinding.declaringClass; 72 if (declaringClass.isEnum()) { 74 MethodScope methodScope = currentScope.methodScope(); 75 SourceTypeBinding sourceType = methodScope.enclosingSourceType(); 76 if (lastFieldBinding.isStatic() 77 && (sourceType == declaringClass || sourceType.superclass == declaringClass) && lastFieldBinding.constant() == Constant.NotAConstant 79 && !methodScope.isStatic 80 && methodScope.isInsideInitializerOrConstructor()) { 81 currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(lastFieldBinding, this); 82 } 83 } 84 } 85 if (lastFieldBinding.isBlankFinal() 87 && this.otherBindings != null && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { 89 if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) { 90 currentScope.problemReporter().uninitializedBlankFinalField( 91 lastFieldBinding, 92 this); 93 } 94 } 95 break; 96 case Binding.LOCAL : 97 LocalVariableBinding localBinding; 99 if (!flowInfo 100 .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { 101 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); 102 } 103 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 104 localBinding.useFlag = LocalVariableBinding.USED; 105 } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { 106 localBinding.useFlag = LocalVariableBinding.FAKE_USED; 107 } 108 checkNPE(currentScope, flowContext, flowInfo, true); 109 } 110 111 if (needValue) { 112 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); 113 } 115 if (this.otherBindings != null) { 117 for (int i = 0; i < otherBindingsCount-1; i++) { 118 lastFieldBinding = this.otherBindings[i]; 119 needValue = !this.otherBindings[i+1].isStatic(); 120 if (needValue || complyTo14) { 121 manageSyntheticAccessIfNecessary( 122 currentScope, 123 lastFieldBinding, 124 i == 0 125 ? ((VariableBinding)this.binding).type 126 : this.otherBindings[i-1].type, 127 i + 1, 128 flowInfo); 129 } 130 } 131 lastFieldBinding = this.otherBindings[otherBindingsCount-1]; 132 } 133 134 if (isCompound) { 135 if (otherBindingsCount == 0 136 && lastFieldBinding.isBlankFinal() 137 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding) 138 && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) { 139 currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this); 140 } 141 TypeBinding lastReceiverType; 142 switch (otherBindingsCount) { 143 case 0 : 144 lastReceiverType = this.actualReceiverType; 145 break; 146 case 1 : 147 lastReceiverType = ((VariableBinding)this.binding).type; 148 break; 149 default: 150 lastReceiverType = this.otherBindings[otherBindingsCount-2].type; 151 break; 152 } 153 manageSyntheticAccessIfNecessary( 154 currentScope, 155 lastFieldBinding, 156 lastReceiverType, 157 otherBindingsCount, 158 flowInfo); 159 } 160 161 if (assignment.expression != null) { 162 flowInfo = 163 assignment 164 .expression 165 .analyseCode(currentScope, flowContext, flowInfo) 166 .unconditionalInits(); 167 } 168 169 if (lastFieldBinding.isFinal()) { 171 if (otherBindingsCount == 0 173 && this.indexOfFirstFieldBinding == 1 174 && lastFieldBinding.isBlankFinal() 175 && !isCompound 176 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { 177 if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) { 178 currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this); 179 } else { 180 flowContext.recordSettingFinal(lastFieldBinding, this, flowInfo); 181 } 182 flowInfo.markAsDefinitelyAssigned(lastFieldBinding); 183 } else { 184 currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this); 185 if (otherBindingsCount == 0 && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { flowInfo.markAsDefinitelyAssigned(lastFieldBinding); 187 } 188 } 189 } 190 TypeBinding lastReceiverType; 192 switch (otherBindingsCount) { 193 case 0 : 194 lastReceiverType = this.actualReceiverType; 195 break; 196 case 1 : 197 lastReceiverType = ((VariableBinding)this.binding).type; 198 break; 199 default : 200 lastReceiverType = this.otherBindings[otherBindingsCount-2].type; 201 break; 202 } 203 manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 , flowInfo); 204 205 return flowInfo; 206 } 207 208 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 209 return analyseCode(currentScope, flowContext, flowInfo, true); 210 } 211 212 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { 213 int otherBindingsCount = this.otherBindings == null ? 0 : this.otherBindings.length; 215 216 boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic(); 217 boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; 218 switch (this.bits & ASTNode.RestrictiveFlagMASK) { 219 case Binding.FIELD : if (needValue || complyTo14) { 221 manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) this.binding, this.actualReceiverType, 0, flowInfo); 222 } 223 if (this.indexOfFirstFieldBinding == 1) { FieldBinding fieldBinding = (FieldBinding) this.binding; 225 ReferenceBinding declaringClass = fieldBinding.declaringClass; 226 if (declaringClass.isEnum()) { 228 MethodScope methodScope = currentScope.methodScope(); 229 SourceTypeBinding sourceType = methodScope.enclosingSourceType(); 230 if (fieldBinding.isStatic() 231 && (sourceType == declaringClass || sourceType.superclass == declaringClass) && fieldBinding.constant() == Constant.NotAConstant 233 && !methodScope.isStatic 234 && methodScope.isInsideInitializerOrConstructor()) { 235 currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); 236 } 237 } 238 if (fieldBinding.isBlankFinal() 240 && currentScope.allowBlankFinalFieldAssignment(fieldBinding) 241 && !flowInfo.isDefinitelyAssigned(fieldBinding)) { 242 currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); 243 } 244 } 245 break; 246 case Binding.LOCAL : LocalVariableBinding localBinding; 248 if (!flowInfo 249 .isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) { 250 currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); 251 } 252 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 253 localBinding.useFlag = LocalVariableBinding.USED; 254 } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { 255 localBinding.useFlag = LocalVariableBinding.FAKE_USED; 256 } 257 checkNPE(currentScope, flowContext, flowInfo, true); 258 } 259 if (needValue) { 260 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); 261 } 263 if (this.otherBindings != null) { 264 for (int i = 0; i < otherBindingsCount; i++) { 265 needValue = i < otherBindingsCount-1 ? !this.otherBindings[i+1].isStatic() : valueRequired; 266 if (needValue || complyTo14) { 267 TypeBinding lastReceiverType = getGenericCast(i); 268 if (lastReceiverType == null) { 269 if (i == 0) { 270 lastReceiverType = ((VariableBinding)this.binding).type; 271 } else { 272 lastReceiverType = this.otherBindings[i-1].type; 273 } 274 } 275 manageSyntheticAccessIfNecessary( 276 currentScope, 277 this.otherBindings[i], 278 lastReceiverType, 279 i + 1, 280 flowInfo); 281 } 282 } 283 } 284 return flowInfo; 285 } 286 287 290 public TypeBinding checkFieldAccess(BlockScope scope) { 291 FieldBinding fieldBinding = (FieldBinding) this.binding; 292 MethodScope methodScope = scope.methodScope(); 293 if (this.indexOfFirstFieldBinding == 1 295 && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass 296 && methodScope.lastVisibleFieldID >= 0 297 && fieldBinding.id >= methodScope.lastVisibleFieldID 298 && (!fieldBinding.isStatic() || methodScope.isStatic)) { 299 scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType()); 300 } 301 this.bits &= ~ASTNode.RestrictiveFlagMASK; this.bits |= Binding.FIELD; 303 return getOtherFieldBindings(scope); 304 } 305 306 public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) { 307 if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) { 310 LocalVariableBinding local = (LocalVariableBinding) this.binding; 311 if (local != null && 312 (local.type.tagBits & TagBits.IsBaseType) == 0 && 313 (checkString || local.type.id != TypeIds.T_JavaLangString)) { 314 if ((this.bits & ASTNode.IsNonNull) == 0) { 315 flowContext.recordUsingNullReference(scope, local, this, 316 FlowContext.MAY_NULL, flowInfo); 317 } 318 flowInfo.markAsComparedEqualToNonNull(local); 319 if (flowContext.initsOnFinally != null) { 321 flowContext.initsOnFinally.markAsComparedEqualToNonNull(local); 322 } 323 } 324 } 325 } 326 327 330 public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) { 331 if (runtimeTimeType == null || compileTimeType == null) 332 return; 333 FieldBinding field = null; 335 int length = this.otherBindings == null ? 0 : this.otherBindings.length; 336 if (length == 0) { 337 if ((this.bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) { 338 field = (FieldBinding) this.binding; 339 } 340 } else { 341 field = this.otherBindings[length-1]; 342 } 343 if (field != null) { 344 FieldBinding originalBinding = field.original(); 345 TypeBinding originalType = originalBinding.type; 346 if (originalBinding != field 348 && originalType != field.type 349 && runtimeTimeType.id != TypeIds.T_JavaLangObject 350 && (originalType.tagBits & TagBits.HasTypeVariable) != 0) { 351 TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 352 ? compileTimeType : runtimeTimeType; 354 setGenericCast(length, originalType.genericCast(targetType)); 355 } 356 } 357 super.computeConversion(scope, runtimeTimeType, compileTimeType); 358 } 359 360 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { 361 int pc = codeStream.position; 362 FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 363 codeStream.recordPositionsFrom(pc , this.sourceStart); 364 assignment.expression.generateCode(currentScope, codeStream, true); 365 fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired); 366 if (valueRequired) { 368 codeStream.generateImplicitConversion(assignment.implicitConversion); 369 } 370 } 371 372 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 373 int pc = codeStream.position; 374 if (this.constant != Constant.NotAConstant) { 375 if (valueRequired) { 376 codeStream.generateConstant(this.constant, this.implicitConversion); 377 } 378 } else { 379 FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 380 if (lastFieldBinding != null) { 381 boolean isStatic = lastFieldBinding.isStatic(); 382 Constant fieldConstant = lastFieldBinding.constant(); 383 if (fieldConstant != Constant.NotAConstant) { 384 if (!isStatic){ 385 codeStream.invokeObjectGetClass(); 386 codeStream.pop(); 387 } 388 if (valueRequired) { codeStream.generateConstant(fieldConstant, this.implicitConversion); 390 } 391 } else { 392 boolean isFirst = lastFieldBinding == this.binding 393 && (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType()) 394 && this.otherBindings == null; TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); 396 if (valueRequired 397 || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) 398 || ((this.implicitConversion & TypeIds.UNBOXING) != 0) 399 || requiredGenericCast != null) { 400 int lastFieldPc = codeStream.position; 401 if (lastFieldBinding.declaringClass == null) { codeStream.arraylength(); 403 if (valueRequired) { 404 codeStream.generateImplicitConversion(this.implicitConversion); 405 } else { 406 codeStream.pop(); 408 } 409 } else { 410 SyntheticMethodBinding accessor = 411 this.syntheticReadAccessors == null 412 ? null 413 : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; 414 if (accessor == null) { 415 if (isStatic) { 416 codeStream.getstatic(lastFieldBinding); 417 } else { 418 codeStream.getfield(lastFieldBinding); 419 } 420 } else { 421 codeStream.invokestatic(accessor); 422 } 423 if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); 424 if (valueRequired) { 425 codeStream.generateImplicitConversion(this.implicitConversion); 426 } else { 427 boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; 428 if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); 430 switch (isUnboxing ? postConversionType(currentScope).id : lastFieldBinding.type.id) { 431 case T_long : 432 case T_double : 433 codeStream.pop2(); 434 break; 435 default : 436 codeStream.pop(); 437 } 438 } 439 } 440 441 int fieldPosition = (int) (this.sourcePositions[this.sourcePositions.length - 1] >>> 32); 442 codeStream.recordPositionsFrom(lastFieldPc, fieldPosition); 443 } else { 444 if (!isStatic){ 445 codeStream.invokeObjectGetClass(); codeStream.pop(); 447 } 448 } 449 } 450 } 451 } 452 codeStream.recordPositionsFrom(pc, this.sourceStart); 453 } 454 455 public void generateCompoundAssignment( 456 BlockScope currentScope, 457 CodeStream codeStream, 458 Expression expression, 459 int operator, 460 int assignmentImplicitConversion, 461 boolean valueRequired) { 462 463 FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 464 SyntheticMethodBinding accessor = 465 this.syntheticReadAccessors == null 466 ? null 467 : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; 468 if (lastFieldBinding.isStatic()) { 469 if (accessor == null) { 470 codeStream.getstatic(lastFieldBinding); 471 } else { 472 codeStream.invokestatic(accessor); 473 } 474 } else { 475 codeStream.dup(); 476 if (accessor == null) { 477 codeStream.getfield(lastFieldBinding); 478 } else { 479 codeStream.invokestatic(accessor); 480 } 481 } 482 int operationTypeID; 485 switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) { 486 case T_JavaLangString : 487 case T_JavaLangObject : 488 case T_undefined : 489 codeStream.generateStringConcatenationAppend(currentScope, null, expression); 490 break; 491 default : 492 TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); 493 if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); 494 codeStream.generateImplicitConversion(this.implicitConversion); 496 if (expression == IntLiteral.One) { codeStream.generateConstant(expression.constant, this.implicitConversion); 499 } else { 500 expression.generateCode(currentScope, codeStream, true); 501 } 502 codeStream.sendOperator(operator, operationTypeID); 504 codeStream.generateImplicitConversion(assignmentImplicitConversion); 506 } 507 fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, valueRequired); 509 } 511 512 public void generatePostIncrement( 513 BlockScope currentScope, 514 CodeStream codeStream, 515 CompoundAssignment postIncrement, 516 boolean valueRequired) { 517 518 FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream); 519 SyntheticMethodBinding accessor = 520 this.syntheticReadAccessors == null 521 ? null 522 : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1]; 523 if (lastFieldBinding.isStatic()) { 524 if (accessor == null) { 525 codeStream.getstatic(lastFieldBinding); 526 } else { 527 codeStream.invokestatic(accessor); 528 } 529 } else { 530 codeStream.dup(); 531 if (accessor == null) { 532 codeStream.getfield(lastFieldBinding); 533 } else { 534 codeStream.invokestatic(accessor); 535 } 536 } 537 if (valueRequired) { 539 if (lastFieldBinding.isStatic()) { 540 if ((lastFieldBinding.type == TypeBinding.LONG) 541 || (lastFieldBinding.type == TypeBinding.DOUBLE)) { 542 codeStream.dup2(); 543 } else { 544 codeStream.dup(); 545 } 546 } else { if ((lastFieldBinding.type == TypeBinding.LONG) 548 || (lastFieldBinding.type == TypeBinding.DOUBLE)) { 549 codeStream.dup2_x1(); 550 } else { 551 codeStream.dup_x1(); 552 } 553 } 554 } 555 TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); 556 if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); 557 558 codeStream.generateImplicitConversion(this.implicitConversion); 559 codeStream.generateConstant( 560 postIncrement.expression.constant, 561 this.implicitConversion); 562 codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); 563 codeStream.generateImplicitConversion( 564 postIncrement.preAssignImplicitConversion); 565 fieldStore(codeStream, lastFieldBinding, this.syntheticWriteAccessor, false); 566 } 567 568 572 public FieldBinding generateReadSequence(BlockScope currentScope, CodeStream codeStream) { 573 int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length; 575 boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); 576 FieldBinding lastFieldBinding = null; 577 TypeBinding lastGenericCast = null; 578 boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4; 579 580 switch (this.bits & ASTNode.RestrictiveFlagMASK) { 581 case Binding.FIELD : 582 lastFieldBinding = (FieldBinding) this.codegenBinding; 583 lastGenericCast = this.genericCast; 584 if (lastFieldBinding.constant() != Constant.NotAConstant) { 586 break; 587 } 588 if ((needValue && !lastFieldBinding.isStatic()) || lastGenericCast != null) { 589 int pc = codeStream.position; 590 if ((this.bits & ASTNode.DepthMASK) != 0) { 591 ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); 592 Object [] emulationPath = currentScope.getEmulationPath(targetType, true , false); 593 codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); 594 } else { 595 generateReceiver(codeStream); 596 } 597 codeStream.recordPositionsFrom(pc, this.sourceStart); 598 } 599 break; 600 case Binding.LOCAL : if (!needValue) break; LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; 603 Constant localConstant = localBinding.constant(); 605 if (localConstant != Constant.NotAConstant) { 606 codeStream.generateConstant(localConstant, 0); 607 } else { 609 if ((this.bits & ASTNode.DepthMASK) != 0) { 611 VariableBinding[] path = currentScope.getEmulationPath(localBinding); 613 codeStream.generateOuterAccess(path, this, localBinding, currentScope); 614 } else { 615 codeStream.load(localBinding); 616 } 617 } 618 } 619 620 int positionsLength = this.sourcePositions.length; 623 if (this.otherCodegenBindings != null) { 624 for (int i = 0; i < otherBindingsCount; i++) { 625 int pc = codeStream.position; 626 FieldBinding nextField = this.otherCodegenBindings[i]; 627 TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i]; 628 if (lastFieldBinding != null) { 629 needValue = !nextField.isStatic(); 630 Constant fieldConstant = lastFieldBinding.constant(); 631 if (fieldConstant != Constant.NotAConstant) { 632 if (i > 0 && !lastFieldBinding.isStatic()) { 633 codeStream.invokeObjectGetClass(); codeStream.pop(); 635 } 636 if (needValue) { 637 codeStream.generateConstant(fieldConstant, 0); 638 } 639 } else { 640 if (needValue || (i > 0 && complyTo14) || lastGenericCast != null) { 641 MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; 642 if (accessor == null) { 643 if (lastFieldBinding.isStatic()) { 644 codeStream.getstatic(lastFieldBinding); 645 } else { 646 codeStream.getfield(lastFieldBinding); 647 } 648 } else { 649 codeStream.invokestatic(accessor); 650 } 651 if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); 652 if (!needValue) codeStream.pop(); 653 } else { 654 if (this.codegenBinding == lastFieldBinding) { 655 if (lastFieldBinding.isStatic()){ 656 if (((FieldBinding)this.binding).original().declaringClass != this.actualReceiverType.erasure()) { 658 MethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[i]; 659 if (accessor == null) { 660 codeStream.getstatic(lastFieldBinding); 661 } else { 662 codeStream.invokestatic(accessor); 663 } 664 codeStream.pop(); 665 } 666 } 667 } else if (!lastFieldBinding.isStatic()){ 668 codeStream.invokeObjectGetClass(); codeStream.pop(); 670 } 671 } 672 if ((positionsLength - otherBindingsCount + i - 1) >= 0) { 673 int fieldPosition = (int) (this.sourcePositions[positionsLength - otherBindingsCount + i - 1] >>>32); 674 codeStream.recordPositionsFrom(pc, fieldPosition); 675 } 676 } 677 } 678 lastFieldBinding = nextField; 679 lastGenericCast = nextGenericCast; 680 } 681 } 682 return lastFieldBinding; 683 } 684 685 public void generateReceiver(CodeStream codeStream) { 686 codeStream.aload_0(); 687 } 688 689 692 public TypeBinding[] genericTypeArguments() { 693 return null; 694 } 695 696 protected FieldBinding getCodegenBinding(int index) { 698 if (index == 0){ 699 return (FieldBinding)this.codegenBinding; 700 } else { 701 return this.otherCodegenBindings[index-1]; 702 } 703 } 704 705 protected TypeBinding getGenericCast(int index) { 707 if (index == 0){ 708 return this.genericCast; 709 } else { 710 if (this.otherGenericCasts == null) return null; 711 return this.otherGenericCasts[index-1]; 712 } 713 } 714 715 public TypeBinding getOtherFieldBindings(BlockScope scope) { 716 int length = this.tokens.length; 718 FieldBinding field; 719 if ((this.bits & Binding.FIELD) != 0) { 720 field = (FieldBinding) this.binding; 721 if (!field.isStatic()) { 722 if (this.indexOfFirstFieldBinding > 1 || scope.methodScope().isStatic) { scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field); 726 return null; 727 } 728 } else { 729 if (this.indexOfFirstFieldBinding > 1 731 && field.declaringClass != this.actualReceiverType 732 && field.declaringClass.canBeSeenBy(scope)) { 733 scope.problemReporter().indirectAccessToStaticField(this, field); 734 } 735 } 736 if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) != 0 && this.indexOfFirstFieldBinding == length)) 738 scope.problemReporter().deprecatedField(field, this); 739 } else { 740 field = null; 741 } 742 TypeBinding type = ((VariableBinding) this.binding).type; 743 int index = this.indexOfFirstFieldBinding; 744 if (index == length) { this.constant = ((FieldBinding) this.binding).constant(); 746 return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0) 748 ? type.capture(scope, this.sourceEnd) 749 : type; 750 } 751 int otherBindingsLength = length - index; 753 this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength]; 754 this.otherDepths = new int[otherBindingsLength]; 755 756 this.constant = ((VariableBinding) this.binding).constant(); 758 int firstDepth = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT; 760 while (index < length) { 762 char[] token = this.tokens[index]; 763 if (type == null) 764 return null; 766 this.bits &= ~ASTNode.DepthMASK; FieldBinding previousField = field; 768 field = scope.getField(type.capture(scope, (int)this.sourcePositions[index]), token, this); 769 int place = index - this.indexOfFirstFieldBinding; 770 this.otherBindings[place] = field; 771 this.otherDepths[place] = (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT; 772 if (field.isValidBinding()) { 773 if (previousField != null) { 775 TypeBinding fieldReceiverType = type; 776 TypeBinding receiverErasure = type.erasure(); 777 if (receiverErasure instanceof ReferenceBinding) { 778 if (receiverErasure.findSuperTypeWithSameErasure(field.declaringClass) == null) { 779 fieldReceiverType = field.declaringClass; } 781 } 782 FieldBinding originalBinding = previousField.original(); 783 if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && fieldReceiverType.id != TypeIds.T_JavaLangObject) { 784 setGenericCast(index-1,originalBinding.type.genericCast(fieldReceiverType)); } 786 } 787 if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) !=0 && index+1 == length)) { 789 scope.problemReporter().deprecatedField(field, this); 790 } 791 if (this.constant != Constant.NotAConstant) { 793 this.constant = field.constant(); 794 } 795 796 if (field.isStatic()) { 797 scope.problemReporter().nonStaticAccessToStaticField(this, field); 799 if (field.declaringClass != type) { 801 scope.problemReporter().indirectAccessToStaticField(this, field); 802 } 803 } 804 type = field.type; 805 index++; 806 } else { 807 this.constant = Constant.NotAConstant; scope.problemReporter().invalidField(this, field, index, type); 809 setDepth(firstDepth); 810 return null; 811 } 812 } 813 setDepth(firstDepth); 814 type = (this.otherBindings[otherBindingsLength - 1]).type; 815 return (type != null && (this.bits & ASTNode.IsStrictlyAssigned) == 0) 817 ? type.capture(scope, this.sourceEnd) 818 : type; 819 } 820 821 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 822 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 823 if (((this.bits & ASTNode.DepthMASK) == 0) || (this.constant != Constant.NotAConstant)) { 825 return; 826 } 827 if ((this.bits & ASTNode.RestrictiveFlagMASK) == Binding.LOCAL) { 828 currentScope.emulateOuterAccess((LocalVariableBinding) this.binding); 829 } 830 } 831 } 832 833 836 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FieldBinding fieldBinding, TypeBinding lastReceiverType, int index, FlowInfo flowInfo) { 837 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; 838 if (fieldBinding.constant() != Constant.NotAConstant) 840 return; 841 842 FieldBinding originalField = fieldBinding.original(); 844 if (originalField != fieldBinding) { 845 setCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, originalField); 846 } 847 848 if (fieldBinding.isPrivate()) { FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); 850 if (someCodegenBinding.declaringClass != currentScope.enclosingSourceType()) { 851 setSyntheticAccessor(fieldBinding, index, 852 ((SourceTypeBinding) someCodegenBinding.declaringClass).addSyntheticMethod(someCodegenBinding, index >= 0 )); 853 currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 ); 854 return; 855 } 856 } else if (fieldBinding.isProtected()){ 857 int depth = (index == 0 || (index < 0 && this.otherDepths == null)) 858 ? (this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT 859 : this.otherDepths[index < 0 ? this.otherDepths.length-1 : index-1]; 860 861 if (depth > 0 && (fieldBinding.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage())) { 863 FieldBinding someCodegenBinding = getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index); 864 setSyntheticAccessor(fieldBinding, index, 865 ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth)).addSyntheticMethod(someCodegenBinding, index >= 0 )); 866 currentScope.problemReporter().needToEmulateFieldAccess(someCodegenBinding, this, index >= 0 ); 867 return; 868 } 869 } 870 if (fieldBinding.declaringClass != lastReceiverType 875 && !lastReceiverType.isArrayType() 876 && fieldBinding.declaringClass != null && fieldBinding.constant() == Constant.NotAConstant) { 878 CompilerOptions options = currentScope.compilerOptions(); 879 if ((options.targetJDK >= ClassFileConstants.JDK1_2 880 && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 && this.indexOfFirstFieldBinding == 1 && fieldBinding.isStatic())) 881 && fieldBinding.declaringClass.id != TypeIds.T_JavaLangObject) || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { 883 884 setCodegenBinding( 885 index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index, 886 currentScope.enclosingSourceType().getUpdatedFieldBinding( 887 getCodegenBinding(index < 0 ? (this.otherBindings == null ? 0 : this.otherBindings.length) : index), 888 (ReferenceBinding)lastReceiverType.erasure())); 889 } 890 } 891 } 892 893 public int nullStatus(FlowInfo flowInfo) { 894 return FlowInfo.UNKNOWN; 895 } 896 897 public Constant optimizedBooleanConstant() { 898 switch (this.resolvedType.id) { 899 case T_boolean : 900 case T_JavaLangBoolean : 901 if (this.constant != Constant.NotAConstant) return this.constant; 902 switch (this.bits & ASTNode.RestrictiveFlagMASK) { 903 case Binding.FIELD : if (this.otherBindings == null) 905 return ((FieldBinding)this.binding).constant(); 906 case Binding.LOCAL : return this.otherBindings[this.otherBindings.length-1].constant(); 909 } 910 } 911 return Constant.NotAConstant; 912 } 913 914 917 public TypeBinding postConversionType(Scope scope) { 918 TypeBinding convertedType = this.resolvedType; 919 TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); 920 if (requiredGenericCast != null) 921 convertedType = requiredGenericCast; 922 int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; 923 switch (runtimeType) { 924 case T_boolean : 925 convertedType = TypeBinding.BOOLEAN; 926 break; 927 case T_byte : 928 convertedType = TypeBinding.BYTE; 929 break; 930 case T_short : 931 convertedType = TypeBinding.SHORT; 932 break; 933 case T_char : 934 convertedType = TypeBinding.CHAR; 935 break; 936 case T_int : 937 convertedType = TypeBinding.INT; 938 break; 939 case T_float : 940 convertedType = TypeBinding.FLOAT; 941 break; 942 case T_long : 943 convertedType = TypeBinding.LONG; 944 break; 945 case T_double : 946 convertedType = TypeBinding.DOUBLE; 947 break; 948 default : 949 } 950 if ((this.implicitConversion & TypeIds.BOXING) != 0) { 951 convertedType = scope.environment().computeBoxingType(convertedType); 952 } 953 return convertedType; 954 } 955 956 public StringBuffer printExpression(int indent, StringBuffer output) { 957 for (int i = 0; i < this.tokens.length; i++) { 958 if (i > 0) output.append('.'); 959 output.append(this.tokens[i]); 960 } 961 return output; 962 } 963 964 967 public TypeBinding reportError(BlockScope scope) { 968 if (this.binding instanceof ProblemFieldBinding) { 969 scope.problemReporter().invalidField(this, (FieldBinding) this.binding); 970 } else if (this.binding instanceof ProblemReferenceBinding) { 971 scope.problemReporter().invalidType(this, (TypeBinding) this.binding); 972 } else { 973 scope.problemReporter().unresolvableReference(this, this.binding); 974 } 975 return null; 976 } 977 978 public TypeBinding resolveType(BlockScope scope) { 979 this.actualReceiverType = scope.enclosingReceiverType(); 983 this.constant = Constant.NotAConstant; 984 if ((this.codegenBinding = this.binding = scope.getBinding(this.tokens, this.bits & ASTNode.RestrictiveFlagMASK, this, true )).isValidBinding()) { 985 switch (this.bits & ASTNode.RestrictiveFlagMASK) { 986 case Binding.VARIABLE : case Binding.TYPE | Binding.VARIABLE : 988 if (this.binding instanceof LocalVariableBinding) { 989 if (!((LocalVariableBinding) this.binding).isFinal() && ((this.bits & ASTNode.DepthMASK) != 0)) 990 scope.problemReporter().cannotReferToNonFinalOuterLocal( 991 (LocalVariableBinding) this.binding, 992 this); 993 this.bits &= ~ASTNode.RestrictiveFlagMASK; this.bits |= Binding.LOCAL; 995 return this.resolvedType = getOtherFieldBindings(scope); 996 } 997 if (this.binding instanceof FieldBinding) { 998 FieldBinding fieldBinding = (FieldBinding) this.binding; 999 MethodScope methodScope = scope.methodScope(); 1000 if (this.indexOfFirstFieldBinding == 1 1002 && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass 1003 && methodScope.lastVisibleFieldID >= 0 1004 && fieldBinding.id >= methodScope.lastVisibleFieldID 1005 && (!fieldBinding.isStatic() || methodScope.isStatic)) { 1006 scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType()); 1007 } 1008 if (!fieldBinding.isStatic() 1009 && this.indexOfFirstFieldBinding == 1 1010 && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) { 1011 scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding); 1012 } 1013 this.bits &= ~ASTNode.RestrictiveFlagMASK; this.bits |= Binding.FIELD; 1015 1016 1023 return this.resolvedType = getOtherFieldBindings(scope); 1024 } 1025 this.bits &= ~ASTNode.RestrictiveFlagMASK; this.bits |= Binding.TYPE; 1028 case Binding.TYPE : TypeBinding type = (TypeBinding) this.binding; 1030 type = scope.environment().convertToRawType(type); 1033 return this.resolvedType = type; 1034 } 1035 } 1036 return this.resolvedType = this.reportError(scope); 1038} 1039 1040protected void setCodegenBinding(int index, FieldBinding someCodegenBinding) { 1042 if (index == 0){ 1043 this.codegenBinding = someCodegenBinding; 1044 } else { 1045 int length = this.otherBindings.length; 1046 if (this.otherCodegenBindings == this.otherBindings){ 1047 System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[length], 0, length); 1048 } 1049 this.otherCodegenBindings[index-1] = someCodegenBinding; 1050 } 1051} 1052 1053public void setFieldIndex(int index) { 1054 this.indexOfFirstFieldBinding = index; 1055} 1056 1057protected void setGenericCast(int index, TypeBinding someGenericCast) { 1059 if (index == 0){ 1060 this.genericCast = someGenericCast; 1061 } else { 1062 if (this.otherGenericCasts == null) { 1063 this.otherGenericCasts = new TypeBinding[this.otherBindings.length]; 1064 } 1065 this.otherGenericCasts[index-1] = someGenericCast; 1066 } 1067} 1068 1069protected void setSyntheticAccessor(FieldBinding fieldBinding, int index, SyntheticMethodBinding syntheticAccessor) { 1071 if (index < 0) { this.syntheticWriteAccessor = syntheticAccessor; 1073 } else { 1074 if (this.syntheticReadAccessors == null) { 1075 this.syntheticReadAccessors = new SyntheticMethodBinding[this.otherBindings == null ? 1 : this.otherBindings.length + 1]; 1076 } 1077 this.syntheticReadAccessors[index] = syntheticAccessor; 1078 } 1079} 1080 1081public void traverse(ASTVisitor visitor, BlockScope scope) { 1082 visitor.visit(this, scope); 1083 visitor.endVisit(this, scope); 1084} 1085 1086public void traverse(ASTVisitor visitor, ClassScope scope) { 1087 visitor.visit(this, scope); 1088 visitor.endVisit(this, scope); 1089} 1090 1091public String unboundReferenceErrorName() { 1092 return new String (this.tokens[0]); 1093} 1094} 1095 | Popular Tags |