|
|
|
@ -225,14 +225,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -225,14 +225,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
return LiftCSharpEqualityComparison(comp, ComparisonKind.Inequality, trueInst) |
|
|
|
|
?? LiftCSharpUserEqualityComparison(comp, ComparisonKind.Inequality, trueInst); |
|
|
|
|
} |
|
|
|
|
else if (IsGenericNewPattern(comp.Left, comp.Right, trueInst, falseInst)) |
|
|
|
|
else if (!comp.IsLifted && IsGenericNewPattern(comp.Left, comp.Right, trueInst, falseInst)) |
|
|
|
|
{ |
|
|
|
|
// (default(T) == null) ? Activator.CreateInstance<T>() : default(T)
|
|
|
|
|
// => Activator.CreateInstance<T>()
|
|
|
|
|
return trueInst; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
else if (!comp.IsLifted) |
|
|
|
|
{ |
|
|
|
|
// Not (in)equality, but one of < <= > >=.
|
|
|
|
|
// Returns false unless all HasValue bits are true.
|
|
|
|
@ -401,11 +401,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -401,11 +401,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
{ |
|
|
|
|
result = default(CompOrDecimal); |
|
|
|
|
result.Instruction = inst; |
|
|
|
|
if (inst is Comp comp && !comp.IsLifted) |
|
|
|
|
if (inst is Comp comp) |
|
|
|
|
{ |
|
|
|
|
result.Kind = comp.Kind; |
|
|
|
|
result.Left = comp.Left; |
|
|
|
|
result.Right = comp.Right; |
|
|
|
|
result.IsLifted = comp.IsLifted; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
else if (inst is Call call && call.Method.IsOperator && call.Arguments.Count == 2 && !call.IsLifted) |
|
|
|
@ -449,6 +450,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -449,6 +450,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
public ComparisonKind Kind; |
|
|
|
|
public ILInstruction Left; |
|
|
|
|
public ILInstruction Right; |
|
|
|
|
public bool IsLifted; |
|
|
|
|
|
|
|
|
|
public IType LeftExpectedType { |
|
|
|
|
get { |
|
|
|
@ -528,6 +530,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -528,6 +530,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
// The HasValue comparison must be the same operator as the Value comparison.
|
|
|
|
|
if (hasValueTest is Comp hasValueComp) |
|
|
|
|
{ |
|
|
|
|
if (valueComp.IsLifted || hasValueComp.IsLifted) |
|
|
|
|
return null; |
|
|
|
|
// Comparing two nullables: HasValue comparison must be the same operator as the Value comparison
|
|
|
|
|
if ((hasValueTestNegated ? hasValueComp.Kind.Negate() : hasValueComp.Kind) != newComparisonKind) |
|
|
|
|
return null; |
|
|
|
@ -576,6 +580,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -576,6 +580,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
/// </summary>
|
|
|
|
|
ILInstruction LiftCSharpComparison(CompOrDecimal comp, ComparisonKind newComparisonKind) |
|
|
|
|
{ |
|
|
|
|
if (comp.IsLifted) |
|
|
|
|
{ |
|
|
|
|
// Happens when legacy csc generates 'num.GetValueOrDefault() == const && num.HasValue',
|
|
|
|
|
// checking HasValue is redundant here, modern Roslyn versions optimize it and our
|
|
|
|
|
// NullableLifting transform on Comp will already lift the lhs of the logic.and.
|
|
|
|
|
// Treat this case as if the transform had not undone the optimization yet.
|
|
|
|
|
if (nullableVars.Count != 1) |
|
|
|
|
{ |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (comp.Left.MatchLdLoc(nullableVars[0]) || comp.Right.MatchLdLoc(nullableVars[0])) |
|
|
|
|
{ |
|
|
|
|
return comp.MakeLifted(newComparisonKind, comp.Left.Clone(), comp.Right.Clone()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
var (left, right, bits) = DoLiftBinary(comp.Left, comp.Right, comp.LeftExpectedType, comp.RightExpectedType); |
|
|
|
|
// due to the restrictions on side effects, we only allow instructions that are pure after lifting.
|
|
|
|
|
// (we can't check this before lifting due to the calls to GetValueOrDefault())
|
|
|
|
@ -611,7 +633,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
@@ -611,7 +633,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
|
|
|
|
|
// call op_Inequality(call GetValueOrDefault(ldloca nullable1), call GetValueOrDefault(ldloca nullable2))
|
|
|
|
|
// else
|
|
|
|
|
// ldc.i4 0
|
|
|
|
|
|
|
|
|
|
if (hasValueComp.IsLifted) |
|
|
|
|
return null; |
|
|
|
|
if (!MatchHasValueCall(hasValueComp.Left, out ILVariable nullable1)) |
|
|
|
|
return null; |
|
|
|
|
if (!MatchHasValueCall(hasValueComp.Right, out ILVariable nullable2)) |
|
|
|
|