diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
index 331cb7b4a..6b2b83a2f 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/NativeInts.cs
@@ -83,6 +83,25 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine((nuint)i + u);
}
+ public void Shifts()
+ {
+ Console.WriteLine(i << i32);
+ Console.WriteLine(i >> i32);
+ Console.WriteLine(u >> i32);
+ Console.WriteLine(u << i32);
+ }
+
+ public void Comparisons()
+ {
+ Console.WriteLine(i < i32);
+ Console.WriteLine(i <= i32);
+ Console.WriteLine(i > i32);
+ Console.WriteLine(i >= i32);
+ Console.WriteLine(i == (nint)u);
+ Console.WriteLine(i < (nint)u);
+ Console.WriteLine((nuint)i < u);
+ }
+
public object[] Boxing()
{
return new object[10] {
diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 658320030..b98ab1317 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -795,7 +795,7 @@ namespace ICSharpCode.Decompiler.CSharp
} else if (rightUType.GetStackType() == inst.InputType && !rightUType.IsSmallIntegerType()) {
targetType = rightUType;
} else {
- targetType = compilation.FindType(inst.InputType.ToKnownTypeCode(leftUType.GetSign()));
+ targetType = FindType(inst.InputType, leftUType.GetSign());
}
}
if (inst.IsLifted) {
@@ -1316,6 +1316,9 @@ namespace ICSharpCode.Decompiler.CSharp
return resultExpr;
}
+ ///
+ /// Gets a type matching the stack type and sign.
+ ///
IType FindType(StackType stackType, Sign sign)
{
if (stackType == StackType.I && settings.NativeIntegers) {
@@ -1325,6 +1328,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
+ ///
+ /// Gets a type used for performing arithmetic with the stack type and sign.
+ ///
+ /// This may result in a larger type than requested when the selected C# version
+ /// doesn't support native integers.
+ /// Should only be used after a call to PrepareArithmeticArgument()
+ /// to ensure that we're not preserving extra bits from an oversized TranslatedExpression.
+ ///
IType FindArithmeticType(StackType stackType, Sign sign)
{
if (stackType == StackType.I) {
@@ -1396,6 +1407,8 @@ namespace ICSharpCode.Decompiler.CSharp
var left = Translate(inst.Left);
var right = Translate(inst.Right);
+ left = PrepareArithmeticArgument(left, inst.LeftInputType, inst.Sign, inst.IsLifted);
+
Sign sign = inst.Sign;
var leftUType = NullableType.GetUnderlyingType(left.Type);
if (leftUType.IsCSharpSmallIntegerType() && sign != Sign.Unsigned && inst.UnderlyingResultType == StackType.I4) {
@@ -1407,12 +1420,7 @@ namespace ICSharpCode.Decompiler.CSharp
// if we don't need a specific sign, prefer keeping that of the input:
sign = leftUType.GetSign();
}
- IType targetType;
- if (inst.UnderlyingResultType == StackType.I4) {
- targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32);
- } else {
- targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt64 : KnownTypeCode.Int64);
- }
+ IType targetType = FindArithmeticType(inst.UnderlyingResultType, sign);
if (NullableType.IsNullable(left.Type)) {
targetType = NullableType.Create(compilation, targetType);
}