diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index a124786b7..3ca987c66 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.CSharp.PatternMatching; using Mono.Cecil; namespace Decompiler.Transforms @@ -182,22 +183,22 @@ namespace Decompiler.Transforms for (cur = next; cur != null; cur = next) { next = cur.NextSibling; - // Delete any following statements as long as they assign simple variables to the display class: + // Delete any following statements as long as they assign parameters to the display class: // Test for the pattern: // "variableName.MemberName = right;" - ExpressionStatement es = cur as ExpressionStatement; - if (es == null) + ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement( + new AssignmentExpression( + new NamedNode("left", new MemberReferenceExpression { Target = new IdentifierExpression(variable.Name) }).ToExpression(), + new AnyNode("right").ToExpression() + ) + ); + Match m = closureFieldAssignmentPattern.Match(cur); + if (m != null && IsParameter(m.Get("right").Single())) { + dict[m.Get("left").Single().MemberName] = m.Get("right").Single(); + cur.Remove(); + } else { break; - AssignmentExpression ae = es.Expression as AssignmentExpression; - if (ae == null || ae.Operator != AssignmentOperatorType.Assign) - break; - MemberReferenceExpression left = ae.Left as MemberReferenceExpression; - if (left == null || !IsParameter(ae.Right)) - break; - if (!(left.Target is IdentifierExpression) || (left.Target as IdentifierExpression).Identifier != variable.Name) - break; - dict[left.MemberName] = ae.Right; - es.Remove(); + } } // Now create variables for all fields of the display class (except for those that we already handled) diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 6ed396d20..d81eddee9 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -43,8 +43,12 @@ namespace Decompiler if (expr != null) { ILVariable v = expr.Operand as ILVariable; if (v != null && v.IsGenerated && v.Type == null && expr.Code == ILCode.Stloc && HasSingleLoad(v)) { - // don't deal with this node or its children yet, - // wait for the expected type to be inferred first + // Don't deal with this node or its children yet, + // wait for the expected type to be inferred first. + // This happens with the arg_... variables introduced by the ILAst - we skip inferring the whole statement, + // and first infer the statement that reads from the arg_... variable. + // The ldloc inference will write the expected type to the variable, and the next InferRemainingStores() pass + // will then infer this statement with the correct expected type. storedToGeneratedVariables.Add(expr); return; }