Browse Source

Fix bug when decompiling lambdas that are nested 3 or more levels (and have a closure on each level).

pull/144/head
Daniel Grunwald 14 years ago
parent
commit
57db57670c
  1. 22
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  2. 13
      ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

22
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -330,12 +330,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -330,12 +330,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (right is ThisReferenceExpression) {
isParameter = true;
} else if (right is IdentifierExpression) {
// handle parameters only if the whole method contains no other occurrance except for 'right'
// handle parameters only if the whole method contains no other occurrence except for 'right'
ILVariable v = right.Annotation<ILVariable>();
isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1;
if (!isParameter && TypeAnalysis.IsSameType(v.Type, fieldDef.FieldType) && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) {
if (!isParameter && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) {
// parent display class within the same method
// (closure2.localsX = closure1;)
isDisplayClassParentPointerAssignment = true;
}
} else if (right is MemberReferenceExpression) {
// copy of parent display class reference from an outer lambda
// closure2.localsX = this.localsY
MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("right").Single();
do {
// descend into the targets of the mre as long as the field types are closures
FieldDefinition fieldDef2 = mre.Annotation<FieldReference>().ResolveWithinSameModule();
if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ResolveWithinSameModule())) {
break;
}
// if we finally get to a this reference, it's copying a display class parent pointer
if (mre.Target is ThisReferenceExpression) {
isDisplayClassParentPointerAssignment = true;
}
mre = mre.Target as MemberReferenceExpression;
} while (mre != null);
}
if (isParameter || isDisplayClassParentPointerAssignment) {
dict[fieldDef] = right;

13
ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

@ -25,22 +25,26 @@ public static class DelegateConstruction @@ -25,22 +25,26 @@ public static class DelegateConstruction
public Action CaptureOfThisAndParameterInForEach(int a)
{
foreach (var item in Enumerable.Empty<int>()) {
foreach (int item in Enumerable.Empty<int>()) {
if (item > 0) {
return delegate {
CaptureOfThisAndParameter(item + a);
};
}
}
return null;
}
public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
{
foreach (var item in Enumerable.Empty<int>()) {
foreach (int item in Enumerable.Empty<int>()) {
int copyOfItem = item;
if (item > 0) {
return delegate {
CaptureOfThisAndParameter(item + a + copyOfItem);
};
}
}
return null;
}
}
@ -162,4 +166,9 @@ public static class DelegateConstruction @@ -162,4 +166,9 @@ public static class DelegateConstruction
{
return b => c => a + b + c;
}
public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a)
{
return b => c => d => a + b + c + d;
}
}

Loading…
Cancel
Save