private static object FoldNeverOverflowBinaryOperators()

in src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs [1621:1817]


        private static object FoldNeverOverflowBinaryOperators(BinaryOperatorKind kind, ConstantValue valueLeft, ConstantValue valueRight)
        {
            Debug.Assert(valueLeft != null);
            Debug.Assert(valueRight != null);

            // Note that we *cannot* do folding on single-precision floats as doubles to preserve precision,
            // as that would cause incorrect rounding that would be impossible to correct afterwards.
            switch (kind)
            {
                case BinaryOperatorKind.ObjectEqual:
                    if (valueLeft.IsNull) return valueRight.IsNull;
                    if (valueRight.IsNull) return false;
                    break;
                case BinaryOperatorKind.ObjectNotEqual:
                    if (valueLeft.IsNull) return !valueRight.IsNull;
                    if (valueRight.IsNull) return true;
                    break;
                case BinaryOperatorKind.DoubleAddition:
                    return valueLeft.DoubleValue + valueRight.DoubleValue;
                case BinaryOperatorKind.FloatAddition:
                    return valueLeft.SingleValue + valueRight.SingleValue;
                case BinaryOperatorKind.DoubleSubtraction:
                    return valueLeft.DoubleValue - valueRight.DoubleValue;
                case BinaryOperatorKind.FloatSubtraction:
                    return valueLeft.SingleValue - valueRight.SingleValue;
                case BinaryOperatorKind.DoubleMultiplication:
                    return valueLeft.DoubleValue * valueRight.DoubleValue;
                case BinaryOperatorKind.FloatMultiplication:
                    return valueLeft.SingleValue * valueRight.SingleValue;
                case BinaryOperatorKind.DoubleDivision:
                    return valueLeft.DoubleValue / valueRight.DoubleValue;
                case BinaryOperatorKind.FloatDivision:
                    return valueLeft.SingleValue / valueRight.SingleValue;
                case BinaryOperatorKind.DoubleRemainder:
                    return valueLeft.DoubleValue % valueRight.DoubleValue;
                case BinaryOperatorKind.FloatRemainder:
                    return valueLeft.SingleValue % valueRight.SingleValue;
                case BinaryOperatorKind.IntLeftShift:
                    return valueLeft.Int32Value << valueRight.Int32Value;
                case BinaryOperatorKind.LongLeftShift:
                    return valueLeft.Int64Value << valueRight.Int32Value;
                case BinaryOperatorKind.UIntLeftShift:
                    return valueLeft.UInt32Value << valueRight.Int32Value;
                case BinaryOperatorKind.ULongLeftShift:
                    return valueLeft.UInt64Value << valueRight.Int32Value;
                case BinaryOperatorKind.IntRightShift:
                    return valueLeft.Int32Value >> valueRight.Int32Value;
                case BinaryOperatorKind.LongRightShift:
                    return valueLeft.Int64Value >> valueRight.Int32Value;
                case BinaryOperatorKind.UIntRightShift:
                    return valueLeft.UInt32Value >> valueRight.Int32Value;
                case BinaryOperatorKind.ULongRightShift:
                    return valueLeft.UInt64Value >> valueRight.Int32Value;
                case BinaryOperatorKind.BoolAnd:
                    return valueLeft.BooleanValue & valueRight.BooleanValue;
                case BinaryOperatorKind.IntAnd:
                    return valueLeft.Int32Value & valueRight.Int32Value;
                case BinaryOperatorKind.LongAnd:
                    return valueLeft.Int64Value & valueRight.Int64Value;
                case BinaryOperatorKind.UIntAnd:
                    return valueLeft.UInt32Value & valueRight.UInt32Value;
                case BinaryOperatorKind.ULongAnd:
                    return valueLeft.UInt64Value & valueRight.UInt64Value;
                case BinaryOperatorKind.BoolOr:
                    return valueLeft.BooleanValue | valueRight.BooleanValue;
                case BinaryOperatorKind.IntOr:
                    return valueLeft.Int32Value | valueRight.Int32Value;
                case BinaryOperatorKind.LongOr:
                    return valueLeft.Int64Value | valueRight.Int64Value;
                case BinaryOperatorKind.UIntOr:
                    return valueLeft.UInt32Value | valueRight.UInt32Value;
                case BinaryOperatorKind.ULongOr:
                    return valueLeft.UInt64Value | valueRight.UInt64Value;
                case BinaryOperatorKind.BoolXor:
                    return valueLeft.BooleanValue ^ valueRight.BooleanValue;
                case BinaryOperatorKind.IntXor:
                    return valueLeft.Int32Value ^ valueRight.Int32Value;
                case BinaryOperatorKind.LongXor:
                    return valueLeft.Int64Value ^ valueRight.Int64Value;
                case BinaryOperatorKind.UIntXor:
                    return valueLeft.UInt32Value ^ valueRight.UInt32Value;
                case BinaryOperatorKind.ULongXor:
                    return valueLeft.UInt64Value ^ valueRight.UInt64Value;
                case BinaryOperatorKind.LogicalBoolAnd:
                    return valueLeft.BooleanValue && valueRight.BooleanValue;
                case BinaryOperatorKind.LogicalBoolOr:
                    return valueLeft.BooleanValue || valueRight.BooleanValue;
                case BinaryOperatorKind.BoolEqual:
                    return valueLeft.BooleanValue == valueRight.BooleanValue;
                case BinaryOperatorKind.StringEqual:
                    return valueLeft.StringValue == valueRight.StringValue;
                case BinaryOperatorKind.DecimalEqual:
                    return valueLeft.DecimalValue == valueRight.DecimalValue;
                case BinaryOperatorKind.FloatEqual:
                    return valueLeft.SingleValue == valueRight.SingleValue;
                case BinaryOperatorKind.DoubleEqual:
                    return valueLeft.DoubleValue == valueRight.DoubleValue;
                case BinaryOperatorKind.IntEqual:
                    return valueLeft.Int32Value == valueRight.Int32Value;
                case BinaryOperatorKind.LongEqual:
                    return valueLeft.Int64Value == valueRight.Int64Value;
                case BinaryOperatorKind.UIntEqual:
                    return valueLeft.UInt32Value == valueRight.UInt32Value;
                case BinaryOperatorKind.ULongEqual:
                    return valueLeft.UInt64Value == valueRight.UInt64Value;
                case BinaryOperatorKind.BoolNotEqual:
                    return valueLeft.BooleanValue != valueRight.BooleanValue;
                case BinaryOperatorKind.StringNotEqual:
                    return valueLeft.StringValue != valueRight.StringValue;
                case BinaryOperatorKind.DecimalNotEqual:
                    return valueLeft.DecimalValue != valueRight.DecimalValue;
                case BinaryOperatorKind.FloatNotEqual:
                    return valueLeft.SingleValue != valueRight.SingleValue;
                case BinaryOperatorKind.DoubleNotEqual:
                    return valueLeft.DoubleValue != valueRight.DoubleValue;
                case BinaryOperatorKind.IntNotEqual:
                    return valueLeft.Int32Value != valueRight.Int32Value;
                case BinaryOperatorKind.LongNotEqual:
                    return valueLeft.Int64Value != valueRight.Int64Value;
                case BinaryOperatorKind.UIntNotEqual:
                    return valueLeft.UInt32Value != valueRight.UInt32Value;
                case BinaryOperatorKind.ULongNotEqual:
                    return valueLeft.UInt64Value != valueRight.UInt64Value;
                case BinaryOperatorKind.DecimalLessThan:
                    return valueLeft.DecimalValue < valueRight.DecimalValue;
                case BinaryOperatorKind.FloatLessThan:
                    return valueLeft.SingleValue < valueRight.SingleValue;
                case BinaryOperatorKind.DoubleLessThan:
                    return valueLeft.DoubleValue < valueRight.DoubleValue;
                case BinaryOperatorKind.IntLessThan:
                    return valueLeft.Int32Value < valueRight.Int32Value;
                case BinaryOperatorKind.LongLessThan:
                    return valueLeft.Int64Value < valueRight.Int64Value;
                case BinaryOperatorKind.UIntLessThan:
                    return valueLeft.UInt32Value < valueRight.UInt32Value;
                case BinaryOperatorKind.ULongLessThan:
                    return valueLeft.UInt64Value < valueRight.UInt64Value;
                case BinaryOperatorKind.DecimalGreaterThan:
                    return valueLeft.DecimalValue > valueRight.DecimalValue;
                case BinaryOperatorKind.FloatGreaterThan:
                    return valueLeft.SingleValue > valueRight.SingleValue;
                case BinaryOperatorKind.DoubleGreaterThan:
                    return valueLeft.DoubleValue > valueRight.DoubleValue;
                case BinaryOperatorKind.IntGreaterThan:
                    return valueLeft.Int32Value > valueRight.Int32Value;
                case BinaryOperatorKind.LongGreaterThan:
                    return valueLeft.Int64Value > valueRight.Int64Value;
                case BinaryOperatorKind.UIntGreaterThan:
                    return valueLeft.UInt32Value > valueRight.UInt32Value;
                case BinaryOperatorKind.ULongGreaterThan:
                    return valueLeft.UInt64Value > valueRight.UInt64Value;
                case BinaryOperatorKind.DecimalLessThanOrEqual:
                    return valueLeft.DecimalValue <= valueRight.DecimalValue;
                case BinaryOperatorKind.FloatLessThanOrEqual:
                    return valueLeft.SingleValue <= valueRight.SingleValue;
                case BinaryOperatorKind.DoubleLessThanOrEqual:
                    return valueLeft.DoubleValue <= valueRight.DoubleValue;
                case BinaryOperatorKind.IntLessThanOrEqual:
                    return valueLeft.Int32Value <= valueRight.Int32Value;
                case BinaryOperatorKind.LongLessThanOrEqual:
                    return valueLeft.Int64Value <= valueRight.Int64Value;
                case BinaryOperatorKind.UIntLessThanOrEqual:
                    return valueLeft.UInt32Value <= valueRight.UInt32Value;
                case BinaryOperatorKind.ULongLessThanOrEqual:
                    return valueLeft.UInt64Value <= valueRight.UInt64Value;
                case BinaryOperatorKind.DecimalGreaterThanOrEqual:
                    return valueLeft.DecimalValue >= valueRight.DecimalValue;
                case BinaryOperatorKind.FloatGreaterThanOrEqual:
                    return valueLeft.SingleValue >= valueRight.SingleValue;
                case BinaryOperatorKind.DoubleGreaterThanOrEqual:
                    return valueLeft.DoubleValue >= valueRight.DoubleValue;
                case BinaryOperatorKind.IntGreaterThanOrEqual:
                    return valueLeft.Int32Value >= valueRight.Int32Value;
                case BinaryOperatorKind.LongGreaterThanOrEqual:
                    return valueLeft.Int64Value >= valueRight.Int64Value;
                case BinaryOperatorKind.UIntGreaterThanOrEqual:
                    return valueLeft.UInt32Value >= valueRight.UInt32Value;
                case BinaryOperatorKind.ULongGreaterThanOrEqual:
                    return valueLeft.UInt64Value >= valueRight.UInt64Value;
                case BinaryOperatorKind.UIntDivision:
                    return valueLeft.UInt32Value / valueRight.UInt32Value;
                case BinaryOperatorKind.ULongDivision:
                    return valueLeft.UInt64Value / valueRight.UInt64Value;

                // MinValue % -1 always overflows at runtime but never at compile time
                case BinaryOperatorKind.IntRemainder:
                    return (valueRight.Int32Value != -1) ? valueLeft.Int32Value % valueRight.Int32Value : 0;
                case BinaryOperatorKind.LongRemainder:
                    return (valueRight.Int64Value != -1) ? valueLeft.Int64Value % valueRight.Int64Value : 0;
                case BinaryOperatorKind.UIntRemainder:
                    return valueLeft.UInt32Value % valueRight.UInt32Value;
                case BinaryOperatorKind.ULongRemainder:
                    return valueLeft.UInt64Value % valueRight.UInt64Value;
            }

            return null;
        }