Skip to content

Commit

Permalink
[mcs] Fix null coalescing operator on cast of source expression resol…
Browse files Browse the repository at this point in the history
…ved to implicit user operator conversion. Fixes #36161
  • Loading branch information
marek-safar committed Nov 26, 2015
1 parent 8327116 commit f958af3
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
12 changes: 9 additions & 3 deletions mcs/mcs/nullable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@ public class NullCoalescingOperator : Expression
{
Expression left, right;
Unwrap unwrap;
bool user_conversion_left;

public NullCoalescingOperator (Expression left, Expression right)
{
Expand Down Expand Up @@ -1220,6 +1221,7 @@ Expression ConvertExpression (ResolveContext ec)
return ReducedExpression.Create (right, this, false).Resolve (ec);

left = Convert.ImplicitConversion (ec, unwrap ?? left, rtype, loc);
user_conversion_left = left is UserCast;
type = rtype;
return this;
}
Expand Down Expand Up @@ -1283,10 +1285,14 @@ public override void Emit (EmitContext ec)
// Null check is done on original expression not after expression is converted to
// result type. This is in most cases same but when user conversion is involved
// we can end up in situation when user operator does the null handling which is
// not what the operator is supposed to do
// not what the operator is supposed to do.
// There is tricky case where cast of left expression is meant to be cast of
// whole source expression (null check is done on it) and cast from right-to-left
// conversion needs to do null check on unconverted source expression.
//
var op_expr = left as UserCast;
if (op_expr != null) {
if (user_conversion_left) {
var op_expr = (UserCast) left;

op_expr.Source.Emit (ec);
LocalTemporary temp;

Expand Down
20 changes: 20 additions & 0 deletions mcs/tests/test-931.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

class MainClass
{
public static implicit operator string (MainClass src)
{
return null;
}

public static int Main ()
{
var obj = new MainClass ();
var s = "x";
var res = (string) obj ?? s;
if (res != "x")
return 1;

return 0;
}
}
13 changes: 13 additions & 0 deletions mcs/tests/ver-il-net_4_x.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51840,6 +51840,19 @@
</method>
</type>
</test>
<test name="test-931.cs">
<type name="MainClass">
<method name="System.String op_Implicit(MainClass)" attrs="2198">
<size>10</size>
</method>
<method name="Int32 Main()" attrs="150">
<size>60</size>
</method>
<method name="Void .ctor()" attrs="6278">
<size>7</size>
</method>
</type>
</test>
<test name="test-94.cs">
<type name="Base">
<method name="Int32 IVehicle.Start()" attrs="481">
Expand Down

0 comments on commit f958af3

Please sign in to comment.