diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
index d7678dd54..d5d50f352 100644
--- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
+++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
@@ -515,14 +515,20 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Rem_Un:
return InferArgumentsInBinaryOperator(expr, false, expectedType);
case ILCode.Shl:
- case ILCode.Shr:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
- return InferTypeForExpression(expr.Arguments[0], typeSystem.Int32);
+ if (expectedType != null && (
+ expectedType.MetadataType == MetadataType.Int32 || expectedType.MetadataType == MetadataType.UInt32 ||
+ expectedType.MetadataType == MetadataType.Int64 || expectedType.MetadataType == MetadataType.UInt64)
+ )
+ return NumericPromotion(InferTypeForExpression(expr.Arguments[0], expectedType));
+ else
+ return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ case ILCode.Shr:
case ILCode.Shr_Un:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
- return InferTypeForExpression(expr.Arguments[0], typeSystem.UInt32);
+ return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
case ILCode.CompoundAssignment:
{
TypeReference varType = InferTypeForExpression(expr.Arguments[0].Arguments[0], null);
@@ -763,6 +769,27 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
+ ///
+ /// Promotes primitive types smaller than int32 to int32.
+ ///
+ ///
+ /// Always promotes to signed int32.
+ ///
+ TypeReference NumericPromotion(TypeReference type)
+ {
+ if (type == null)
+ return null;
+ switch (type.MetadataType) {
+ case MetadataType.SByte:
+ case MetadataType.Int16:
+ case MetadataType.Byte:
+ case MetadataType.UInt16:
+ return typeSystem.Int32;
+ default:
+ return type;
+ }
+ }
+
TypeReference HandleConversion(int targetBitSize, bool targetSigned, ILExpression arg, TypeReference expectedType, TypeReference targetType)
{
if (targetBitSize >= NativeInt && expectedType is PointerType) {
diff --git a/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
index 813005933..034d0c8bf 100644
--- a/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
+++ b/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
@@ -24,4 +24,34 @@ public class TypeAnalysisTests
{
return (byte)(256 - (int)b);
}
+
+ public int GetHashCode(long num)
+ {
+ return (int)num ^ (int)(num >> 32);
+ }
+
+ public int ShiftByte(byte num)
+ {
+ return (int)num << 8;
+ }
+
+ public int RShiftByte(byte num)
+ {
+ return num >> 8;
+ }
+
+ public int RShiftByteWithSignExtension(byte num)
+ {
+ return (sbyte)num >> 8;
+ }
+
+ public int RShiftSByte(sbyte num)
+ {
+ return num >> 8;
+ }
+
+ public int RShiftSByteWithZeroExtension(sbyte num)
+ {
+ return (byte)num >> 8;
+ }
}