public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
   if ((this.left.constant != Constant.NotAConstant)
       && (this.right.constant != Constant.NotAConstant)) {
     this.constant =
         Constant.computeConstantOperationEQUAL_EQUAL(
             this.left.constant, leftType.id, this.right.constant, rightType.id);
     if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
       this.constant = BooleanConstant.fromValue(!this.constant.booleanValue());
   } else {
     this.constant = Constant.NotAConstant;
     // no optimization for null == null
   }
 }
Пример #2
0
 Object decodeDefaultValue() {
   Object value = null;
   // u1 tag;
   int tag = u1At(this.readOffset);
   this.readOffset++;
   int constValueOffset = -1;
   switch (tag) {
     case 'Z': // boolean constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = BooleanConstant.fromValue(i4At(constValueOffset + 1) == 1);
       this.readOffset += 2;
       break;
     case 'I': // integer constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = IntConstant.fromValue(i4At(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'C': // char constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = CharConstant.fromValue((char) i4At(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'B': // byte constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = ByteConstant.fromValue((byte) i4At(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'S': // short constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = ShortConstant.fromValue((short) i4At(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'D': // double constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = DoubleConstant.fromValue(doubleAt(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'F': // float constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = FloatConstant.fromValue(floatAt(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 'J': // long constant
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value = LongConstant.fromValue(i8At(constValueOffset + 1));
       this.readOffset += 2;
       break;
     case 's': // String
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       value =
           StringConstant.fromValue(
               String.valueOf(utf8At(constValueOffset + 3, u2At(constValueOffset + 1))));
       this.readOffset += 2;
       break;
     case 'e':
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       char[] typeName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1));
       this.readOffset += 2;
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       char[] constName = utf8At(constValueOffset + 3, u2At(constValueOffset + 1));
       this.readOffset += 2;
       value = new EnumConstantSignature(typeName, constName);
       break;
     case 'c':
       constValueOffset = this.constantPoolOffsets[u2At(this.readOffset)] - this.structOffset;
       char[] className = utf8At(constValueOffset + 3, u2At(constValueOffset + 1));
       value = new ClassSignature(className);
       this.readOffset += 2;
       break;
     case '@':
       value =
           new AnnotationInfo(
               this.reference,
               this.constantPoolOffsets,
               this.readOffset + this.structOffset,
               false,
               true);
       this.readOffset += ((AnnotationInfo) value).readOffset;
       break;
     case '[':
       int numberOfValues = u2At(this.readOffset);
       this.readOffset += 2;
       if (numberOfValues == 0) {
         value = EmptyValueArray;
       } else {
         Object[] arrayElements = new Object[numberOfValues];
         value = arrayElements;
         for (int i = 0; i < numberOfValues; i++) arrayElements[i] = decodeDefaultValue();
       }
       break;
     default:
       throw new IllegalStateException("Unrecognized tag " + (char) tag); // $NON-NLS-1$
   }
   return value;
 }
  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;
  }