From 9b36f6e6da1ca772c41b1541a89290333b1aa745 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sat, 10 Oct 2026 12:48:58 +0200 Subject: [PATCH] Fix #4135: Keep bool-to-int conditional in its local Once comp(x != 0) is removed for a bool x, `int n = b ? 1 : 0` becomes a plain copy of the bool, and copy propagation replaced every load of n with `(b ? 1 : 0)`. Refuse copies between bool and non-bool variables rather than requiring identical types, which would also block legitimate copies such as dynamic -> object or Derived[] -> Base[]. --- .../TestCases/Pretty/TypeAnalysisTests.cs | 17 +++++++++++++++++ .../IL/Transforms/CopyPropagation.cs | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index 5db791b..6f9a467 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -377,6 +377,23 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty { return (int)a == 0; } + + public static byte BoolToIntLocalUsedTwice(byte b, bool flag) + { + int num = (flag ? 1 : 0); + return (byte)(b + num >> num); + } + + public static int BoolToIntLocalAsLoopBound(object[] array, bool skipFirst) + { + int num = (skipFirst ? 1 : 0); + int num2 = array.Length - 1; + while (num2 >= num && array[num2] == null) + { + num2--; + } + return num2; + } } public enum UIntEnum : uint diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index e6d44b0..ddea232 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -124,6 +124,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms { return false; // non-local code move might change semantics when there's split variables } + if (v.Type.IsKnownType(KnownTypeCode.Boolean) != target.Type.IsKnownType(KnownTypeCode.Boolean)) + { + return false; + } switch (v.Kind) { case VariableKind.Parameter: