Browse Source

Fix #2791: Ensure that the capture scope used is either a loop or the ILFunction root container.

pull/2795/head
Siegfried Pammer 3 years ago
parent
commit
47250d670b
  1. 44
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 16
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  3. 2
      ICSharpCode.Decompiler/IL/ILVariable.cs

44
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -601,6 +601,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction @@ -601,6 +601,50 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
}
}
internal class Issue2791
{
public void M()
{
Run(delegate (object o) {
try
{
List<int> list = o as List<int>;
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
{

16
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -281,7 +281,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -281,7 +281,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
void FindInsertionPoints(AstNode node, int nodeLevel)
{
BlockContainer scope = node.Annotation<BlockContainer>();
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 @@ -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 @@ -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)

2
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -209,7 +209,7 @@ namespace ICSharpCode.Decompiler.IL @@ -209,7 +209,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// This property returns null for variables that are not captured.

Loading…
Cancel
Save