diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs b/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs index 4d67e9bb4..2314532da 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs @@ -21,11 +21,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; using System.Threading; -using System.Threading.Tasks; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -225,6 +222,32 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow goto default; } } + case StObj stobj when mode == StateRangeAnalysisMode.IteratorDispose: + { + if (stobj.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis()) + { + if (field.MemberDefinition == stateField && value.MatchLdcI4(-2)) + { + // Roslyn 4.13 sets the state field in Dispose() to mark the iterator as disposed, + // don't consider this user code. + return stateRange; + } + else if (value.MatchDefaultOrNullOrZero()) + { + // Roslyn 4.13 clears any local hoisted local variables in Dispose(), + // don't consider this user code. + return stateRange; + } + else + { + goto default; + } + } + else + { + goto default; + } + } default: // User code - abort analysis if (mode == StateRangeAnalysisMode.IteratorDispose && !(inst is Leave l && l.IsLeavingFunction))