コード例 #1
0
  public TypeBinding resolveType(BlockScope scope) {

    boolean leftIsCast, rightIsCast;
    if ((leftIsCast = this.left instanceof CastExpression) == true)
      this.left.bits |= DisableUnnecessaryCastCheck; // will check later on
    TypeBinding originalLeftType = this.left.resolveType(scope);

    if ((rightIsCast = this.right instanceof CastExpression) == true)
      this.right.bits |= DisableUnnecessaryCastCheck; // will check later on
    TypeBinding originalRightType = this.right.resolveType(scope);

    // always return BooleanBinding
    if (originalLeftType == null || originalRightType == null) {
      this.constant = Constant.NotAConstant;
      return null;
    }

    // autoboxing support
    boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
    TypeBinding leftType = originalLeftType, rightType = originalRightType;
    if (use15specifics) {
      if (leftType != TypeBinding.NULL && leftType.isBaseType()) {
        if (!rightType.isBaseType()) {
          rightType = scope.environment().computeBoxingType(rightType);
        }
      } else {
        if (rightType != TypeBinding.NULL && rightType.isBaseType()) {
          leftType = scope.environment().computeBoxingType(leftType);
        }
      }
    }
    // both base type
    if (leftType.isBaseType() && rightType.isBaseType()) {
      int leftTypeID = leftType.id;
      int rightTypeID = rightType.id;

      // the code is an int
      // (cast)  left   == (cast)  right --> result
      //  0000   0000       0000   0000      0000
      //  <<16   <<12       <<8    <<4       <<0
      int operatorSignature = OperatorSignatures[EQUAL_EQUAL][(leftTypeID << 4) + rightTypeID];
      this.left.computeConversion(
          scope,
          TypeBinding.wellKnownType(scope, (operatorSignature >>> 16) & 0x0000F),
          originalLeftType);
      this.right.computeConversion(
          scope,
          TypeBinding.wellKnownType(scope, (operatorSignature >>> 8) & 0x0000F),
          originalRightType);
      this.bits |= operatorSignature & 0xF;
      if ((operatorSignature & 0x0000F) == T_undefined) {
        this.constant = Constant.NotAConstant;
        scope.problemReporter().invalidOperator(this, leftType, rightType);
        return null;
      }
      // check need for operand cast
      if (leftIsCast || rightIsCast) {
        CastExpression.checkNeedForArgumentCasts(
            scope,
            EQUAL_EQUAL,
            operatorSignature,
            this.left,
            leftType.id,
            leftIsCast,
            this.right,
            rightType.id,
            rightIsCast);
      }
      computeConstant(leftType, rightType);

      // check whether comparing identical expressions
      Binding leftDirect = Expression.getDirectBinding(this.left);
      if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) {
        if (leftTypeID != TypeIds.T_double
            && leftTypeID != TypeIds.T_float
            && (!(this.right
                instanceof Assignment))) // https://bugs.eclipse.org/bugs/show_bug.cgi?id=281776
        scope.problemReporter().comparingIdenticalExpressions(this);
      } else if (this.constant != Constant.NotAConstant) {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276740
        int operator = (this.bits & OperatorMASK) >> OperatorSHIFT;
        if ((operator == EQUAL_EQUAL && this.constant == BooleanConstant.fromValue(true))
            || (operator == NOT_EQUAL && this.constant == BooleanConstant.fromValue(false)))
          scope.problemReporter().comparingIdenticalExpressions(this);
      }
      return this.resolvedType = TypeBinding.BOOLEAN;
    }

    // Object references
    // spec 15.20.3
    if ((!leftType.isBaseType() || leftType == TypeBinding.NULL) // cannot compare: Object == (int)0
        && (!rightType.isBaseType() || rightType == TypeBinding.NULL)
        && (checkCastTypesCompatibility(scope, leftType, rightType, null)
            || checkCastTypesCompatibility(scope, rightType, leftType, null))) {

      // (special case for String)
      if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) {
        computeConstant(leftType, rightType);
      } else {
        this.constant = Constant.NotAConstant;
      }
      TypeBinding objectType = scope.getJavaLangObject();
      this.left.computeConversion(scope, objectType, leftType);
      this.right.computeConversion(scope, objectType, rightType);
      // check need for operand cast
      boolean unnecessaryLeftCast = (this.left.bits & UnnecessaryCast) != 0;
      boolean unnecessaryRightCast = (this.right.bits & UnnecessaryCast) != 0;
      if (unnecessaryLeftCast || unnecessaryRightCast) {
        TypeBinding alternateLeftType =
            unnecessaryLeftCast ? ((CastExpression) this.left).expression.resolvedType : leftType;
        TypeBinding alternateRightType =
            unnecessaryRightCast
                ? ((CastExpression) this.right).expression.resolvedType
                : rightType;
        if (checkCastTypesCompatibility(scope, alternateLeftType, alternateRightType, null)
            || checkCastTypesCompatibility(scope, alternateRightType, alternateLeftType, null)) {
          if (unnecessaryLeftCast)
            scope.problemReporter().unnecessaryCast((CastExpression) this.left);
          if (unnecessaryRightCast)
            scope.problemReporter().unnecessaryCast((CastExpression) this.right);
        }
      }
      // check whether comparing identical expressions
      Binding leftDirect = Expression.getDirectBinding(this.left);
      if (leftDirect != null && leftDirect == Expression.getDirectBinding(this.right)) {
        if (!(this.right instanceof Assignment)) {
          scope.problemReporter().comparingIdenticalExpressions(this);
        }
      }
      return this.resolvedType = TypeBinding.BOOLEAN;
    }
    this.constant = Constant.NotAConstant;
    scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
    return null;
  }