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. 25
      ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

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

@ -330,12 +330,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (right is ThisReferenceExpression) { if (right is ThisReferenceExpression) {
isParameter = true; isParameter = true;
} else if (right is IdentifierExpression) { } 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>(); ILVariable v = right.Annotation<ILVariable>();
isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1; 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; 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) { if (isParameter || isDisplayClassParentPointerAssignment) {
dict[fieldDef] = right; dict[fieldDef] = right;

25
ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

@ -25,21 +25,25 @@ public static class DelegateConstruction
public Action CaptureOfThisAndParameterInForEach(int a) public Action CaptureOfThisAndParameterInForEach(int a)
{ {
foreach (var item in Enumerable.Empty<int>()) { foreach (int item in Enumerable.Empty<int>()) {
return delegate { if (item > 0) {
CaptureOfThisAndParameter(item + a); return delegate {
}; CaptureOfThisAndParameter(item + a);
};
}
} }
return null; return null;
} }
public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a)
{ {
foreach (var item in Enumerable.Empty<int>()) { foreach (int item in Enumerable.Empty<int>()) {
int copyOfItem = item; int copyOfItem = item;
return delegate { if (item > 0) {
CaptureOfThisAndParameter(item + a + copyOfItem); return delegate {
}; CaptureOfThisAndParameter(item + a + copyOfItem);
};
}
} }
return null; return null;
} }
@ -162,4 +166,9 @@ public static class DelegateConstruction
{ {
return b => c => a + b + c; 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