diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 27826cd22..af753bb60 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -290,15 +290,30 @@ namespace ICSharpCode.Decompiler.CSharp out var singleGetter, out var needsUninlining, out var itemVariable)) return null; var collectionExpr = m.Get("collection").Single(); + if (collectionExpr is BaseReferenceExpression) { + collectionExpr = new ThisReferenceExpression().CopyAnnotationsFrom(collectionExpr); + } if (needsUninlining) { + var type = singleGetter.Method.ReturnType; + ILInstruction instToReplace = singleGetter; + switch (instToReplace.Parent) { + case CastClass cc: + type = cc.Type; + instToReplace = cc; + break; + case UnboxAny ua: + type = ua.Type; + instToReplace = ua; + break; + } itemVariable = currentFunction.RegisterVariable( - VariableKind.ForeachLocal, singleGetter.Method.ReturnType, + VariableKind.ForeachLocal, type, AssignVariableNames.GenerateVariableName(currentFunction, collectionExpr.Annotation(), "item") ); - singleGetter.ReplaceWith(new LdLoc(itemVariable)); - body.Instructions.Insert(0, new StLoc(itemVariable, singleGetter)); + instToReplace.ReplaceWith(new LdLoc(itemVariable)); + body.Instructions.Insert(0, new StLoc(itemVariable, instToReplace)); } else { - if (!itemVariable.IsSingleDefinition) + if (itemVariable.StoreCount != 1) return null; itemVariable.Kind = VariableKind.ForeachLocal; itemVariable.Name = AssignVariableNames.GenerateVariableName(currentFunction, collectionExpr.Annotation(), "item", itemVariable); @@ -322,14 +337,17 @@ namespace ICSharpCode.Decompiler.CSharp var loads = (enumerator.LoadInstructions.OfType().Concat(enumerator.AddressInstructions.OfType())).Where(ld => !ld.IsDescendantOf(moveNextUsage)).ToArray(); if (loads.Length == 1 && ParentIsCurrentGetter(loads[0])) { singleGetter = (CallInstruction)loads[0].Parent; - needsUninlining = !singleGetter.Parent.MatchStLoc(out existingVariable); + ILInstruction inst = singleGetter; + while (inst.Parent is UnboxAny || inst.Parent is CastClass) + inst = inst.Parent; + needsUninlining = !inst.Parent.MatchStLoc(out existingVariable); } return singleGetter != null && singleGetter.IsDescendantOf(body.Instructions[0]) && ILInlining.CanUninline(singleGetter, body.Instructions[0]); } bool ParentIsCurrentGetter(ILInstruction inst) { - return inst.Parent is CallVirt cv && cv.Method.IsAccessor && + return inst.Parent is CallInstruction cv && cv.Method.IsAccessor && cv.Method.AccessorOwner is IProperty p && p.Getter.Equals(cv.Method); } #endregion