[mcs] Complex binary logical expressions flowanalysis
authorMarek Safar <marek.safar@gmail.com>
Tue, 19 Aug 2014 07:34:39 +0000 (09:34 +0200)
committerMarek Safar <marek.safar@gmail.com>
Tue, 19 Aug 2014 07:34:39 +0000 (09:34 +0200)
mcs/errors/cs0165-46.cs [new file with mode: 0644]
mcs/errors/cs0165-47.cs [new file with mode: 0644]
mcs/mcs/expression.cs
mcs/tests/test-904.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/cs0165-46.cs b/mcs/errors/cs0165-46.cs
new file mode 100644 (file)
index 0000000..2ec5014
--- /dev/null
@@ -0,0 +1,21 @@
+// CS0165:
+// Line: 16
+
+class Test
+{
+       public static bool Foo (out int v)
+       {
+               v = 0;
+               return false;
+       }
+
+       static void Main()
+       {
+               int a;
+               bool b = false;
+               if ((b || Foo (out a)) && b)
+                       return;
+               else
+                       System.Console.WriteLine (a);
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0165-47.cs b/mcs/errors/cs0165-47.cs
new file mode 100644 (file)
index 0000000..a4b99b7
--- /dev/null
@@ -0,0 +1,21 @@
+// CS0165:
+// Line: 17
+
+class Test
+{
+       public static bool Foo (out int v)
+       {
+               v = 0;
+               return false;
+       }
+
+       static void Main()
+       {
+               int a;
+               bool b = false;
+
+               if ((b && Foo (out a)) || b) {
+                       System.Console.WriteLine (a);
+               }
+       }
+}
\ No newline at end of file
index 216a3ae1377bcc4c3260f817e1ccfe5350b2bbdd..5285c73e5049900b0ccb3b6ea0fb64d10a802f2c 100644 (file)
@@ -2641,26 +2641,36 @@ namespace Mono.CSharp
                        }
 
                        left.FlowAnalysis (fc);
-                       var left_fc = fc.DefiniteAssignment;
                        var left_fc_ontrue = fc.DefiniteAssignmentOnTrue;
                        var left_fc_onfalse = fc.DefiniteAssignmentOnFalse;
 
                        fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (
                                oper == Operator.LogicalOr ? left_fc_onfalse : left_fc_ontrue);
                        right.FlowAnalysis (fc);
-                       fc.DefiniteAssignment = left_fc;
 
                        if (!set_on_true_false) {
+                               if (oper == Operator.LogicalOr)
+                                       fc.DefiniteAssignment = (left_fc_onfalse | (fc.DefiniteAssignmentOnFalse & fc.DefiniteAssignmentOnTrue)) & left_fc_ontrue;
+                               else
+                                       fc.DefiniteAssignment = (left_fc_ontrue | (fc.DefiniteAssignmentOnFalse & fc.DefiniteAssignmentOnTrue)) & left_fc_onfalse;
+
                                fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignmentOnTrue = null;
                                return;
                        }
 
+                       var lc = left as Constant;
                        if (oper == Operator.LogicalOr) {
-                               fc.DefiniteAssignmentOnTrue = new DefiniteAssignmentBitSet (left_fc_ontrue);
                                fc.DefiniteAssignmentOnFalse = left_fc_onfalse | fc.DefiniteAssignmentOnFalse;
+                               if (lc != null && lc.IsDefaultValue)
+                                       fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse;
+                               else
+                                       fc.DefiniteAssignmentOnTrue = new DefiniteAssignmentBitSet (left_fc_ontrue & (left_fc_onfalse | fc.DefiniteAssignmentOnTrue));
                        } else {
                                fc.DefiniteAssignmentOnTrue = left_fc_ontrue | fc.DefiniteAssignmentOnTrue;
-                               fc.DefiniteAssignmentOnFalse = new DefiniteAssignmentBitSet (left_fc_onfalse);
+                               if (lc != null && !lc.IsDefaultValue)
+                                       fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignmentOnTrue;
+                               else
+                                       fc.DefiniteAssignmentOnFalse = new DefiniteAssignmentBitSet ((left_fc_ontrue | fc.DefiniteAssignmentOnFalse) & left_fc_onfalse);
                        }
                }
 
diff --git a/mcs/tests/test-904.cs b/mcs/tests/test-904.cs
new file mode 100644 (file)
index 0000000..1f9516d
--- /dev/null
@@ -0,0 +1,35 @@
+using System;
+
+class Test
+{
+       public static bool Foo (out int v)
+       {
+               v = 0;
+               return false;
+       }
+
+       static void Main()
+       {
+               bool b = false;
+       
+               int a1;
+               var r1 = (false || Foo (out a1)) ? a1 : 1;
+
+               int a2;
+               var r2 = (true && Foo (out a2)) ? 2 : a2;
+
+               int a3;
+               var r3 = (b || Foo (out a3)) && Foo (out a3);
+               int b3 = a3;
+
+               int a4;
+               var r4 = ((b || Foo (out a4)) && Foo (out a4));
+               int b4 = a4;
+
+               int a5;
+               if ((b || Foo (out a5)) && (b || Foo (out a5)))
+                       Console.WriteLine ();
+               else
+                       Console.WriteLine (a5);
+       }
+}
index f5cd277d06a6c94185b71a5268ac61cc91a09e30..55205a1608f2ada528758b8cdd6047c5a71aaf86 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-904.cs">\r
+    <type name="Test">\r
+      <method name="Boolean Foo(Int32 ByRef)" attrs="150">\r
+        <size>13</size>\r
+      </method>\r
+      <method name="Void Main()" attrs="145">\r
+        <size>172</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-91.cs">\r
     <type name="Abstract">\r
       <method name="Void .ctor()" attrs="6276">\r