Browse Source

Implement workaround for #1961

pull/1968/head
Siegfried Pammer 5 years ago
parent
commit
e748e71b56
  1. 6
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  2. 51
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

6
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -992,6 +992,12 @@ namespace ICSharpCode.Decompiler.CSharp
stmt.Parameters.AddRange(exprBuilder.MakeParameters(function.Parameters, function)); stmt.Parameters.AddRange(exprBuilder.MakeParameters(function.Parameters, function));
stmt.ReturnType = exprBuilder.ConvertType(function.Method.ReturnType); stmt.ReturnType = exprBuilder.ConvertType(function.Method.ReturnType);
stmt.Body = nestedBuilder.ConvertAsBlock(function.Body); stmt.Body = nestedBuilder.ConvertAsBlock(function.Body);
Comment prev = null;
foreach (string warning in function.Warnings) {
stmt.Body.InsertChildAfter(prev, prev = new Comment(warning), Roles.Comment);
}
if (function.Method.TypeParameters.Count > 0) { if (function.Method.TypeParameters.Count > 0) {
var astBuilder = exprBuilder.astBuilder; var astBuilder = exprBuilder.astBuilder;
if (astBuilder.ShowTypeParameters) { if (astBuilder.ShowTypeParameters) {

51
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -31,32 +31,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
ILTransformContext context; ILTransformContext context;
ITypeResolveContext decompilationContext; ITypeResolveContext decompilationContext;
readonly Stack<MethodDefinitionHandle> activeMethods = new Stack<MethodDefinitionHandle>();
void IILTransform.Run(ILFunction function, ILTransformContext context) void IILTransform.Run(ILFunction function, ILTransformContext context)
{ {
if (!context.Settings.AnonymousMethods) if (!context.Settings.AnonymousMethods)
return; return;
this.context = context; var prevContext = this.context;
this.decompilationContext = new SimpleTypeResolveContext(function.Method); var prevDecompilationContext = this.decompilationContext;
var cancellationToken = context.CancellationToken; try {
foreach (var inst in function.Descendants) { activeMethods.Push((MethodDefinitionHandle)function.Method.MetadataToken);
cancellationToken.ThrowIfCancellationRequested(); this.context = context;
if (inst is NewObj call) { this.decompilationContext = new SimpleTypeResolveContext(function.Method);
context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); var cancellationToken = context.CancellationToken;
ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); foreach (var inst in function.Descendants) {
if (f != null && target is IInstructionWithVariableOperand instWithVar) { cancellationToken.ThrowIfCancellationRequested();
if (instWithVar.Variable.Kind == VariableKind.Local) { if (inst is NewObj call) {
instWithVar.Variable.Kind = VariableKind.DisplayClassLocal; context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call);
} ILFunction f = TransformDelegateConstruction(call, out ILInstruction target);
var displayClassTypeDef = instWithVar.Variable.Type.GetDefinition(); if (f != null && target is IInstructionWithVariableOperand instWithVar) {
if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) { if (instWithVar.Variable.Kind == VariableKind.Local) {
if (store.Value is NewObj newObj) { instWithVar.Variable.Kind = VariableKind.DisplayClassLocal;
instWithVar.Variable.CaptureScope = BlockContainer.FindClosestContainer(store); }
var displayClassTypeDef = instWithVar.Variable.Type.GetDefinition();
if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) {
if (store.Value is NewObj newObj) {
instWithVar.Variable.CaptureScope = BlockContainer.FindClosestContainer(store);
}
} }
} }
context.StepEndGroup();
} }
context.StepEndGroup();
} }
} finally {
this.context = prevContext;
this.decompilationContext = prevDecompilationContext;
activeMethods.Pop();
} }
} }
@ -131,6 +141,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (LocalFunctionDecompiler.IsLocalFunctionMethod(targetMethod, context)) if (LocalFunctionDecompiler.IsLocalFunctionMethod(targetMethod, context))
return null; return null;
target = value.Arguments[0]; target = value.Arguments[0];
var handle = (MethodDefinitionHandle)targetMethod.MetadataToken;
if (activeMethods.Contains(handle)) {
this.context.Function.Warnings.Add(" Found self-referencing delegate construction. Abort transformation to avoid stack overflow.");
return null;
}
var methodDefinition = context.PEFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)targetMethod.MetadataToken); var methodDefinition = context.PEFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)targetMethod.MetadataToken);
if (!methodDefinition.HasBody()) if (!methodDefinition.HasBody())
return null; return null;
@ -157,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter))); function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter)));
// handle nested lambdas // handle nested lambdas
nestedContext.StepStartGroup("DelegateConstruction (nested lambdas)", function); nestedContext.StepStartGroup("DelegateConstruction (nested lambdas)", function);
((IILTransform)new DelegateConstruction()).Run(function, nestedContext); ((IILTransform)this).Run(function, nestedContext);
nestedContext.StepEndGroup(); nestedContext.StepEndGroup();
function.AddILRange(target); function.AddILRange(target);
function.AddILRange(value); function.AddILRange(value);

Loading…
Cancel
Save