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; + } }