Browse Source

Fix #346: incorrect type inference for if statement on ref bool parameter

pull/345/merge
Daniel Grunwald 14 years ago
parent
commit
1b6d1088e8
  1. 24
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  2. 28
      ICSharpCode.Decompiler/Tests/UnsafeCode.cs
  3. 8
      ICSharpCode.Decompiler/Tests/ValueTypes.cs

24
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -385,23 +385,29 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldobj: case ILCode.Ldobj:
{ {
TypeReference type = (TypeReference)expr.Operand; TypeReference type = (TypeReference)expr.Operand;
if (expectedType != null) { var argType = InferTypeForExpression(expr.Arguments[0], null);
int infoAmount = GetInformationAmount(expectedType); if (argType is PointerType || argType is ByReferenceType) {
var elementType = ((TypeSpecification)argType).ElementType;
int infoAmount = GetInformationAmount(elementType);
if (infoAmount == 1 && GetInformationAmount(type) == 8) { if (infoAmount == 1 && GetInformationAmount(type) == 8) {
// A bool can be loaded from both bytes and sbytes. // A bool can be loaded from both bytes and sbytes.
type = expectedType; type = elementType;
} }
if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) { if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) {
// An integer can be loaded as another integer of the same size. // An integer can be loaded as another integer of the same size.
// For integers smaller than 32 bit, the signs must match (as loading performs sign extension) // For integers smaller than 32 bit, the signs must match (as loading performs sign extension)
if (infoAmount >= 32 || IsSigned(expectedType) == IsSigned(type)) bool? elementTypeIsSigned = IsSigned(elementType);
type = expectedType; bool? typeIsSigned = IsSigned(type);
if (elementTypeIsSigned != null && typeIsSigned != null) {
if (infoAmount >= 32 || elementTypeIsSigned == typeIsSigned)
type = elementType;
}
} }
} }
if (forceInferChildren) { if (argType is PointerType)
if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type)) is PointerType) InferTypeForExpression(expr.Arguments[0], new PointerType(type));
InferTypeForExpression(expr.Arguments[0], new PointerType(type)); else
} InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type));
return type; return type;
} }
case ILCode.Stobj: case ILCode.Stobj:

28
ICSharpCode.Decompiler/Tests/UnsafeCode.cs

@ -33,6 +33,21 @@ public class UnsafeCode
return *(long*)(&d); return *(long*)(&d);
} }
public unsafe double ConvertLongToDouble(long d)
{
return *(double*)(&d);
}
public unsafe int ConvertFloatToInt(float d)
{
return *(int*)(&d);
}
public unsafe float ConvertIntToFloat(int d)
{
return *(float*)(&d);
}
public unsafe void PassRefParameterAsPointer(ref int p) public unsafe void PassRefParameterAsPointer(ref int p)
{ {
fixed (int* ptr = &p) fixed (int* ptr = &p)
@ -48,7 +63,8 @@ public class UnsafeCode
public unsafe void AddressInMultiDimensionalArray(double[,] matrix) public unsafe void AddressInMultiDimensionalArray(double[,] matrix)
{ {
fixed (double* ptr = &matrix[1, 2]) { fixed (double* ptr = &matrix[1, 2])
{
this.PointerReferenceExpression(ptr); this.PointerReferenceExpression(ptr);
} }
} }
@ -58,7 +74,7 @@ public class UnsafeCode
fixed (char* ptr = text) fixed (char* ptr = text)
{ {
char* ptr2 = ptr; char* ptr2 = ptr;
while (*ptr2 != 0) while (*ptr2 != '\0')
{ {
*ptr2 = 'A'; *ptr2 = 'A';
ptr2++; ptr2++;
@ -68,7 +84,7 @@ public class UnsafeCode
public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val) public unsafe void PutDoubleIntoLongArray1(long[] array, int index, double val)
{ {
fixed (long* ptr = array) fixed (long* ptr = array)
{ {
((double*)ptr)[index] = val; ((double*)ptr)[index] = val;
} }
@ -76,7 +92,7 @@ public class UnsafeCode
public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val) public unsafe void PutDoubleIntoLongArray2(long[] array, int index, double val)
{ {
fixed (long* ptr = &array[index]) fixed (long* ptr = &array[index])
{ {
*(double*)ptr = val; *(double*)ptr = val;
} }
@ -89,7 +105,7 @@ public class UnsafeCode
public unsafe void FixMultipleStrings(string text) public unsafe void FixMultipleStrings(string text)
{ {
fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text) fixed (char* ptr = text, userName = Environment.UserName, ptr2 = text)
{ {
*ptr = 'c'; *ptr = 'c';
*userName = 'd'; *userName = 'd';
@ -100,7 +116,7 @@ public class UnsafeCode
public unsafe string StackAlloc(int count) public unsafe string StackAlloc(int count)
{ {
char* ptr = stackalloc char[count]; char* ptr = stackalloc char[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
ptr[i] = (char)i; ptr[i] = (char)i;
} }

8
ICSharpCode.Decompiler/Tests/ValueTypes.cs

@ -160,4 +160,12 @@ public static class ValueTypes
s.SetField(); s.SetField();
return p; return p;
} }
public static void UseRefBoolInCondition(ref bool x)
{
if (x)
{
Console.WriteLine("true");
}
}
} }

Loading…
Cancel
Save