[mono/mono] [4 commits] e02fd2fd: False user-operator has priority over logical not user-operator

1 view
Skip to first unread message

Marek Safar (marek.safar@gmail.com)

unread,
Nov 10, 2010, 1:00:59 PM11/10/10
to Mono Patches List

Branch: refs/heads/master
Home: https://github.com/mono/mono

Commit: e02fd2fdd6fa5a5d629020c522f08a6b0edfa209
Author: Marek Safar <marek...@gmail.com>
Date: 11/10/2010 12:57:07
URL: https://github.com/mono/mono/commit/e02fd2fdd6fa5a5d629020c522f08a6b0edfa209

False user-operator has priority over logical not user-operator

Changed paths:
M mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpUnaryOperationBinder.cs
M mcs/mcs/ecore.cs
M mcs/mcs/expression.cs
M mcs/tests/dtest-050.cs
M mcs/tests/ver-il-dmcs.xml

Modified: mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpUnaryOperationBinder.cs
===================================================================
--- a/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpUnaryOperationBinder.cs
+++ b/mcs/class/Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpUnaryOperationBinder.cs
@@ -59,7 +59,6 @@ namespace Microsoft.CSharp.RuntimeBinder
case ExpressionType.Negate:
return Compiler.Unary.Operator.UnaryNegation;
case ExpressionType.Not:
- case ExpressionType.IsFalse:
return Compiler.Unary.Operator.LogicalNot;
case ExpressionType.OnesComplement:
return Compiler.Unary.Operator.OnesComplement;
@@ -77,6 +76,8 @@ namespace Microsoft.CSharp.RuntimeBinder

