Browse Source

Fix bugs in Expression.Quote/Expression.Invoke handling

Fix bugs in operator handling
pull/988/head
Siegfried Pammer 8 years ago
parent
commit
ad68204b04
  1. 66
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs
  2. 31
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

66
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs

@ -93,7 +93,7 @@ public class ExpressionTrees @@ -93,7 +93,7 @@ public class ExpressionTrees
public void ArrayIndex()
{
ExpressionTrees.ToCode(ExpressionTrees.X(), () => (new[] {
ExpressionTrees.ToCode(ExpressionTrees.X(), () => (new int[3] {
3,
4,
5
@ -119,7 +119,7 @@ public class ExpressionTrees @@ -119,7 +119,7 @@ public class ExpressionTrees
public void ComplexGenericName()
{
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Func<int, bool>)(x => x > 0))(0));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Func<int, bool>)((int x) => x > 0))(0));
}
public void DefaultValue()
@ -134,7 +134,7 @@ public class ExpressionTrees @@ -134,7 +134,7 @@ public class ExpressionTrees
public void IndexerAccess()
{
var dict = Enumerable.Range(1, 20).ToDictionary(n => n.ToString());
Dictionary<string, int> dict = Enumerable.Range(1, 20).ToDictionary((int n) => n.ToString());
ExpressionTrees.ToCode(ExpressionTrees.X(), () => dict["3"] == 3);
}
@ -213,28 +213,28 @@ public class ExpressionTrees @@ -213,28 +213,28 @@ public class ExpressionTrees
public void MembersDefault()
{
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(DateTime).Ticks == 0);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(int[]).Length == 0);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(Type).IsLayoutSequential);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(List<int>).Count);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(int[]).Clone() == null);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(Type).IsInstanceOfType(new object()));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => default(List<int>).AsReadOnly());
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Array)null).Length == 0);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Type)null).IsLayoutSequential);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((List<int>)null).Count);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Array)null).Clone() == null);
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((Type)null).IsInstanceOfType(new object()));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => ((List<int>)null).AsReadOnly());
}
public void DoAssert()
{
field = 37;
ExpressionTrees.ToCode(ExpressionTrees.X(), () => field != C());
ExpressionTrees.ToCode(ExpressionTrees.X(), () => !ReferenceEquals(this, new ExpressionTrees()));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => MyEquals(this) && !MyEquals(default(ExpressionTrees)));
this.field = 37;
ExpressionTrees.ToCode(ExpressionTrees.X(), () => this.field != this.C());
ExpressionTrees.ToCode(ExpressionTrees.X(), () => !object.ReferenceEquals(this, new ExpressionTrees()));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => this.MyEquals(this) && !this.MyEquals(null));
}
int C()
private int C()
{
return field + 5;
}
bool MyEquals(ExpressionTrees other)
private bool MyEquals(ExpressionTrees other)
{
return other != null && field == other.field;
}
@ -295,18 +295,18 @@ public class ExpressionTrees @@ -295,18 +295,18 @@ public class ExpressionTrees
{
ExpressionTrees.ToCode<int, Func<int, Func<int, int>>>(ExpressionTrees.X(), a => b => c => a + b + c);
}
bool Fizz(Func<int, bool> a)
private bool Fizz(Func<int, bool> a)
{
return a(42);
}
bool Buzz(Func<int, bool> a)
private bool Buzz(Func<int, bool> a)
{
return a(42);
}
bool Fizz(Func<string, bool> a)
private bool Fizz(Func<string, bool> a)
{
return a("42");
}
@ -322,7 +322,15 @@ public class ExpressionTrees @@ -322,7 +322,15 @@ public class ExpressionTrees
public void NewArrayAndExtensionMethod()
{
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 }));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new double[3] {
1.0,
2.01,
3.5
}.SequenceEqual(new double[3] {
1.0,
2.01,
3.5
}));
}
public void NewMultiDimArray()
@ -351,7 +359,10 @@ public class ExpressionTrees @@ -351,7 +359,10 @@ public class ExpressionTrees
CloseInput = false,
CheckCharacters = false
};
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new XmlReaderSettings { CloseInput = s.CloseInput, CheckCharacters = s.CheckCharacters }.Equals(s));
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new XmlReaderSettings {
CloseInput = s.CloseInput,
CheckCharacters = s.CheckCharacters
}.Equals(s));
}
public void Quoted()
@ -366,7 +377,12 @@ public class ExpressionTrees @@ -366,7 +377,12 @@ public class ExpressionTrees
public void QuotedWithAnonymous()
{
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new[] { new { X = "a", Y = "b" } }.Select(o => o.X + o.Y).Single());
ExpressionTrees.ToCode(ExpressionTrees.X(), () => new[] {
new {
X = "a",
Y = "b"
}
}.Select(o => o.X + o.Y).Single());
}
public void StaticCall()

