diff --git a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs index 78e413826..83000fe10 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs @@ -395,6 +395,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms // - increment block if (incrementBlock.Instructions.Count <= 1 || loop.Blocks.Count < 3) return false; + if (StoresRefLocalUsedAfterLoop(loop, incrementBlock)) + return false; context.Step("Transform to for loop: " + loop.EntryPoint.Label, loop); // move the block to the end of the loop: loop.Blocks.MoveElementToEnd(incrementBlock); @@ -467,6 +469,27 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + static bool StoresRefLocalUsedAfterLoop(BlockContainer loop, Block incrementBlock) + { + foreach (var store in incrementBlock.Instructions.SkipLast(1).SelectMany(inst => inst.Descendants).OfType()) + { + var variable = store.Variable; + if (variable.Type.IsByRefLike && IsVariableUsedAfterLoop(loop, variable)) + return true; + } + return false; + } + + static bool IsVariableUsedAfterLoop(BlockContainer loop, ILVariable variable) + { + foreach (var use in variable.LoadInstructions.Concat(variable.AddressInstructions).Concat(variable.StoreInstructions.Cast())) + { + if (loop.GetCommonParent(use) is Block { Kind: BlockKind.ControlFlow } && loop.IsBefore(use)) + return true; + } + return false; + } + bool IsAssignment(ILInstruction inst) { if (inst is StLoc)