Browse Source

Fix #1638: YieldReturnDecompiler: Recognize Dispose method of yield fsm by looking at the method impls, if its name was mangled.

issue1638
Siegfried Pammer 5 years ago
parent
commit
a4d05c889f
  1. 40
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

40
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -535,7 +535,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{ {
if (isCompiledWithMono) if (isCompiledWithMono)
{ {
disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "Dispose"); disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => ImplementsDisposeMethod(m, "Dispose"));
var function = CreateILAst(disposeMethod, context); var function = CreateILAst(disposeMethod, context);
BlockContainer body = (BlockContainer)function.Body; BlockContainer body = (BlockContainer)function.Body;
@ -558,12 +558,48 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
else else
{ {
// Non-Mono: analyze try-finally structure in Dispose() // Non-Mono: analyze try-finally structure in Dispose()
disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "System.IDisposable.Dispose"); disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => ImplementsDisposeMethod(m, "System.IDisposable.Dispose"));
var function = CreateILAst(disposeMethod, context); var function = CreateILAst(disposeMethod, context);
var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorDispose, stateField); var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(function.Body, LongSet.Universe); rangeAnalysis.AssignStateRanges(function.Body, LongSet.Universe);
finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange; finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
} }
bool ImplementsDisposeMethod(MethodDefinitionHandle m, string disposeMethodName)
{
var def = metadata.GetMethodDefinition(m);
var name = metadata.GetString(def.Name);
if (name == disposeMethodName)
return true;
foreach (var i in m.GetMethodImplementations(metadata))
{
var impl = metadata.GetMethodImplementation(i);
switch (impl.MethodDeclaration.Kind)
{
case HandleKind.MethodDefinition:
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)impl.MethodDeclaration);
if (!md.GetDeclaringType().GetFullTypeName(metadata).IsKnownType(KnownTypeCode.IDisposable))
continue;
if (metadata.GetString(md.Name) != "Dispose")
continue;
return true;
case HandleKind.MemberReference:
var mr = metadata.GetMemberReference((MemberReferenceHandle)impl.MethodDeclaration);
if (mr.GetKind() != MemberReferenceKind.Method)
continue;
if (!mr.Parent.GetFullTypeName(metadata).IsKnownType(KnownTypeCode.IDisposable))
continue;
if (metadata.GetString(mr.Name) != "Dispose")
continue;
return true;
default:
continue;
}
}
return false;
}
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]

Loading…
Cancel
Save