Browse Source

Fix #1913: Make sure to declare local variables captured by local functions before the first invocation of the local function.

pull/2005/head
Siegfried Pammer 5 years ago
parent
commit
4f7ca65408
  1. 1
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 14
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  3. 6
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

1
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -200,6 +200,7 @@ namespace ICSharpCode.Decompiler.CSharp
int skipCount = localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters; int skipCount = localFunction.ReducedMethod.NumberOfCompilerGeneratedTypeParameters;
ide.TypeArguments.AddRange(method.TypeArguments.Skip(skipCount).Select(expressionBuilder.ConvertType)); ide.TypeArguments.AddRange(method.TypeArguments.Skip(skipCount).Select(expressionBuilder.ConvertType));
} }
ide.AddAnnotation(localFunction);
target = ide.WithoutILInstruction() target = ide.WithoutILInstruction()
.WithRR(ToMethodGroup(method, localFunction)); .WithRR(ToMethodGroup(method, localFunction));
} else { } else {

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

@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
@ -257,7 +256,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (node is IdentifierExpression identExpr) { if (node is IdentifierExpression identExpr) {
var rr = identExpr.GetResolveResult() as ILVariableResolveResult; var rr = identExpr.GetResolveResult() as ILVariableResolveResult;
if (rr != null && VariableNeedsDeclaration(rr.Variable.Kind)) { if (rr != null && VariableNeedsDeclaration(rr.Variable.Kind)) {
var variable = rr.Variable; FindInsertionPointForVariable(rr.Variable);
} else if (identExpr.Annotation<ILFunction>() is ILFunction localFunction && localFunction.Kind == ILFunctionKind.LocalFunction) {
foreach (var v in localFunction.CapturedVariables) {
if (VariableNeedsDeclaration(v.Kind))
FindInsertionPointForVariable(v);
}
}
void FindInsertionPointForVariable(ILVariable variable)
{
InsertionPoint newPoint; InsertionPoint newPoint;
int startIndex = scopeTracking.Count - 1; int startIndex = scopeTracking.Count - 1;
if (variable.CaptureScope != null && startIndex > 0 && variable.CaptureScope != scopeTracking[startIndex].Scope) { if (variable.CaptureScope != null && startIndex > 0 && variable.CaptureScope != scopeTracking[startIndex].Scope) {
@ -287,7 +295,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} else { } else {
v = new VariableToDeclare(variable, variable.HasInitialValue, v = new VariableToDeclare(variable, variable.HasInitialValue,
newPoint, identExpr, sourceOrder: variableDict.Count); newPoint, identExpr, sourceOrder: variableDict.Count);
variableDict.Add(rr.Variable, v); variableDict.Add(variable, v);
} }
} }
} }

6
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -73,6 +73,12 @@ namespace ICSharpCode.Decompiler.IL
/// </summary> /// </summary>
public BlockContainer DeclarationScope { get; internal set; } public BlockContainer DeclarationScope { get; internal set; }
/// <summary>
/// Gets the set of captured variables by this ILFunction.
/// </summary>
/// <remarks>This is populated by the <see cref="TransformDisplayClassUsage" /> step.</remarks>
public HashSet<ILVariable> CapturedVariables { get; } = new HashSet<ILVariable>(ILVariableEqualityComparer.Instance);
/// <summary> /// <summary>
/// List of warnings of ILReader. /// List of warnings of ILReader.
/// </summary> /// </summary>

Loading…
Cancel
Save