Browse Source

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

pull/345/merge
Daniel Grunwald 13 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 @@ -385,23 +385,29 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldobj:
{
TypeReference type = (TypeReference)expr.Operand;
if (expectedType != null) {
int infoAmount = GetInformationAmount(expectedType);
var argType = InferTypeForExpression(expr.Arguments[0], null);
if (argType is PointerType || argType is ByReferenceType) {
var elementType = ((TypeSpecification)argType).ElementType;
int infoAmount = GetInformationAmount(elementType);
if (infoAmount == 1 && GetInformationAmount(type) == 8) {
// A bool can be loaded from both bytes and sbytes.
type = expectedType;
type = elementType;
}
if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) {
// 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)
if (infoAmount >= 32 || IsSigned(expectedType) == IsSigned(type))
type = expectedType;
bool? elementTypeIsSigned = IsSigned(elementType);
bool? typeIsSigned = IsSigned(type);
if (elementTypeIsSigned != null && typeIsSigned != null) {
if (infoAmount >= 32 || elementTypeIsSigned == typeIsSigned)
type = elementType;
}
}
}
if (forceInferChildren) {
if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type)) is PointerType)
InferTypeForExpression(expr.Arguments[0], new PointerType(type));
}
if (argType is PointerType)
InferTypeForExpression(expr.Arguments[0], new PointerType(type));
else
InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type));
return type;
}
case ILCode.Stobj:

28
ICSharpCode.Decompiler/Tests/UnsafeCode.cs

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

8
ICSharpCode.Decompiler/Tests/ValueTypes.cs

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

Loading…
Cancel
Save