if (Operation == ExpressionType.IsTrue) {
expr = new Compiler.BooleanExpression (expr);
+ } else if (Operation == ExpressionType.IsFalse) {
+ expr = new Compiler.BooleanExpressionFalse (expr);
} else {
if (Operation == ExpressionType.Increment)
expr = new Compiler.UnaryMutator (Compiler.UnaryMutator.Mode.PreIncrement, expr, Compiler.Location.Null);
Modified: mcs/mcs/ecore.cs
===================================================================
--- a/mcs/mcs/ecore.cs
+++ b/mcs/mcs/ecore.cs
@@ -683,7 +683,7 @@ namespace Mono.CSharp {
/// Returns an expression that can be used to invoke operator false
/// on the expression if it exists.
/// </summary>
- static public Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
+ protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
{
return GetOperatorTrueOrFalse (ec, e, false, loc);
}
Modified: mcs/mcs/expression.cs
===================================================================
--- a/mcs/mcs/expression.cs
+++ b/mcs/mcs/expression.cs
@@ -273,7 +273,7 @@ namespace Mono.CSharp {
throw new Exception ("Can not constant fold: " + Oper.ToString());
}

- protected Expression ResolveOperator (ResolveContext ec, Expression expr)
+ protected virtual Expression ResolveOperator (ResolveContext ec, Expression expr)
{
eclass = ExprClass.Value;

@@ -4367,6 +4367,19 @@ namespace Mono.CSharp {
return converted;
}
}
+
+ public class BooleanExpressionFalse : Unary
+ {
+ public BooleanExpressionFalse (Expression expr)
+ : base (Operator.LogicalNot, expr, expr.Location)
+ {
+ }
+
+ protected override Expression ResolveOperator (ResolveContext ec, Expression expr)
+ {
+ return GetOperatorFalse (ec, expr, loc) ?? base.ResolveOperator (ec, expr);
+ }
+ }

/// <summary>
/// Implements the ternary conditional operator (?:)
Modified: mcs/tests/dtest-050.cs
===================================================================
--- a/mcs/tests/dtest-050.cs
+++ b/mcs/tests/dtest-050.cs
@@ -1,5 +1,24 @@
using System;

+
+public struct S
+{
+ public static bool operator true (S s)
+ {
+ throw new ApplicationException ();
+ }
+
+ public static bool operator false (S s)
+ {
+ return true;
+ }
+
+ public static string operator ! (S s)
+ {
+ throw new ApplicationException ();
+ }
+}
+
class C
{
static bool Throw ()
@@ -34,6 +53,10 @@ class C
return 4;
}

+ dynamic a = new S ();
+ dynamic b = new S ();
+ var result = a && b;
+
Console.WriteLine ("ok");
return 0;
}
Modified: mcs/tests/ver-il-dmcs.xml
===================================================================
--- a/mcs/tests/ver-il-dmcs.xml
+++ b/mcs/tests/ver-il-dmcs.xml
@@ -2719,12 +2719,23 @@
<size>2</size>
</method>
<method name="Int32 Main()">
- <size>943</size>
+ <size>1157</size>
</method>
<method name="Void .ctor()">
<size>7</size>
</method>
</type>
+ <type name="S">
+ <method name="Boolean op_True(S)">
+ <size>6</size>
+ </method>
+ <method name="Boolean op_False(S)">
+ <size>2</size>
+ </method>
+ <method name="System.String op_LogicalNot(S)">
+ <size>6</size>
+ </method>
+ </type>
</test>
<test name="dtest-cls-01.cs">
<type name="A">
@@ -43634,6 +43645,22 @@
</method>
</type>
</test>
+ <test name="test-732.cs">
+ <type name="C">
+ <method name="Int32 op_Implicit(C, Boolean)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Main()">
+ <size>22</size>
+ </method>
+ <method name="Int32 op_Explicit(C)">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-733.cs">
<type name="Test">
<method name="Int32 Main()">


Commit: bdf6dee0fac9de8c9032deed0111d6bd238f298b
Author: Marek Safar <marek...@gmail.com>
Date: 11/10/2010 12:57:08
URL: https://github.com/mono/mono/commit/bdf6dee0fac9de8c9032deed0111d6bd238f298b

More tweaks for nullable binary operation

Changed paths:
M mcs/mcs/cfold.cs
M mcs/mcs/expression.cs
M mcs/mcs/field.cs
M mcs/mcs/nullable.cs
M mcs/tests/test-783.cs
M mcs/tests/ver-il-dmcs.xml
M mcs/tests/ver-il-gmcs.xml

Modified: mcs/mcs/cfold.cs
===================================================================
--- a/mcs/mcs/cfold.cs
+++ b/mcs/mcs/cfold.cs
@@ -477,6 +477,11 @@ namespace Mono.CSharp {
return new EnumConstant (result, lt);
}

+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -568,6 +573,11 @@ namespace Mono.CSharp {
return result;

case Binary.Operator.Multiply:
+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -658,6 +668,11 @@ namespace Mono.CSharp {
break;

case Binary.Operator.Division:
+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -752,6 +767,11 @@ namespace Mono.CSharp {
break;

case Binary.Operator.Modulus:
+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -836,6 +856,11 @@ namespace Mono.CSharp {
// There is no overflow checking on left shift
//
case Binary.Operator.LeftShift:
+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
IntConstant ic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
if (ic == null){
Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
@@ -865,6 +890,11 @@ namespace Mono.CSharp {
// There is no overflow checking on right shift
//
case Binary.Operator.RightShift:
+ if (left is NullLiteral && right is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
IntConstant sic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
if (sic == null){
Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
@@ -978,6 +1008,17 @@ namespace Mono.CSharp {
return new BoolConstant (bool_res, left.Location);

case Binary.Operator.LessThan:
+ if (right is NullLiteral) {
+ if (left is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
+ if (left is Nullable.LiftedNull) {
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+ }
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -1006,6 +1047,17 @@ namespace Mono.CSharp {
return new BoolConstant (bool_res, left.Location);

case Binary.Operator.GreaterThan:
+ if (right is NullLiteral) {
+ if (left is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
+ if (left is Nullable.LiftedNull) {
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+ }
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -1034,6 +1086,17 @@ namespace Mono.CSharp {
return new BoolConstant (bool_res, left.Location);

case Binary.Operator.GreaterThanOrEqual:
+ if (right is NullLiteral) {
+ if (left is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
+ if (left is Nullable.LiftedNull) {
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+ }
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

@@ -1062,6 +1125,17 @@ namespace Mono.CSharp {
return new BoolConstant (bool_res, left.Location);

case Binary.Operator.LessThanOrEqual:
+ if (right is NullLiteral) {
+ if (left is NullLiteral) {
+ var lifted_int = new Nullable.NullableType (TypeManager.int32_type, loc).ResolveAsTypeTerminal (ec, false);
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec);
+ }
+
+ if (left is Nullable.LiftedNull) {
+ return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
+ }
+ }
+
if (!DoBinaryNumericPromotions (ec, ref left, ref right))
return null;

Modified: mcs/mcs/expression.cs
===================================================================
--- a/mcs/mcs/expression.cs
+++ b/mcs/mcs/expression.cs
@@ -2814,13 +2814,14 @@ namespace Mono.CSharp {
//
// dynamic && bool => IsFalse (temp = left) ? temp : temp && right;
// dynamic || bool => IsTrue (temp = left) ? temp : temp || right;
- //
+ //
+ left = temp.CreateReferenceExpression (ec, loc);
if (oper == Operator.LogicalAnd) {
expr = DynamicUnaryConversion.CreateIsFalse (cond_args, loc);
- cond_left = temp.CreateReferenceExpression (ec, loc);
+ cond_left = left;
} else {
expr = DynamicUnaryConversion.CreateIsTrue (cond_args, loc);
- cond_left = temp.CreateReferenceExpression (ec, loc);
+ cond_left = left;
}

args.Add (new Argument (left));
@@ -2835,7 +2836,7 @@ namespace Mono.CSharp {

//
// bool && dynamic => (temp = left) ? temp && right : temp;
- // bool || dynamic => (temp = left) ? temp : right || right;
+ // bool || dynamic => (temp = left) ? temp : temp || right;
//
if (oper == Operator.LogicalAnd) {
cond_left = right;
@@ -3074,7 +3075,7 @@ namespace Mono.CSharp {
} else if (lenum) {
underlying_type = EnumSpec.GetUnderlyingType (ltype);
expr = Convert.ImplicitConversion (ec, right, ltype, right.Location);
- if (expr == null) {
+ if (expr == null || expr is EnumConstant) {
expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location);
if (expr == null)
return null;
Modified: mcs/mcs/field.cs
===================================================================
--- a/mcs/mcs/field.cs
+++ b/mcs/mcs/field.cs
@@ -209,7 +209,7 @@ namespace Mono.CSharp
{
if (member_type == InternalType.Dynamic) {
Compiler.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder);
- } else if (member_type.HasDynamicElement) {
+ } else if (!(Parent is CompilerGeneratedClass) && member_type.HasDynamicElement) {
Compiler.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type);
}

Modified: mcs/mcs/nullable.cs
===================================================================
--- a/mcs/mcs/nullable.cs
+++ b/mcs/mcs/nullable.cs
@@ -647,7 +647,7 @@ namespace Mono.CSharp.Nullable
// Arguments can be lifted for equal operators when the return type is bool and both
// arguments are of same type
//
- if (left_orig.IsNull) {
+ if (left_orig is NullLiteral) {
left = right;
state |= State.LeftNullLifted;
type = TypeManager.bool_type;
Modified: mcs/tests/test-783.cs
===================================================================
--- a/mcs/tests/test-783.cs
+++ b/mcs/tests/test-783.cs
@@ -2,15 +2,40 @@ enum E { a, b }

class C
{
- public static void Main ()
+ static void M (E e)
+ {
+ }
+
+ static int Test (int a)
+ {
+ return -1;
+ }
+
+ static int Test (E e)
+ {
+ return 1;
+ }
+
+ public static int Main ()
{
M ((uint) 0);
M ((long) 0);
M ((sbyte) 0);
M ((ulong) 0);
- }
+
+ var d = E.b;
+ if (Test (d - 0) != 1)
+ return 1;
+
+ if (Test (d - 1) != 1)
+ return 2;

- static void M (E e)
- {
+ if (Test (d + 0) != 1)
+ return 3;
+
+ if (Test (d + 1) != 1)
+ return 4;
+
+ return 0;
}
-}
\ No newline at end of file
+}
Modified: mcs/tests/ver-il-dmcs.xml
===================================================================
--- a/mcs/tests/ver-il-dmcs.xml
+++ b/mcs/tests/ver-il-dmcs.xml
@@ -963,7 +963,7 @@
<size>683</size>
</method>
<method name="Void AndAlsoTest()">
- <size>1251</size>
+ <size>1252</size>
</method>
<method name="Void DivideTest()">
<size>927</size>
@@ -1146,7 +1146,7 @@
<size>685</size>
</method>
<method name="Void OrElseTest()">
- <size>1256</size>
+ <size>1257</size>
</method>
<method name="Void RightShiftTest()">
<size>1152</size>
@@ -2192,7 +2192,7 @@
<test name="dtest-029.cs">
<type name="C">
<method name="Boolean Test[T,U](T, U)">
- <size>508</size>
+ <size>423</size>
</method>
<method name="Int32 Main()">
<size>82</size>
@@ -2719,7 +2719,7 @@
<size>2</size>
</method>
<method name="Int32 Main()">
- <size>1157</size>
+ <size>1158</size>
</method>
<method name="Void .ctor()">
<size>7</size>
@@ -16896,6 +16896,16 @@
</method>
</type>
</test>
+ <test name="gtest-548.cs">
+ <type name="C">
+ <method name="Int32 Main()">
+ <size>12</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="gtest-anon-1.cs">
<type name="X">
<method name="Void .ctor()">
@@ -44931,15 +44941,21 @@
</test>
<test name="test-783.cs">
<type name="C">
- <method name="Void Main()">
- <size>25</size>
- </method>
<method name="Void M(E)">
<size>1</size>
</method>
<method name="Void .ctor()">
<size>7</size>
</method>
+ <method name="Int32 Test(Int32)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Test(E)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Main()">
+ <size>88</size>
+ </method>
</type>
</test>
<test name="test-784.cs">
Modified: mcs/tests/ver-il-gmcs.xml
===================================================================
--- a/mcs/tests/ver-il-gmcs.xml
+++ b/mcs/tests/ver-il-gmcs.xml
@@ -40603,6 +40603,22 @@
</method>
</type>
</test>
+ <test name="test-732.cs">
+ <type name="C">
+ <method name="Int32 op_Implicit(C, Boolean)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Main()">
+ <size>22</size>
+ </method>
+ <method name="Int32 op_Explicit(C)">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-733.cs">
<type name="Test">
<method name="Int32 Main()">
@@ -41873,15 +41889,21 @@
</test>
<test name="test-783.cs">
<type name="C">
- <method name="Void Main()">
- <size>25</size>
- </method>
<method name="Void M(E)">
<size>1</size>
</method>
<method name="Void .ctor()">
<size>7</size>
</method>
+ <method name="Int32 Test(Int32)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Test(E)">
+ <size>2</size>
+ </method>
+ <method name="Int32 Main()">
+ <size>88</size>
+ </method>
</type>
</test>
<test name="test-784.cs">


Commit: 55def591e2ff63a16209d7fc27ae5d0aabf31fe3
Author: Marek Safar <marek...@gmail.com>
Date: 11/10/2010 12:57:08
URL: https://github.com/mono/mono/commit/55def591e2ff63a16209d7fc27ae5d0aabf31fe3

Implement dynamic mutator over dynamic indexer

Changed paths:
M mcs/mcs/argument.cs
M mcs/mcs/dynamic.cs
Added paths:
A mcs/tests/dtest-051.cs

Modified: mcs/mcs/argument.cs
===================================================================
--- a/mcs/mcs/argument.cs
+++ b/mcs/mcs/argument.cs
@@ -48,8 +48,14 @@ namespace Mono.CSharp
this.Expr = expr;
}

- public TypeSpec Type {
- get { return Expr.Type; }
+ #region Properties
+
+ public bool IsByRef {
+ get { return ArgType == AType.Ref || ArgType == AType.Out; }
+ }
+
+ public bool IsDefaultArgument {
+ get { return ArgType == AType.Default; }
}

public Parameter.Modifier Modifier {
@@ -67,6 +73,24 @@ namespace Mono.CSharp
}
}

+ public TypeSpec Type {
+ get { return Expr.Type; }
+ }
+
+ #endregion
+
+ public Argument Clone (Expression expr)
+ {
+ Argument a = (Argument) MemberwiseClone ();
+ a.Expr = expr;
+ return a;
+ }
+
+ public Argument Clone (CloneContext clonectx)
+ {
+ return Clone (Expr.Clone (clonectx));
+ }
+
public virtual Expression CreateExpressionTree (ResolveContext ec)
{
if (ArgType == AType.Default)
@@ -83,14 +107,6 @@ namespace Mono.CSharp
return TypeManager.CSharpName (Expr.Type);
}

- public bool IsByRef {
- get { return ArgType == AType.Ref || ArgType == AType.Out; }
- }
-
- public bool IsDefaultArgument {
- get { return ArgType == AType.Default; }
- }
-
public bool ResolveMethodGroup (ResolveContext ec)
{
SimpleName sn = Expr as SimpleName;
@@ -139,13 +155,6 @@ namespace Mono.CSharp
IMemoryLocation ml = (IMemoryLocation) Expr;
ml.AddressOf (ec, mode);
}
-
- public Argument Clone (CloneContext clonectx)
- {
- Argument a = (Argument) MemberwiseClone ();
- a.Expr = Expr.Clone (clonectx);
- return a;
- }
}

public class NamedArgument : Argument
@@ -395,7 +404,7 @@ namespace Mono.CSharp
if (!dup_args)
continue;

- if (a.Expr is Constant) {
+ if (a.Expr is Constant || a.Expr is This) {
//
// No need to create a temporary variable for constants
//
Modified: mcs/mcs/dynamic.cs
===================================================================
--- a/mcs/mcs/dynamic.cs
+++ b/mcs/mcs/dynamic.cs
@@ -562,6 +562,8 @@ namespace Mono.CSharp

class DynamicIndexBinder : DynamicMemberAssignable
{
+ bool can_be_mutator;
+
public DynamicIndexBinder (Arguments args, Location loc)
: base (args, loc)
{
@@ -573,6 +575,12 @@ namespace Mono.CSharp
base.flags = flags;
}

+ protected override Expression DoResolve (ResolveContext ec)
+ {
+ can_be_mutator = true;
+ return base.DoResolve (ec);
+ }
+
protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet)
{
Arguments binder_args = new Arguments (3);
@@ -584,6 +592,38 @@ namespace Mono.CSharp
isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0;
return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args);
}
+
+ protected override Arguments CreateSetterArguments (ResolveContext rc, Expression rhs)
+ {
+ //
+ // Indexer has arguments which complicates things as the setter and getter
+ // are called in two steps when unary mutator is used. We have to make a
+ // copy of all variable arguments to not duplicate any side effect.
+ //
+ // ++d[++arg, Foo ()]
+ //
+
+ if (!can_be_mutator)
+ return base.CreateSetterArguments (rc, rhs);
+
+ var setter_args = new Arguments (Arguments.Count + 1);
+ for (int i = 0; i < Arguments.Count; ++i) {
+ var expr = Arguments[i].Expr;
+
+ if (expr is Constant || expr is VariableReference || expr is This) {
+ setter_args.Add (Arguments [i]);
+ continue;
+ }
+
+ LocalVariable temp = LocalVariable.CreateCompilerGenerated (expr.Type, rc.CurrentBlock, loc);
+ expr = new SimpleAssign (temp.CreateReferenceExpression (rc, expr.Location), expr).Resolve (rc);
+ Arguments[i].Expr = temp.CreateReferenceExpression (rc, expr.Location).Resolve (rc);
+ setter_args.Add (Arguments [i].Clone (expr));
+ }
+
+ setter_args.Add (new Argument (rhs));
+ return setter_args;
+ }
}

class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder
@@ -722,6 +762,14 @@ namespace Mono.CSharp

protected abstract Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet);

+ protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs)
+ {
+ var setter_args = new Arguments (Arguments.Count + 1);
+ setter_args.AddRange (Arguments);
+ setter_args.Add (new Argument (rhs));
+ return setter_args;
+ }
+
public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
{
if (right_side == EmptyExpression.OutAccess.Instance) {
@@ -730,9 +778,7 @@ namespace Mono.CSharp
}

if (DoResolveCore (rc)) {
- setter_args = new Arguments (Arguments.Count + 1);
- setter_args.AddRange (Arguments);
- setter_args.Add (new Argument (right_side));
+ setter_args = CreateSetterArguments (rc, right_side);
setter = CreateCallSiteBinder (rc, setter_args, true);
}

Added: mcs/tests/dtest-051.cs
===================================================================
--- /dev/null
+++ b/mcs/tests/dtest-051.cs
@@ -0,0 +1,31 @@
+using System;
+
+class C
+{
+ int value = 1;
+
+ public int this [int arg] {
+ get { return this.value; }
+ set { this.value = value + arg; }
+ }
+
+ public static int Main ()
+ {
+ C c = new C ();
+ dynamic d = c;
+ int index = 1;
+
+ var x = ++d[++index];
+
+ if (index != 2)
+ return 1;
+
+ if (c.value != 4)
+ return 2;
+
+ if (x != 2)
+ return 3;
+
+ return 0;
+ }
+}

Commit: e152071d2a0061d7aa6d7f40b220b78f43132aa2
Author: Marek Safar <marek...@gmail.com>
Date: 11/10/2010 12:57:08
URL: https://github.com/mono/mono/commit/e152071d2a0061d7aa6d7f40b220b78f43132aa2

New test.

Added paths:
A mcs/errors/gcs0464-3.cs

Added: mcs/errors/gcs0464-3.cs
===================================================================
--- /dev/null
+++ b/mcs/errors/gcs0464-3.cs
@@ -0,0 +1,12 @@
+// CS0464: The result of comparing type `int?' with null is always `false'
+// Line: 9
+// Compiler options: -warnaserror -warn:2
+
+public class X
+{
+ public static bool Compute ()
+ {
+ return null >= null;
+ }
+}
+

Reply all
Reply to author
Forward
0 new messages