diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs
index 7cccce8bd..689b2860d 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/AwaitInFinallyTransform.cs
@@ -16,12 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
@@ -109,7 +107,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (objectVariable.LoadCount != 1 || objectVariable.StoreCount > 2)
continue;
- var beforeExceptionCaptureBlock = (Block)LocalFunctionDecompiler.GetStatement(objectVariable.LoadInstructions[0])?.Parent;
+ var beforeExceptionCaptureBlock = Block.FindClosestBlock(objectVariable.LoadInstructions[0]);
if (beforeExceptionCaptureBlock == null)
continue;
diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
index 479a8f207..06ea213f0 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs
@@ -383,6 +383,22 @@ namespace ICSharpCode.Decompiler.IL
return null;
}
+ ///
+ /// Gets the closest ancestor that is child of a control-flow (top-level) Block.
+ /// Returns null, if the instruction is not a descendant of a Block.
+ ///
+ public static ILInstruction? GetContainingStatement(ILInstruction inst)
+ {
+ var curr = inst;
+ while (curr != null)
+ {
+ if (curr.Parent is Block { Kind: BlockKind.ControlFlow })
+ return curr;
+ curr = curr.Parent;
+ }
+ return null;
+ }
+
public bool MatchInlineAssignBlock([NotNullWhen(true)] out CallInstruction? call, [NotNullWhen(true)] out ILInstruction? value)
{
call = null;
diff --git a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
index f68c6d076..75b3860d9 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/DetectCatchWhenConditionBlocks.cs
@@ -16,9 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@@ -107,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// We are only interested in store "statements" copying the exception variable
// without modifying it.
- var statement = LocalFunctionDecompiler.GetStatement(load);
+ var statement = Block.GetContainingStatement(load);
if (!(statement is StLoc stloc))
{
i++;
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
index 7d36fb9e2..f73f624f1 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
@@ -312,25 +312,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
protected internal override void VisitNewObj(NewObj inst)
{
- Block block;
if (TransformSpanTCtorContainingStackAlloc(inst, out ILInstruction locallocSpan))
{
context.Step("new Span(stackalloc) -> stackalloc Span", inst);
inst.ReplaceWith(locallocSpan);
- block = null;
- ILInstruction stmt = locallocSpan;
- while (stmt.Parent != null)
- {
- if (stmt.Parent is Block b)
- {
- block = b;
- break;
- }
- stmt = stmt.Parent;
- }
+ ILInstruction stmt = Block.GetContainingStatement(locallocSpan);
// Special case to eliminate extra store
if (stmt.GetNextSibling() is StLoc storeStmt && storeStmt.Value is LdLoc)
- ILInlining.InlineIfPossible(block, stmt.ChildIndex, context);
+ ILInlining.InlineIfPossible((Block)stmt.Parent, stmt.ChildIndex, context);
return;
}
if (TransformArrayInitializers.TransformSpanTArrayInitialization(inst, context, out var replacement))
diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
index c377238c1..4b73758b5 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs
@@ -575,17 +575,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
&& TransformDisplayClassUsage.IsPotentialClosure(context.CurrentTypeDefinition, type);
}
- internal static ILInstruction GetStatement(ILInstruction inst)
- {
- while (inst.Parent != null)
- {
- if (inst.Parent is Block b && b.Kind == BlockKind.ControlFlow)
- return inst;
- inst = inst.Parent;
- }
- return inst;
- }
-
LocalFunctionMethod ReduceToLocalFunction(IMethod method, int typeParametersToRemove)
{
int parametersToRemove = 0;
@@ -747,7 +736,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (variable.Kind == VariableKind.Parameter)
return null;
if (type.Kind == TypeKind.Struct)
- return GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
+ return Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
else
return (StLoc)variable.StoreInstructions[0];
}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
index c433c3b81..103c77d79 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs
@@ -604,7 +604,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (context.Settings.LocalFunctions && closureType?.Kind == TypeKind.Struct
&& variable.UsesInitialValue && IsPotentialClosure(context, closureType))
{
- initializer = LocalFunctionDecompiler.GetStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
+ initializer = Block.GetContainingStatement(variable.AddressInstructions.OrderBy(i => i.StartILOffset).First());
return true;
}
return false;