Author: raja
Date: 2006-05-25 07:16:31 -0400 (Thu, 25 May 2006)
New Revision: 61104

Modified:
   trunk/mcs/gmcs/ChangeLog
   trunk/mcs/gmcs/expression.cs
   trunk/mcs/gmcs/generic.cs
   trunk/mcs/tests/ChangeLog
   trunk/mcs/tests/gtest-211.cs
Log:
In gmcs:
        Fix #78324
        * expression.cs (Binary.DoResolve): Use Nullable.LiftedBinaryOperator
        also when one of the operands is a null literal.
        * generic.cs (Nullable.LiftedBinaryOperator.EmitEquality): Rewrite
        to improve clarity, and generate slightly better code.

In tests:
        * gtest-211.cs: Add a couple more tests for better coverage.


Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog    2006-05-25 11:07:39 UTC (rev 61103)
+++ trunk/mcs/gmcs/ChangeLog    2006-05-25 11:16:31 UTC (rev 61104)
@@ -1,3 +1,11 @@
+2006-05-25  Raja R Harinath  <[EMAIL PROTECTED]>
+
+       Fix #78324
+       * expression.cs (Binary.DoResolve): Use Nullable.LiftedBinaryOperator
+       also when one of the operands is a null literal.
+       * generic.cs (Nullable.LiftedBinaryOperator.EmitEquality): Rewrite
+       to improve clarity, and generate slightly better code.
+
 2006-05-24  Raja R Harinath  <[EMAIL PROTECTED]>
 
        * flowanalysis.cs (FlowBranchingToplevel.AddReturnOrigin): Move

Modified: trunk/mcs/gmcs/expression.cs
===================================================================
--- trunk/mcs/gmcs/expression.cs        2006-05-25 11:07:39 UTC (rev 61103)
+++ trunk/mcs/gmcs/expression.cs        2006-05-25 11:16:31 UTC (rev 61104)
@@ -2464,7 +2464,9 @@
                        }
 
                        Type ltype = left.Type, rtype = right.Type;
-                       if (ltype.IsValueType && rtype.IsValueType &&
+                       if ((left is NullLiteral || ltype.IsValueType) &&
+                           (right is NullLiteral || rtype.IsValueType) &&
+                           !(left is NullLiteral && right is NullLiteral) &&
                            (TypeManager.IsNullableType (ltype) || 
TypeManager.IsNullableType (rtype)))
                                return new Nullable.LiftedBinaryOperator (oper, 
left, right, loc).Resolve (ec);
 

Modified: trunk/mcs/gmcs/generic.cs
===================================================================
--- trunk/mcs/gmcs/generic.cs   2006-05-25 11:07:39 UTC (rev 61103)
+++ trunk/mcs/gmcs/generic.cs   2006-05-25 11:16:31 UTC (rev 61104)
@@ -3150,96 +3150,72 @@
                        {
                                ILGenerator ig = ec.ig;
 
-                               Label left_not_null_label = ig.DefineLabel ();
-                               Label false_label = ig.DefineLabel ();
-                               Label true_label = ig.DefineLabel ();
-                               Label end_label = ig.DefineLabel ();
+                               // Given 'X? x;' for any value type X: 'x != 
null' is the same as 'x.HasValue'
+                               if (left is NullLiteral) {
+                                       if (right_unwrap == null)
+                                               throw new 
InternalErrorException ();
+                                       right_unwrap.EmitCheck (ec);
+                                       if (Oper == Binary.Operator.Equality) {
+                                               ig.Emit (OpCodes.Ldc_I4_0);
+                                               ig.Emit (OpCodes.Ceq);
+                                       }
+                                       return;
+                               }
 
-                               bool false_label_used = false;
-                               bool true_label_used = false;
-
-                               if (left_unwrap != null) {
+                               if (right is NullLiteral) {
+                                       if (left_unwrap == null)
+                                               throw new 
InternalErrorException ();
                                        left_unwrap.EmitCheck (ec);
-                                       if (right is NullLiteral) {
-                                               if (Oper == 
Binary.Operator.Equality) {
-                                                       true_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, true_label);
-                                               } else {
-                                                       false_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, false_label);
-                                               }
-                                       } else if (right_unwrap != null) {
-                                               ig.Emit (OpCodes.Dup);
-                                               ig.Emit (OpCodes.Brtrue, 
left_not_null_label);
-                                               right_unwrap.EmitCheck (ec);
+                                       if (Oper == Binary.Operator.Equality) {
+                                               ig.Emit (OpCodes.Ldc_I4_0);
                                                ig.Emit (OpCodes.Ceq);
-                                               if (Oper == 
Binary.Operator.Inequality) {
-                                                       ig.Emit 
(OpCodes.Ldc_I4_0);
-                                                       ig.Emit (OpCodes.Ceq);
-                                               }
-                                               ig.Emit (OpCodes.Br, end_label);
-
-                                               ig.MarkLabel 
(left_not_null_label);
-                                               ig.Emit (OpCodes.Pop);
-                                       } else {
-                                               if (Oper == 
Binary.Operator.Equality) {
-                                                       false_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, false_label);
-                                               } else {
-                                                       true_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, true_label);
-                                               }
                                        }
+                                       return;
                                }
 
