diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs index 4046bebd1..6fe579180 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs @@ -601,6 +601,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction } } + internal class Issue2791 + { + public void M() + { + Run(delegate (object o) { + try + { + List list = o as List; + Action action = delegate { + list.Select((int x) => x * 2); + }; +#if OPT && ROSLYN + Action obj = delegate { +#else + Action action2 = delegate { +#endif + list.Select((int x) => x * 2); + }; + Console.WriteLine(); + action(); + Console.WriteLine(); +#if OPT && ROSLYN + obj(); +#else + action2(); +#endif + } + catch (Exception) + { + Console.WriteLine("catch"); + } + finally + { + Console.WriteLine("finally"); + } + }, null); + } + + private void Run(ParameterizedThreadStart del, object x) + { + del(x); + } + } + [AttributeUsage(AttributeTargets.All)] internal class MyAttribute : Attribute { diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 4eda0ba10..b146e85a4 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -281,7 +281,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms void FindInsertionPoints(AstNode node, int nodeLevel) { BlockContainer scope = node.Annotation(); - if (scope != null && (scope.EntryPoint.IncomingEdgeCount > 1 || scope.Parent is ILFunction)) + if (scope != null && IsRelevantScope(scope)) { // track loops and function bodies as scopes, for comparison with CaptureScope. scopeTracking.Add((new InsertionPoint { level = nodeLevel, nextNode = node }, scope)); @@ -316,9 +316,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { InsertionPoint newPoint; int startIndex = scopeTracking.Count - 1; - if (variable.CaptureScope != null && startIndex > 0 && variable.CaptureScope != scopeTracking[startIndex].Scope) + BlockContainer captureScope = variable.CaptureScope; + while (captureScope != null && !IsRelevantScope(captureScope)) { - while (startIndex > 0 && scopeTracking[startIndex].Scope != variable.CaptureScope) + captureScope = BlockContainer.FindClosestContainer(captureScope.Parent); + } + if (captureScope != null && startIndex > 0 && captureScope != scopeTracking[startIndex].Scope) + { + while (startIndex > 0 && scopeTracking[startIndex].Scope != captureScope) startIndex--; newPoint = scopeTracking[startIndex + 1].InsertionPoint; } @@ -366,6 +371,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } + private static bool IsRelevantScope(BlockContainer scope) + { + return scope.EntryPoint.IncomingEdgeCount > 1 || scope.Parent is ILFunction; + } + internal static bool VariableNeedsDeclaration(VariableKind kind) { switch (kind) diff --git a/ICSharpCode.Decompiler/IL/ILVariable.cs b/ICSharpCode.Decompiler/IL/ILVariable.cs index bbe6dfaa6..5f2610449 100644 --- a/ICSharpCode.Decompiler/IL/ILVariable.cs +++ b/ICSharpCode.Decompiler/IL/ILVariable.cs @@ -209,7 +209,7 @@ namespace ICSharpCode.Decompiler.IL /// /// Gets the block container in which this variable is captured. /// For captured variables declared inside the loop, the capture scope is the BlockContainer of the loop. - /// For captured variables declared outside of the loop, the capture scope is the BlockContainer of the parent. + /// For captured variables declared outside of the loop, the capture scope is the BlockContainer of the parent function. /// /// /// This property returns null for variables that are not captured.