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.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 EqualExpression extends BinaryExpression { 21 22 public EqualExpression(Expression left, Expression right,int operator) { 23 super(left,right,operator); 24 } 25 private void checkNullComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse) { 26 27 LocalVariableBinding local = this.left.localVariableBinding(); 28 if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { 29 checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, right.nullStatus(flowInfo), this.left); 30 } 31 local = this.right.localVariableBinding(); 32 if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { 33 checkVariableComparison(scope, flowContext, flowInfo, initsWhenTrue, initsWhenFalse, local, left.nullStatus(flowInfo), this.right); 34 } 35 } 36 private void checkVariableComparison(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, FlowInfo initsWhenTrue, FlowInfo initsWhenFalse, LocalVariableBinding local, int nullStatus, Expression reference) { 37 switch (nullStatus) { 38 case FlowInfo.NULL : 39 if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { 40 flowContext.recordUsingNullReference(scope, local, reference, 41 FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo); 42 initsWhenTrue.markAsComparedEqualToNull(local); initsWhenFalse.markAsComparedEqualToNonNull(local); } else { 45 flowContext.recordUsingNullReference(scope, local, reference, 46 FlowContext.CAN_ONLY_NULL_NON_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo); 47 initsWhenTrue.markAsComparedEqualToNonNull(local); initsWhenFalse.markAsComparedEqualToNull(local); } 50 break; 51 case FlowInfo.NON_NULL : 52 if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { 53 flowContext.recordUsingNullReference(scope, local, reference, 54 FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NON_NULL, flowInfo); 55 initsWhenTrue.markAsComparedEqualToNonNull(local); } else { 57 flowContext.recordUsingNullReference(scope, local, reference, 58 FlowContext.CAN_ONLY_NULL | FlowContext.IN_COMPARISON_NULL, flowInfo); 59 } 60 break; 61 } 62 } 65 66 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 67 FlowInfo result; 68 if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { 69 if ((left.constant != Constant.NotAConstant) && (left.constant.typeID() == T_boolean)) { 70 if (left.constant.booleanValue()) { result = right.analyseCode(currentScope, flowContext, flowInfo); 73 } else { result = right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); 76 } 77 } 78 else if ((right.constant != Constant.NotAConstant) && (right.constant.typeID() == T_boolean)) { 79 if (right.constant.booleanValue()) { result = left.analyseCode(currentScope, flowContext, flowInfo); 82 } else { result = left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); 85 } 86 } 87 else { 88 result = right.analyseCode( 89 currentScope, flowContext, 90 left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits(); 91 } 92 } else { if ((left.constant != Constant.NotAConstant) && (left.constant.typeID() == T_boolean)) { 94 if (!left.constant.booleanValue()) { result = right.analyseCode(currentScope, flowContext, flowInfo); 97 } else { result = right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); 100 } 101 } 102 else if ((right.constant != Constant.NotAConstant) && (right.constant.typeID() == T_boolean)) { 103 if (!right.constant.booleanValue()) { result = left.analyseCode(currentScope, flowContext, flowInfo); 106 } else { result = left.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition(); 109 } 110 } 111 else { 112 result = right.analyseCode( 113 currentScope, flowContext, 114 left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()). 115 116 unconditionalInits(); 117 } 118 } 119 if (result instanceof UnconditionalFlowInfo && 120 (result.tagBits & FlowInfo.UNREACHABLE) == 0) { result = FlowInfo.conditional(result.copy(), result.copy()); 122 } 124 checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse()); 125 return result; 126 } 127 128 public final void computeConstant(TypeBinding leftType, TypeBinding rightType) { 129 if ((this.left.constant != Constant.NotAConstant) && (this.right.constant != Constant.NotAConstant)) { 130 this.constant = 131 Constant.computeConstantOperationEQUAL_EQUAL( 132 left.constant, 133 leftType.id, 134 right.constant, 135 rightType.id); 136 if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL) 137 constant = BooleanConstant.fromValue(!constant.booleanValue()); 138 } else { 139 this.constant = Constant.NotAConstant; 140 } 142 } 143 150 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 151 152 int pc = codeStream.position; 153 if (constant != Constant.NotAConstant) { 154 if (valueRequired) 155 codeStream.generateConstant(constant, implicitConversion); 156 codeStream.recordPositionsFrom(pc, this.sourceStart); 157 return; 158 } 159 160 if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) { 161 generateBooleanEqual(currentScope, codeStream, valueRequired); 162 } else { 163 generateNonBooleanEqual(currentScope, codeStream, valueRequired); 164 } 165 if (valueRequired) { 166 codeStream.generateImplicitConversion(implicitConversion); 167 } 168 codeStream.recordPositionsFrom(pc, this.sourceStart); 169 } 170 174 public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 175 176 if (constant != Constant.NotAConstant) { 177 super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired); 178 return; 179 } 180 if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { 181 if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) { 182 generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); 183 } else { 184 generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired); 185 } 186 } else { 187 if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) { 188 generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); 189 } else { 190 generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired); 191 } 192 } 193 } 194 195 200 public void generateBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 201 202 boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL; 205 Constant cst = left.optimizedBooleanConstant(); 206 if (cst != Constant.NotAConstant) { 207 Constant rightCst = right.optimizedBooleanConstant(); 208 if (rightCst != Constant.NotAConstant) { 209 left.generateCode(currentScope, codeStream, false); 212 right.generateCode(currentScope, codeStream, false); 213 if (valueRequired) { 214 boolean leftBool = cst.booleanValue(); 215 boolean rightBool = rightCst.booleanValue(); 216 if (isEqualOperator) { 217 if (leftBool == rightBool) { 218 codeStream.iconst_1(); 219 } else { 220 codeStream.iconst_0(); 221 } 222 } else { 223 if (leftBool != rightBool) { 224 codeStream.iconst_1(); 225 } else { 226 codeStream.iconst_0(); 227 } 228 } 229 } 230 } else if (cst.booleanValue() == isEqualOperator) { 231 left.generateCode(currentScope, codeStream, false); 233 right.generateCode(currentScope, codeStream, valueRequired); 234 } else { 235 if (valueRequired) { 237 BranchLabel falseLabel = new BranchLabel(codeStream); 238 left.generateCode(currentScope, codeStream, false); 239 right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired); 240 codeStream.iconst_0(); 242 if ((bits & IsReturnedValue) != 0){ 243 codeStream.generateImplicitConversion(this.implicitConversion); 244 codeStream.generateReturnBytecode(this); 245 falseLabel.place(); 247 codeStream.iconst_1(); 248 } else { 249 BranchLabel endLabel = new BranchLabel(codeStream); 250 codeStream.goto_(endLabel); 251 codeStream.decrStackSize(1); 252 falseLabel.place(); 254 codeStream.iconst_1(); 255 endLabel.place(); 256 } 257 } else { 258 left.generateCode(currentScope, codeStream, false); 259 right.generateCode(currentScope, codeStream, false); 260 } 261 } 268 return; 269 } 270 cst = right.optimizedBooleanConstant(); 271 if (cst != Constant.NotAConstant) { 272 if (cst.booleanValue() == isEqualOperator) { 273 left.generateCode(currentScope, codeStream, valueRequired); 275 right.generateCode(currentScope, codeStream, false); 276 } else { 277 if (valueRequired) { 279 BranchLabel falseLabel = new BranchLabel(codeStream); 280 left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired); 281 right.generateCode(currentScope, codeStream, false); 282 codeStream.iconst_0(); 284 if ((bits & IsReturnedValue) != 0){ 285 codeStream.generateImplicitConversion(this.implicitConversion); 286 codeStream.generateReturnBytecode(this); 287 falseLabel.place(); 289 codeStream.iconst_1(); 290 } else { 291 BranchLabel endLabel = new BranchLabel(codeStream); 292 codeStream.goto_(endLabel); 293 codeStream.decrStackSize(1); 294 falseLabel.place(); 296 codeStream.iconst_1(); 297 endLabel.place(); 298 } 299 } else { 300 left.generateCode(currentScope, codeStream, false); 301 right.generateCode(currentScope, codeStream, false); 302 } 303 } 310 return; 311 } 312 left.generateCode(currentScope, codeStream, valueRequired); 314 right.generateCode(currentScope, codeStream, valueRequired); 315 316 if (valueRequired) { 317 if (isEqualOperator) { 318 BranchLabel falseLabel; 319 codeStream.if_icmpne(falseLabel = new BranchLabel(codeStream)); 320 codeStream.iconst_1(); 322 if ((bits & IsReturnedValue) != 0){ 323 codeStream.generateImplicitConversion(this.implicitConversion); 324 codeStream.generateReturnBytecode(this); 325 falseLabel.place(); 327 codeStream.iconst_0(); 328 } else { 329 BranchLabel endLabel = new BranchLabel(codeStream); 330 codeStream.goto_(endLabel); 331 codeStream.decrStackSize(1); 332 falseLabel.place(); 334 codeStream.iconst_0(); 335 endLabel.place(); 336 } 337 } else { 338 codeStream.ixor(); 339 } 340 } 341 } 342 343 348 public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 349 350 if (left.constant != Constant.NotAConstant) { 352 boolean inline = left.constant.booleanValue(); 353 right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); 354 return; 355 } if (right.constant != Constant.NotAConstant) { 357 boolean inline = right.constant.booleanValue(); 358 left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired); 359 return; 360 } 361 left.generateCode(currentScope, codeStream, valueRequired); 363 right.generateCode(currentScope, codeStream, valueRequired); 364 if (valueRequired) { 365 if (falseLabel == null) { 366 if (trueLabel != null) { 367 codeStream.if_icmpeq(trueLabel); 369 } 370 } else { 371 if (trueLabel == null) { 373 codeStream.if_icmpne(falseLabel); 374 } else { 375 } 377 } 378 } 379 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position); 381 } 382 386 public void generateNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 387 388 boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL; 389 if (((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) { 390 Constant cst; 391 if ((cst = left.constant) != Constant.NotAConstant && cst.intValue() == 0) { 392 right.generateCode(currentScope, codeStream, valueRequired); 394 if (valueRequired) { 395 BranchLabel falseLabel = new BranchLabel(codeStream); 396 if (isEqualOperator) { 397 codeStream.ifne(falseLabel); 398 } else { 399 codeStream.ifeq(falseLabel); 400 } 401 codeStream.iconst_1(); 403 if ((bits & IsReturnedValue) != 0){ 404 codeStream.generateImplicitConversion(this.implicitConversion); 405 codeStream.generateReturnBytecode(this); 406 falseLabel.place(); 408 codeStream.iconst_0(); 409 } else { 410 BranchLabel endLabel = new BranchLabel(codeStream); 411 codeStream.goto_(endLabel); 412 codeStream.decrStackSize(1); 413 falseLabel.place(); 415 codeStream.iconst_0(); 416 endLabel.place(); 417 } 418 } 419 return; 420 } 421 if ((cst = right.constant) != Constant.NotAConstant && cst.intValue() == 0) { 422 left.generateCode(currentScope, codeStream, valueRequired); 424 if (valueRequired) { 425 BranchLabel falseLabel = new BranchLabel(codeStream); 426 if (isEqualOperator) { 427 codeStream.ifne(falseLabel); 428 } else { 429 codeStream.ifeq(falseLabel); 430 } 431 codeStream.iconst_1(); 433 if ((bits & IsReturnedValue) != 0){ 434 codeStream.generateImplicitConversion(this.implicitConversion); 435 codeStream.generateReturnBytecode(this); 436 falseLabel.place(); 438 codeStream.iconst_0(); 439 } else { 440 BranchLabel endLabel = new BranchLabel(codeStream); 441 codeStream.goto_(endLabel); 442 codeStream.decrStackSize(1); 443 falseLabel.place(); 445 codeStream.iconst_0(); 446 endLabel.place(); 447 } 448 } 449 return; 450 } 451 } 452 453 if (right instanceof NullLiteral) { 455 if (left instanceof NullLiteral) { 456 if (valueRequired) { 458 if (isEqualOperator) { 459 codeStream.iconst_1(); 460 } else { 461 codeStream.iconst_0(); 462 } 463 } 464 } else { 465 left.generateCode(currentScope, codeStream, valueRequired); 467 if (valueRequired) { 468 BranchLabel falseLabel = new BranchLabel(codeStream); 469 if (isEqualOperator) { 470 codeStream.ifnonnull(falseLabel); 471 } else { 472 codeStream.ifnull(falseLabel); 473 } 474 codeStream.iconst_1(); 476 if ((bits & IsReturnedValue) != 0){ 477 codeStream.generateImplicitConversion(this.implicitConversion); 478 codeStream.generateReturnBytecode(this); 479 falseLabel.place(); 481 codeStream.iconst_0(); 482 } else { 483 BranchLabel endLabel = new BranchLabel(codeStream); 484 codeStream.goto_(endLabel); 485 codeStream.decrStackSize(1); 486 falseLabel.place(); 488 codeStream.iconst_0(); 489 endLabel.place(); 490 } 491 } 492 } 493 return; 494 } else if (left instanceof NullLiteral) { 495 right.generateCode(currentScope, codeStream, valueRequired); 497 if (valueRequired) { 498 BranchLabel falseLabel = new BranchLabel(codeStream); 499 if (isEqualOperator) { 500 codeStream.ifnonnull(falseLabel); 501 } else { 502 codeStream.ifnull(falseLabel); 503 } 504 codeStream.iconst_1(); 506 if ((bits & IsReturnedValue) != 0){ 507 codeStream.generateImplicitConversion(this.implicitConversion); 508 codeStream.generateReturnBytecode(this); 509 falseLabel.place(); 511 codeStream.iconst_0(); 512 } else { 513 BranchLabel endLabel = new BranchLabel(codeStream); 514 codeStream.goto_(endLabel); 515 codeStream.decrStackSize(1); 516 falseLabel.place(); 518 codeStream.iconst_0(); 519 endLabel.place(); 520 } 521 } 522 return; 523 } 524 525 left.generateCode(currentScope, codeStream, valueRequired); 527 right.generateCode(currentScope, codeStream, valueRequired); 528 if (valueRequired) { 529 BranchLabel falseLabel = new BranchLabel(codeStream); 530 if (isEqualOperator) { 531 switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { case T_int : 533 codeStream.if_icmpne(falseLabel); 534 break; 535 case T_float : 536 codeStream.fcmpl(); 537 codeStream.ifne(falseLabel); 538 break; 539 case T_long : 540 codeStream.lcmp(); 541 codeStream.ifne(falseLabel); 542 break; 543 case T_double : 544 codeStream.dcmpl(); 545 codeStream.ifne(falseLabel); 546 break; 547 default : 548 codeStream.if_acmpne(falseLabel); 549 } 550 } else { 551 switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { case T_int : 553 codeStream.if_icmpeq(falseLabel); 554 break; 555 case T_float : 556 codeStream.fcmpl(); 557 codeStream.ifeq(falseLabel); 558 break; 559 case T_long : 560 codeStream.lcmp(); 561 codeStream.ifeq(falseLabel); 562 break; 563 case T_double : 564 codeStream.dcmpl(); 565 codeStream.ifeq(falseLabel); 566 break; 567 default : 568 codeStream.if_acmpeq(falseLabel); 569 } 570 } 571 codeStream.iconst_1(); 573 if ((bits & IsReturnedValue) != 0){ 574 codeStream.generateImplicitConversion(this.implicitConversion); 575 codeStream.generateReturnBytecode(this); 576 falseLabel.place(); 578 codeStream.iconst_0(); 579 } else { 580 BranchLabel endLabel = new BranchLabel(codeStream); 581 codeStream.goto_(endLabel); 582 codeStream.decrStackSize(1); 583 falseLabel.place(); 585 codeStream.iconst_0(); 586 endLabel.place(); 587 } 588 } 589 } 590 591 595 public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { 596 597 int pc = codeStream.position; 598 Constant inline; 599 if ((inline = right.constant) != Constant.NotAConstant) { 600 if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) { 602 left.generateCode(currentScope, codeStream, valueRequired); 603 if (valueRequired) { 604 if (falseLabel == null) { 605 if (trueLabel != null) { 606 codeStream.ifeq(trueLabel); 608 } 609 } else { 610 if (trueLabel == null) { 612 codeStream.ifne(falseLabel); 613 } else { 614 } 616 } 617 } 618 codeStream.recordPositionsFrom(pc, this.sourceStart); 619 return; 620 } 621 } 622 if ((inline = left.constant) != Constant.NotAConstant) { 623 if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) 625 && (inline.intValue() == 0)) { 626 right.generateCode(currentScope, codeStream, valueRequired); 627 if (valueRequired) { 628 if (falseLabel == null) { 629 if (trueLabel != null) { 630 codeStream.ifeq(trueLabel); 632 } 633 } else { 634 if (trueLabel == null) { 636 codeStream.ifne(falseLabel); 637 } else { 638 } 640 } 641 } 642 codeStream.recordPositionsFrom(pc, this.sourceStart); 643 return; 644 } 645 } 646 if (right instanceof NullLiteral) { 649 if (left instanceof NullLiteral) { 650 if (valueRequired) { 652 if (falseLabel == null) { 653 if (trueLabel != null) { 655 codeStream.goto_(trueLabel); 656 } 657 } 658 } 659 } else { 660 left.generateCode(currentScope, codeStream, valueRequired); 661 if (valueRequired) { 662 if (falseLabel == null) { 663 if (trueLabel != null) { 664 codeStream.ifnull(trueLabel); 666 } 667 } else { 668 if (trueLabel == null) { 670 codeStream.ifnonnull(falseLabel); 671 } else { 672 } 674 } 675 } 676 } 677 codeStream.recordPositionsFrom(pc, this.sourceStart); 678 return; 679 } else if (left instanceof NullLiteral) { right.generateCode(currentScope, codeStream, valueRequired); 681 if (valueRequired) { 682 if (falseLabel == null) { 683 if (trueLabel != null) { 684 codeStream.ifnull(trueLabel); 686 } 687 } else { 688 if (trueLabel == null) { 690 codeStream.ifnonnull(falseLabel); 691 } else { 692 } 694 } 695 } 696 codeStream.recordPositionsFrom(pc, this.sourceStart); 697 return; 698 } 699 700 left.generateCode(currentScope, codeStream, valueRequired); 702 right.generateCode(currentScope, codeStream, valueRequired); 703 if (valueRequired) { 704 if (falseLabel == null) { 705 if (trueLabel != null) { 706 switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { case T_int : 709 codeStream.if_icmpeq(trueLabel); 710 break; 711 case T_float : 712 codeStream.fcmpl(); 713 codeStream.ifeq(trueLabel); 714 break; 715 case T_long : 716 codeStream.lcmp(); 717 codeStream.ifeq(trueLabel); 718 break; 719 case T_double : 720 codeStream.dcmpl(); 721 codeStream.ifeq(trueLabel); 722 break; 723 default : 724 codeStream.if_acmpeq(trueLabel); 725 } 726 } 727 } else { 728 if (trueLabel == null) { 730 switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { case T_int : 732 codeStream.if_icmpne(falseLabel); 733 break; 734 case T_float : 735 codeStream.fcmpl(); 736 codeStream.ifne(falseLabel); 737 break; 738 case T_long : 739 codeStream.lcmp(); 740 codeStream.ifne(falseLabel); 741 break; 742 case T_double : 743 codeStream.dcmpl(); 744 codeStream.ifne(falseLabel); 745 break; 746 default : 747 codeStream.if_acmpne(falseLabel); 748 } 749 } else { 750 } 752 } 753 } 754 codeStream.recordPositionsFrom(pc, this.sourceStart); 755 } 756 public boolean isCompactableOperation() { 757 return false; 758 } 759 public TypeBinding resolveType(BlockScope scope) { 760 761 boolean leftIsCast, rightIsCast; 762 if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= DisableUnnecessaryCastCheck; TypeBinding originalLeftType = left.resolveType(scope); 764 765 if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= DisableUnnecessaryCastCheck; TypeBinding originalRightType = right.resolveType(scope); 767 768 if (originalLeftType == null || originalRightType == null){ 770 constant = Constant.NotAConstant; 771 return null; 772 } 773 774 boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; 776 TypeBinding leftType = originalLeftType, rightType = originalRightType; 777 if (use15specifics) { 778 if (leftType != TypeBinding.NULL && leftType.isBaseType()) { 779 if (!rightType.isBaseType()) { 780 rightType = scope.environment().computeBoxingType(rightType); 781 } 782 } else { 783 if (rightType != TypeBinding.NULL && rightType.isBaseType()) { 784 leftType = scope.environment().computeBoxingType(leftType); 785 } 786 } 787 } 788 if (leftType.isBaseType() && rightType.isBaseType()) { 790 int leftTypeID = leftType.id; 791 int rightTypeID = rightType.id; 792 793 int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftTypeID << 4) + rightTypeID]; 798 left.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F), originalLeftType); 799 right.computeConversion(scope, TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F), originalRightType); 800 bits |= operatorSignature & 0xF; 801 if ((operatorSignature & 0x0000F) == T_undefined) { 802 constant = Constant.NotAConstant; 803 scope.problemReporter().invalidOperator(this, leftType, rightType); 804 return null; 805 } 806 if (leftIsCast || rightIsCast) { 808 CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast); 809 } 810 computeConstant(leftType, rightType); 811 return this.resolvedType = TypeBinding.BOOLEAN; 812 } 813 814 if ((!leftType.isBaseType() || leftType == TypeBinding.NULL) && (!rightType.isBaseType() || rightType == TypeBinding.NULL) 818 && (this.checkCastTypesCompatibility(scope, leftType, rightType, null) 819 || this.checkCastTypesCompatibility(scope, rightType, leftType, null))) { 820 821 if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) { 823 computeConstant(leftType, rightType); 824 } else { 825 constant = Constant.NotAConstant; 826 } 827 TypeBinding objectType = scope.getJavaLangObject(); 828 left.computeConversion(scope, objectType, leftType); 829 right.computeConversion(scope, objectType, rightType); 830 boolean unnecessaryLeftCast = (left.bits & UnnecessaryCast) != 0; 832 boolean unnecessaryRightCast = (right.bits & UnnecessaryCast) != 0; 833 if (unnecessaryLeftCast || unnecessaryRightCast) { 834 TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType; 835 TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType; 836 if (this.checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null) 837 || this.checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) { 838 if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 839 if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right); 840 } 841 } 842 return this.resolvedType = TypeBinding.BOOLEAN; 843 } 844 constant = Constant.NotAConstant; 845 scope.problemReporter().notCompatibleTypesError(this, leftType, rightType); 846 return null; 847 } 848 public void traverse(ASTVisitor visitor, BlockScope scope) { 849 if (visitor.visit(this, scope)) { 850 left.traverse(visitor, scope); 851 right.traverse(visitor, scope); 852 } 853 visitor.endVisit(this, scope); 854 } 855 } 856 | Popular Tags |