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 } }
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; }