-                               if (right_unwrap != null) {
+                               Label both_have_value_label = ig.DefineLabel ();
+                               Label end_label = ig.DefineLabel ();
+
+                               if (left_unwrap != null && right_unwrap != 
null) {
+                                       Label dissimilar_label = ig.DefineLabel 
();
+
+                                       left_unwrap.EmitCheck (ec);
+                                       ig.Emit (OpCodes.Dup);
                                        right_unwrap.EmitCheck (ec);
-                                       if (left is NullLiteral) {
-                                               if (Oper == 
Binary.Operator.Equality) {
-                                                       true_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, true_label);
-                                               } else {
-                                                       false_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, false_label);
-                                               }
-                                       } else {
-                                               if (Oper == 
Binary.Operator.Equality) {
-                                                       false_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, false_label);
-                                               } else {
-                                                       true_label_used = true;
-                                                       ig.Emit 
(OpCodes.Brfalse, true_label);
-                                               }
-                                       }
-                               }
+                                       ig.Emit (OpCodes.Ceq);
+                                       ig.Emit (OpCodes.Brfalse, 
dissimilar_label);
 
-                               bool left_is_null = left is NullLiteral;
-                               bool right_is_null = right is NullLiteral;
-                               if (left_is_null || right_is_null) {
-                                       if (((Oper == Binary.Operator.Equality) 
&& (left_is_null == right_is_null)) ||
-                                           ((Oper == 
Binary.Operator.Inequality) && (left_is_null != right_is_null))) {
-                                               true_label_used = true;
-                                               ig.Emit (OpCodes.Br, 
true_label);
-                                       } else {
-                                               false_label_used = true;
-                                               ig.Emit (OpCodes.Br, 
false_label);
-                                       }
-                               } else {
-                                       underlying.Emit (ec);
+                                       ig.Emit (OpCodes.Brtrue, 
both_have_value_label);
+
+                                       // both are null
+                                       if (Oper == Binary.Operator.Equality)
+                                               ig.Emit (OpCodes.Ldc_I4_1);
+                                       else
+                                               ig.Emit (OpCodes.Ldc_I4_0);
                                        ig.Emit (OpCodes.Br, end_label);
-                               }
 
-                               ig.MarkLabel (false_label);
-                               if (false_label_used) {
-                                       ig.Emit (OpCodes.Ldc_I4_0);
-                                       if (true_label_used)
-                                               ig.Emit (OpCodes.Br, end_label);
+                                       ig.MarkLabel (dissimilar_label);
+                                       ig.Emit (OpCodes.Pop);
+                               } else if (left_unwrap != null) {
+                                       left_unwrap.EmitCheck (ec);
+                                       ig.Emit (OpCodes.Brtrue, 
both_have_value_label);
+                               } else if (right_unwrap != null) {
+                                       right_unwrap.EmitCheck (ec);
+                                       ig.Emit (OpCodes.Brtrue, 
both_have_value_label);
+                               } else {
+                                       throw new InternalErrorException 
("shouldn't get here");
                                }
 
-                               ig.MarkLabel (true_label);
-                               if (true_label_used)
+                               // one is null while the other isn't
+                               if (Oper == Binary.Operator.Equality)
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                               else
                                        ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Br, end_label);
 
+                               ig.MarkLabel (both_have_value_label);
+                               underlying.Emit (ec);
+
                                ig.MarkLabel (end_label);
                        }
 

Modified: trunk/mcs/tests/ChangeLog
===================================================================
--- trunk/mcs/tests/ChangeLog   2006-05-25 11:07:39 UTC (rev 61103)
+++ trunk/mcs/tests/ChangeLog   2006-05-25 11:16:31 UTC (rev 61104)
@@ -1,3 +1,7 @@
+2006-05-25  Raja R Harinath  <[EMAIL PROTECTED]>
+
+       * gtest-211.cs: Add a couple more tests for better coverage.
+
 2006-05-23  Raja R Harinath  <[EMAIL PROTECTED]>
 
        * test-519.cs: New test for compiler crash.

Modified: trunk/mcs/tests/gtest-211.cs
===================================================================
--- trunk/mcs/tests/gtest-211.cs        2006-05-25 11:07:39 UTC (rev 61103)
+++ trunk/mcs/tests/gtest-211.cs        2006-05-25 11:16:31 UTC (rev 61104)
@@ -6,17 +6,24 @@
        }
        public static void Main()
        {
+               int? w = null;
                int? x = null;
                int? y = 0;
+               int? z = 1;
+
                f (false, x == 0);
                f (true,  x != 0);
                f (false, x == y);
                f (true,  x != y);
+               f (true,  x == w);
+               f (false, x != w);
                f (true,  x == null);
                f (false, x != null);
 
                f (true,  0 == y);
                f (false, 0 != y);
+               f (false, z == y);
+               f (true,  z != y);
                f (false, null == y);
                f (true,  null != y);
        }

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to