dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.

Home Page:https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Constant-folding int.MinValue % -1

jakobbotsch opened this issue · comments

The following behavior seems strange to me:

int val = int.MinValue % -1; // constant-folded to 0
val = int.MinValue;
val %= -1; // throws OverflowException at runtime

Quoting @mikedn in https://github.com/dotnet/coreclr/issues/18235#issuecomment-393963856, the spec says:

If the left operand is the smallest int or long value and the right operand is -1, a System.OverflowException is thrown. In no case does x % y throw an exception where x / y would not throw an exception.

Is Roslyn supposed to constant-fold int.MinValue % -1 to 0 rather than give an overflow diagnostic like in other situations?

This is a bug.

@gafter I can observe the similar behavior not only for the remainder operator, but for the division as well:

unchecked
{
    Console.WriteLine(int.MinValue / -1); // outputs -2147483648
    int val = int.MinValue;
    val /= -1;   // throws OverflowException
}

Should it be the separate issue?

In this case both outputs are according to the spec:

If the left operand is the smallest representable int or long value and the right operand is –1, an
overflow occurs. In a checked context, this causes a System.ArithmeticException (or a subclass
thereof) to be thrown. In an unchecked context, it is implementation-defined as to whether a
System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported
with the resulting value being that of the left operand.

The issue is that they are not the same.