diff --git a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs index 66f431809e..21ec3becd7 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs @@ -254,7 +254,9 @@ private bool ReduceNesting(Block block, IfInstruction ifInst, ILInstruction exit ifInst = elseIfInst; } - if (!ShouldReduceNesting(ifInst.FalseInst, maxStatements, maxDepth)) + // A chain with no trailing else has no block to reduce: ifInst.FalseInst is a bare Nop. + // Guarding here keeps the else-block cast in ExtractElseBlock safe (#3891). + if (ifInst.FalseInst is not Block falseBlock || !ShouldReduceNesting(falseBlock, maxStatements, maxDepth)) return false; // extract the else block and insert exit points all the way up the else-if tree @@ -582,16 +584,16 @@ private void ComputeStats(ILInstruction inst, ref int numStatements, ref int max /// /// Heuristic to determine whether it is worth duplicating exits into the preceeding sibling blocks (then/else-if/case) - /// in order to reduce the nesting of inst by 1 + /// in order to reduce the nesting of block by 1 /// - /// The instruction heading the nested candidate block + /// The nested candidate block (an else or default block) /// The number of statements in the largest sibling block /// The relative depth of the most nested statement in the sibling blocks /// - private bool ShouldReduceNesting(ILInstruction inst, int maxStatements, int maxDepth) + private bool ShouldReduceNesting(Block block, int maxStatements, int maxDepth) { int maxStatements2 = 0, maxDepth2 = 0; - UpdateStats(inst, ref maxStatements2, ref maxDepth2); + UpdateStats(block, ref maxStatements2, ref maxDepth2); // if the max depth is 2, always reduce nesting (total depth 3 or more) // if the max depth is 1, reduce nesting if this block is the largest // otherwise reduce nesting only if this block is twice as large as any other