31
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
@ -134,7 +135,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -134,7 +135,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// Converts a Expression.Lambda call into an ILFunction.
/// If the conversion fails, null is returned.
/// </summary>
ILFunction ConvertLambda(CallInstruction instruction)
ILInstruction ConvertLambda(CallInstruction instruction)
{
if (instruction.Method.Name != "Lambda" || instruction.Arguments.Count != 2 || instruction.Method.ReturnType.FullName != "System.Linq.Expressions.Expression" || instruction.Method.ReturnType.TypeArguments.Count != 1)
return null;
@ -142,9 +143,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -142,9 +143,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var parameterVariablesList = new List<ILVariable>();
if (!ReadParameters(instruction.Arguments[1], parameterList, parameterVariablesList, new SimpleTypeResolveContext(context.Function.Method)))
return null;
bool isQuotedLambda = instruction.Parent is CallInstruction call && call.Method.FullName == "System.Linq.Expressions.Expression.Quote";
var container = new BlockContainer();
var function = new ILFunction(instruction.Method.ReturnType.TypeArguments[0].TypeArguments.LastOrDefault() ?? context.TypeSystem.Compilation.FindType(KnownTypeCode.Void), parameterList, container);
function.ExpressionTreeType = instruction.Method.ReturnType;
var functionType = instruction.Method.ReturnType.TypeArguments[0];
var function = new ILFunction(functionType.TypeArguments.LastOrDefault() ?? context.TypeSystem.Compilation.FindType(KnownTypeCode.Void), parameterList, container);
if (isQuotedLambda || lambdaStack.Count == 0)
function.ExpressionTreeType = instruction.Method.ReturnType;
function.Variables.AddRange(parameterVariablesList);
lambdaStack.Push(function);
var bodyInstruction = ConvertInstruction(instruction.Arguments[0]);
@ -153,6 +157,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -153,6 +157,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return null;
container.ExpectedResultType = bodyInstruction.ResultType;
container.Blocks.Add(new Block() { Instructions = { new Leave(container, bodyInstruction) } });
if (!isQuotedLambda && lambdaStack.Count > 0)
return new NewObj(functionType.GetConstructors().Single()) {
Arguments = { new LdNull(), function }
};
return function;
}
@ -348,10 +356,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -348,10 +356,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
Arguments = { left, right }
};
case 4:
//if (!trueOrFalse.IsMatch(invocation.Arguments[2]))
// return null;
if (!invocation.Arguments[2].MatchLdcI4(out var isLifted))
return null;
if (!MatchGetMethodFromHandle(invocation.Arguments[3], out method))
return null;
if (isLifted != 0)
method = CSharpOperators.LiftUserDefinedOperator((IMethod)method);
return new Call((IMethod)method) {
Arguments = { left, right }
};
@ -459,7 +469,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -459,7 +469,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var right = ConvertInstruction(invocation.Arguments[1]);
if (right == null)
return null;
if (invocation.Arguments.Count == 3 && MatchGetMethodFromHandle(invocation.Arguments[2], out var method)) {
if (invocation.Arguments.Count == 4 && invocation.Arguments[2].MatchLdcI4(out var isLifted) && MatchGetMethodFromHandle(invocation.Arguments[3], out var method)) {
if (isLifted != 0) {
method = CSharpOperators.LiftUserDefinedOperator((IMethod)method);
}
return new Call((IMethod)method) { Arguments = { left, right } };
}
// TODO: Sign??
@ -617,10 +630,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -617,10 +630,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
Arguments = { left, right }
};
case 4:
//if (!trueOrFalse.IsMatch(invocation.Arguments[2]))
// return null;
if (!invocation.Arguments[2].MatchLdcI4(out var isLifted))
return null;
if (!MatchGetMethodFromHandle(invocation.Arguments[3], out method))
return null;
if (isLifted != 0)
method = CSharpOperators.LiftUserDefinedOperator((IMethod)method);
return new Call((IMethod)method) {
Arguments = { left, right }
};

Loading…
Cancel
Save