Browse Source

Add ImplicitConversions test and fix some conversions.

pull/728/head
Daniel Grunwald 9 years ago
parent
commit
c3937c3fab
  1. 49
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  2. 6
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  3. 10
      ICSharpCode.Decompiler/Tests/RoundtripAssembly.cs

49
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -156,24 +156,29 @@ namespace ICSharpCode.Decompiler.CSharp @@ -156,24 +156,29 @@ namespace ICSharpCode.Decompiler.CSharp
public TranslatedExpression ConvertTo(IType targetType, ExpressionBuilder expressionBuilder, bool checkForOverflow = false, bool addUncheckedAnnotations = true)
{
var type = this.Type;
if (targetType.IsKnownType(KnownTypeCode.Boolean))
return ConvertToBoolean(expressionBuilder);
if (type.Equals(targetType))
return this;
if ((type.IsKnownType(KnownTypeCode.IntPtr) && targetType.IsKnownType(KnownTypeCode.UIntPtr))
|| (type.IsKnownType(KnownTypeCode.UIntPtr) && targetType.IsKnownType(KnownTypeCode.IntPtr))) {
return Expression.Invoke("ToPointer")
.WithoutILInstruction()
.WithRR(new ResolveResult(new PointerType(expressionBuilder.compilation.FindType(KnownTypeCode.Void))))
.ConvertTo(targetType, expressionBuilder);
var compilation = expressionBuilder.compilation;
if (targetType.IsKnownType(KnownTypeCode.Boolean)) {
// convert to boolean through byte, to simulate the truncation to 8 bits
return this.ConvertTo(compilation.FindType(KnownTypeCode.Byte), expressionBuilder, checkForOverflow, addUncheckedAnnotations)
.ConvertToBoolean(expressionBuilder);
}
if (targetType.IsKnownType(KnownTypeCode.IntPtr) || targetType.IsKnownType(KnownTypeCode.UIntPtr)) {
return Expression.CastTo(expressionBuilder.ConvertType(new PointerType(expressionBuilder.compilation.FindType(KnownTypeCode.Void))))
.CastTo(expressionBuilder.ConvertType(targetType))
.WithoutILInstruction()
.WithRR(expressionBuilder.resolver.WithCheckForOverflow(checkForOverflow).ResolveCast(targetType, ResolveResult));
if ((targetType.IsKnownType(KnownTypeCode.IntPtr) || targetType.IsKnownType(KnownTypeCode.UIntPtr)) && type.Kind != TypeKind.Pointer) {
// (u)long -> IntPtr/UIntPtr casts in C# throw overflow exceptions, even in unchecked context.
// To avoid those, convert via void*.
return this.ConvertTo(new PointerType(compilation.FindType(KnownTypeCode.Void)), expressionBuilder, checkForOverflow, addUncheckedAnnotations)
.ConvertTo(targetType, expressionBuilder, checkForOverflow, addUncheckedAnnotations);
}
if (type.Kind == TypeKind.ByReference && targetType.Kind == TypeKind.Pointer && Expression is DirectionExpression) {
if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.Enum) {
// enum to pointer: convert via underlying type
return this.ConvertTo(type.GetEnumUnderlyingType(), expressionBuilder, checkForOverflow, addUncheckedAnnotations)
.ConvertTo(targetType, expressionBuilder, checkForOverflow, addUncheckedAnnotations);
} else if (targetType.Kind == TypeKind.Pointer && (type.IsKnownType(KnownTypeCode.Boolean) || type.IsKnownType(KnownTypeCode.Char))) {
// bool/char to pointer: convert via uint
return this.ConvertTo(compilation.FindType(KnownTypeCode.UInt32), expressionBuilder, checkForOverflow, addUncheckedAnnotations)
.ConvertTo(targetType, expressionBuilder, checkForOverflow, addUncheckedAnnotations);
} else if (targetType.Kind == TypeKind.Pointer && type.Kind == TypeKind.ByReference && Expression is DirectionExpression) {
// convert from reference to pointer
Expression arg = ((DirectionExpression)Expression).Expression.Detach();
var pointerType = new PointerType(((ByReferenceType)type).ElementType);
@ -182,7 +187,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -182,7 +187,8 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ResolveResult(pointerType));
// perform remaining pointer cast, if necessary
return pointerExpr.ConvertTo(targetType, expressionBuilder);
} else if (targetType.Kind == TypeKind.ByReference) {
}
if (targetType.Kind == TypeKind.ByReference) {
// Convert from integer/pointer to reference.
// First, convert to the corresponding pointer type:
var elementType = ((ByReferenceType)targetType).ElementType;
@ -200,8 +206,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -200,8 +206,8 @@ namespace ICSharpCode.Decompiler.CSharp
// convert from boolean to integer (or enum)
return new ConditionalExpression(
this.Expression,
LdcI4(expressionBuilder.compilation, 1).ConvertTo(targetType, expressionBuilder),
LdcI4(expressionBuilder.compilation, 0).ConvertTo(targetType, expressionBuilder)
LdcI4(compilation, 1).ConvertTo(targetType, expressionBuilder),
LdcI4(compilation, 0).ConvertTo(targetType, expressionBuilder)
).WithoutILInstruction().WithRR(new ResolveResult(targetType));
}
var rr = expressionBuilder.resolver.WithCheckForOverflow(checkForOverflow).ResolveCast(targetType, ResolveResult);
@ -231,8 +237,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -231,8 +237,13 @@ namespace ICSharpCode.Decompiler.CSharp
return this;
}
IType boolType = expressionBuilder.compilation.FindType(KnownTypeCode.Boolean);
if (Expression is PrimitiveExpression && Type.IsKnownType(KnownTypeCode.Int32)) {
bool val = (int)((PrimitiveExpression)Expression).Value != 0;
if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is int) {
bool val = (int)ResolveResult.ConstantValue != 0;
return new PrimitiveExpression(val)
.WithILInstruction(this.ILInstructions)
.WithRR(new ConstantResolveResult(boolType, val));
} else if (ResolveResult.IsCompileTimeConstant && ResolveResult.ConstantValue is byte) {
bool val = (byte)ResolveResult.ConstantValue != 0;
return new PrimitiveExpression(val)
.WithILInstruction(this.ILInstructions)
.WithRR(new ConstantResolveResult(boolType, val));

6
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -185,8 +185,12 @@ namespace ICSharpCode.Decompiler.IL @@ -185,8 +185,12 @@ namespace ICSharpCode.Decompiler.IL
case OpCode.BlockContainer:
var container = (BlockContainer)inst;
containerStack.Push(container);
foreach (var block in container.Blocks)
foreach (var block in container.Blocks) {
ConnectBranches(block);
if (block.Instructions.Count == 0 || !block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable)) {
block.Instructions.Add(new InvalidInstruction("Unexpected end of block"));
}
}
containerStack.Pop();
break;
default:

10
ICSharpCode.Decompiler/Tests/RoundtripAssembly.cs

@ -50,6 +50,16 @@ namespace ICSharpCode.Decompiler.Tests @@ -50,6 +50,16 @@ namespace ICSharpCode.Decompiler.Tests
}
}
[Test]
public void Random_Tests_Implicit_Conversions()
{
try {
RunWithOutput("Random Tests\\TestCases", "ImplicitConversions.exe");
} catch (AssertionException ex) {
Assert.Ignore(ex.Message);
}
}
[Test]
public void Random_Tests_TestCases()
{

Loading…
Cancel
Save