Browse Source

Fix #217: cast both sides of reference comparison to object if necessary

pull/728/merge
Daniel Grunwald 9 years ago
parent
commit
64bd447db4
  1. 16
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 6
      ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs
  3. 22
      ICSharpCode.Decompiler/Tests/TestCases/Correctness/Comparisons.cs
  4. 11
      ICSharpCode.Decompiler/Tests/TestCases/Correctness/OverloadResolution.cs

16
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -417,6 +417,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -417,6 +417,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary>
TranslatedExpression TranslateCeq(Comp inst, out bool negateOutput)
{
Debug.Assert(inst.Kind.IsEqualityOrInequality());
// Translate '(e as T) == null' to '!(e is T)'.
// This is necessary for correctness when T is a value type.
if (inst.Left.OpCode == OpCode.IsInst && inst.Right.OpCode == OpCode.LdNull) {
@ -475,9 +476,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -475,9 +476,18 @@ namespace ICSharpCode.Decompiler.CSharp
} else {
left = left.ConvertTo(targetType, this);
}
rr = new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(BinaryOperatorType.Equality, false),
left.ResolveResult, right.ResolveResult);
rr = resolver.ResolveBinaryOperator(inst.Kind.ToBinaryOperatorType(),
left.ResolveResult, right.ResolveResult) as OperatorResolveResult;
if (rr == null || rr.IsError || rr.UserDefinedOperatorMethod != null
|| rr.Operands[0].Type.GetStackType() != inst.InputType)
{
// If converting one input wasn't sufficient, convert both:
left = left.ConvertTo(targetType, this);
right = right.ConvertTo(targetType, this);
rr = new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean),
BinaryOperatorExpression.GetLinqNodeType(BinaryOperatorType.Equality, false),
left.ResolveResult, right.ResolveResult);
}
}
negateOutput = false;
return new BinaryOperatorExpression(left.Expression, inst.Kind.ToBinaryOperatorType(), right.Expression)

6
ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs

@ -97,6 +97,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -97,6 +97,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(cscOptions: cscOptions);
}
[Test]
public void TypeInference([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}
[Test, Ignore("Not implemented")]
public void YieldReturn([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{

22
ICSharpCode.Decompiler/Tests/TestCases/Correctness/Comparisons.cs

@ -45,6 +45,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases @@ -45,6 +45,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases
Console.WriteLine(IsNotNull(new OverloadedOperators()));
Console.WriteLine(IsNull(new OverloadedOperators()));
Console.WriteLine(NullIs(new OverloadedOperators()));
Console.WriteLine(NullIsNot(new OverloadedOperators()));
return 0;
}
@ -88,6 +90,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases @@ -88,6 +90,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases
{
return (object)oo != null;
}
static bool NullIs(OverloadedOperators oo)
{
return null == (object)oo;
}
static bool NullIsNot(OverloadedOperators oo)
{
return null != (object)oo;
}
}
#pragma warning disable CS0660 // Type defines operator == or operator != but does not override Object.Equals(object o)
@ -103,5 +115,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases @@ -103,5 +115,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases
{
throw new NotSupportedException("Not supported to call the user-defined operator");
}
public static bool operator ==(object oo, OverloadedOperators b)
{
throw new NotSupportedException("Not supported to call the user-defined operator");
}
public static bool operator !=(object oo, OverloadedOperators b)
{
throw new NotSupportedException("Not supported to call the user-defined operator");
}
}
}

11
ICSharpCode.Decompiler/Tests/TestCases/Correctness/OverloadResolution.cs

@ -47,5 +47,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness @@ -47,5 +47,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
{
Console.WriteLine("#180: params object[]");
}
static void CallExtensionMethod()
{
new object().ExtensionMethod();
ExtensionMethod(null); // issue #167
}
public static void ExtensionMethod(this object obj)
{
Console.WriteLine("ExtensionMethod(obj)");
}
}
}

Loading…
Cancel
Save