未验证 提交 60994a80 编写于 作者: C Charles Stoner 提交者: GitHub

Result of << operator for native integer constants is platform-dependent in...

Result of << operator for native integer constants is platform-dependent in unchecked context (#47881)
上级 d2351bc7
......@@ -1350,6 +1350,18 @@ private static object FoldNativeIntegerOverflowingBinaryOperator(BinaryOperatorK
return valueLeft.Int32Value / valueRight.Int32Value;
case BinaryOperatorKind.NIntRemainder:
return valueLeft.Int32Value % valueRight.Int32Value;
case BinaryOperatorKind.NIntLeftShift:
{
var int32Value = valueLeft.Int32Value << valueRight.Int32Value;
var int64Value = valueLeft.Int64Value << valueRight.Int32Value;
return (int32Value == int64Value) ? int32Value : null;
}
case BinaryOperatorKind.NUIntLeftShift:
{
var uint32Value = valueLeft.UInt32Value << valueRight.Int32Value;
var uint64Value = valueLeft.UInt64Value << valueRight.Int32Value;
return (uint32Value == uint64Value) ? uint32Value : null;
}
}
return null;
......@@ -1808,12 +1820,10 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
case BinaryOperatorKind.FloatRemainder:
return valueLeft.SingleValue % valueRight.SingleValue;
case BinaryOperatorKind.IntLeftShift:
case BinaryOperatorKind.NIntLeftShift:
return valueLeft.Int32Value << valueRight.Int32Value;
case BinaryOperatorKind.LongLeftShift:
return valueLeft.Int64Value << valueRight.Int32Value;
case BinaryOperatorKind.UIntLeftShift:
case BinaryOperatorKind.NUIntLeftShift:
return valueLeft.UInt32Value << valueRight.Int32Value;
case BinaryOperatorKind.ULongLeftShift:
return valueLeft.UInt64Value << valueRight.Int32Value;
......
......@@ -12019,15 +12019,14 @@ public void ConstantFolding()
binaryOperator("bool", "!=", "nuint", "0", "nuint", uintMaxValue, "True");
binaryOperator("bool", "!=", "nuint", uintMaxValue, "nuint", uintMaxValue, "False");
// https://github.com/dotnet/roslyn/issues/42460: Results of `<<` should be dependent on platform.
binaryOperator("nint", "<<", "nint", intMinValue, "int", "0", intMinValue);
binaryOperator("nint", "<<", "nint", intMinValue, "int", "1", "0");
binaryOperatorNotConstant("nint", "<<", "nint", intMinValue, "int", "1", IntPtr.Size == 4 ? "0" : "-4294967296");
binaryOperator("nint", "<<", "nint", "-1", "int", "31", intMinValue);
binaryOperator("nint", "<<", "nint", "-1", "int", "32", "-1");
binaryOperatorNotConstant("nint", "<<", "nint", "-1", "int", "32", IntPtr.Size == 4 ? "-1" : "-4294967296");
binaryOperator("nuint", "<<", "nuint", "0", "int", "1", "0");
binaryOperator("nuint", "<<", "nuint", uintMaxValue, "int", "1", "4294967294");
binaryOperatorNotConstant("nuint", "<<", "nuint", uintMaxValue, "int", "1", IntPtr.Size == 4 ? "4294967294" : "8589934590");
binaryOperator("nuint", "<<", "nuint", "1", "int", "31", "2147483648");
binaryOperator("nuint", "<<", "nuint", "1", "int", "32", "1");
binaryOperatorNotConstant("nuint", "<<", "nuint", "1", "int", "32", IntPtr.Size == 4 ? "1" : "4294967296");
binaryOperator("nint", ">>", "nint", intMinValue, "int", "0", intMinValue);
binaryOperator("nint", ">>", "nint", intMinValue, "int", "1", "-1073741824");
......@@ -12142,6 +12141,20 @@ void binaryOperatorCheckedOverflow(string opType, string op, string leftType, st
constantExpression(opType, $"unchecked({expr})", expectedResult, Array.Empty<DiagnosticDescription>());
}
void binaryOperatorNotConstant(string opType, string op, string leftType, string leftOperand, string rightType, string rightOperand, string expectedResult)
{
var declarations = $"const {leftType} A = {leftOperand}; const {rightType} B = {rightOperand};";
var expr = $"A {op} B";
constantDeclaration(opType, declarations, expr, null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, expr).WithArguments("Library.F") });
constantDeclaration(opType, declarations, $"checked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"checked({expr})").WithArguments("Library.F") });
constantDeclaration(opType, declarations, $"unchecked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"unchecked({expr})").WithArguments("Library.F") });
expr = $"(({leftType})({leftOperand})) {op} (({rightType})({rightOperand}))";
constantExpression(opType, expr, expectedResult, Array.Empty<DiagnosticDescription>());
constantExpression(opType, $"checked({expr})", expectedResult, Array.Empty<DiagnosticDescription>());
constantExpression(opType, $"unchecked({expr})", expectedResult, Array.Empty<DiagnosticDescription>());
}
void constantDeclaration(string opType, string declarations, string expr, string expectedResult, DiagnosticDescription[] expectedDiagnostics)
{
string sourceA =
......@@ -12247,6 +12260,54 @@ static object Execute(Func<object> f)
{(IntPtr.Size == 4 ? "System.OverflowException" : "0")}");
}
[WorkItem(42460, "https://github.com/dotnet/roslyn/issues/42460")]
[Fact]
public void UncheckedLeftShift_01()
{
string source =
@"using System;
class Program
{
static void Main()
{
const nint x = 0x7fffffff;
Report(x << 1);
Report(LeftShift(x, 1));
}
static nint LeftShift(nint x, int y) => unchecked(x << y);
static void Report(long l) => Console.WriteLine(""{0:x}"", l);
}";
var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
var expectedValue = IntPtr.Size == 4 ? "fffffffffffffffe" : "fffffffe";
CompileAndVerify(comp, expectedOutput:
$@"{expectedValue}
{expectedValue}");
}
[WorkItem(42460, "https://github.com/dotnet/roslyn/issues/42460")]
[Fact]
public void UncheckedLeftShift_02()
{
string source =
@"using System;
class Program
{
static void Main()
{
const nuint x = 0xffffffff;
Report(x << 1);
Report(LeftShift(x, 1));
}
static nuint LeftShift(nuint x, int y) => unchecked(x << y);
static void Report(ulong u) => Console.WriteLine(""{0:x}"", u);
}";
var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9);
var expectedValue = IntPtr.Size == 4 ? "fffffffe" : "1fffffffe";
CompileAndVerify(comp, expectedOutput:
$@"{expectedValue}
{expectedValue}");
}
[WorkItem(42500, "https://github.com/dotnet/roslyn/issues/42500")]
[Fact]
public void ExplicitImplementationReturnTypeDifferences()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册