From 02af1b0ab5873ad87f0fa78ae374ccb4e2a55f90 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 23 Sep 2017 13:03:04 +0200 Subject: [PATCH] [nullables] Lifting support for: bool? == true, bool? != true, bool? == false, bool? != false --- .../IL/Transforms/NullableLiftingTransform.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index a4dd14ed9..d22cc0ea6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -157,6 +157,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } } + if (MatchGetValueOrDefault(condition, out ILVariable v) + && NullableType.GetUnderlyingType(v.Type).IsKnownType(KnownTypeCode.Boolean)) + { + if (MatchHasValueCall(trueInst, v) && falseInst.MatchLdcI4(0)) { + // v.GetValueOrDefault() ? v.HasValue : false + // ==> v == true + context.Step("NullableLiftingTransform: v == true", ifInst); + return new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, + StackType.I4, Sign.None, + new LdLoc(v) { ILRange = trueInst.ILRange }, + new LdcI4(1) { ILRange = falseInst.ILRange } + ) { ILRange = ifInst.ILRange }; + } else if (trueInst.MatchLdcI4(0) && MatchHasValueCall(falseInst, v)) { + // v.GetValueOrDefault() ? false : v.HasValue + // ==> v == false + context.Step("NullableLiftingTransform: v == false", ifInst); + return new Comp(ComparisonKind.Equality, ComparisonLiftingKind.CSharp, + StackType.I4, Sign.None, + new LdLoc(v) { ILRange = falseInst.ILRange }, + trueInst // LdcI4(0) + ) { ILRange = ifInst.ILRange }; + } else if (MatchNegatedHasValueCall(trueInst, v) && falseInst.MatchLdcI4(1)) { + // v.GetValueOrDefault() ? !v.HasValue : true + // ==> v != true + context.Step("NullableLiftingTransform: v != true", ifInst); + return new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, + StackType.I4, Sign.None, + new LdLoc(v) { ILRange = trueInst.ILRange }, + falseInst // LdcI4(1) + ) { ILRange = ifInst.ILRange }; + } else if (trueInst.MatchLdcI4(1) && MatchNegatedHasValueCall(falseInst, v)) { + // v.GetValueOrDefault() ? true : !v.HasValue + // ==> v != false + context.Step("NullableLiftingTransform: v != false", ifInst); + return new Comp(ComparisonKind.Inequality, ComparisonLiftingKind.CSharp, + StackType.I4, Sign.None, + new LdLoc(v) { ILRange = falseInst.ILRange }, + new LdcI4(0) { ILRange = trueInst.ILRange } + ) { ILRange = ifInst.ILRange }; + } + } + return null; } @@ -432,6 +474,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms return call.Arguments[0].MatchLdLoca(out v); } + /// + /// Matches 'call get_HasValue(ldloca v)' + /// + static bool MatchHasValueCall(ILInstruction inst, ILVariable v) + { + return MatchHasValueCall(inst, out var v2) && v == v2; + } + + /// + /// Matches 'logic.not(call get_HasValue(ldloca v))' + /// + static bool MatchNegatedHasValueCall(ILInstruction inst, ILVariable v) + { + return inst.MatchLogicNot(out var arg) && MatchHasValueCall(arg, v); + } + /// /// Matches 'newobj Nullable{underlyingType}.ctor(arg)' ///