diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs index 4ee35ab3d..17b30df9c 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Correctness/Comparisons.cs @@ -52,6 +52,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine(IsNull(new OverloadedOperators())); Console.WriteLine(NullIs(new OverloadedOperators())); Console.WriteLine(NullIsNot(new OverloadedOperators())); + + Console.WriteLine("IntBranchInConditionSlot:"); + IntBranchInConditionSlot(1, 0x100, false); + IntBranchInConditionSlot(0, 0x100, true); + NegatedIntBranchInConditionSlot(1, 0x100, false); + NegatedIntBranchInConditionSlot(0, 0x100, true); return 0; } @@ -92,6 +98,26 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness Console.WriteLine("uint: {0} == Id(-1) = {1}", i, i == Id(-1)); } + // The conditional has an int-valued true branch and a bool false branch, so it is + // compiled to an I4 value that the surrounding 'if' tests for non-zero. Converting + // that value to bool must keep the non-zero test: truncating it to 8 bits first + // loses every bit from 8 up, and flags = 0x100 then reads as false. + static void IntBranchInConditionSlot(int x, int flags, bool other) + { + if ((x > 0) ? (flags != 0) : other) + Console.WriteLine("true"); + else + Console.WriteLine("false"); + } + + static void NegatedIntBranchInConditionSlot(int x, int flags, bool other) + { + if (!((x > 0) ? (flags != 0) : other)) + Console.WriteLine("negated: false"); + else + Console.WriteLine("negated: true"); + } + static void Issue2398(long value) { if ((int)value != 0) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index b953e0652..230484c89 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -396,8 +396,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (astBuilder.NameLookupMode == NameLookupMode.Type) { AstType outermostType = simpleType; - while (outermostType.Parent is AstType) - outermostType = (AstType)outermostType.Parent; + while (outermostType.Parent is AstType parent) + outermostType = parent; if (outermostType.Parent is TypeReferenceExpression) { // ILSpy uses TypeReferenceExpression in expression context even when the C# parser diff --git a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs index 19d4930c4..ceafb59e7 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs @@ -123,6 +123,12 @@ namespace ICSharpCode.Decompiler.IL } } output.Write(OpCode); + if (resultType != null) + { + output.Write(" ["); + output.Write(resultType.ReflectionName); + output.Write(']'); + } output.Write(" ("); condition.WriteTo(output, options); output.Write(") "); diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index c563248c7..d317578ab 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -96,10 +96,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms return; } else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None - && inst.Right.MatchLdcI4(0) && (IfInstruction.IsInConditionSlot(inst) || inst.Left is Comp)) + && inst.Right.MatchLdcI4(0) + && (inst.Left.InferType(context.TypeSystem).IsKnownType(KnownTypeCode.Boolean) + || inst.Left.MatchLdcI4(0) || inst.Left.MatchLdcI4(1))) { - // if (comp(x != 0)) ==> if (x) - // comp(comp(...) != 0) => comp(...) + // When `x` is known to be 0 or 1: + // `comp(x != 0) => x` context.Step("Remove redundant comp(... != 0)", inst); inst.Left.AddILRange(inst); var left = inst.Left;