Resolve conditional expression unreachable expression with unreachable flag set
authorMarek Safar <marek.safar@gmail.com>
Mon, 5 Sep 2011 13:30:06 +0000 (14:30 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 5 Sep 2011 18:02:32 +0000 (19:02 +0100)
mcs/mcs/expression.cs
mcs/mcs/flowanalysis.cs
mcs/tests/test-825.cs
mcs/tests/test-async-13.cs
mcs/tests/ver-il-net_4_0.xml

index 504182ef4ff74ae3967f9324c60b70854be9cc03..dd074c4e498c82917c0c9a89fe4b1501fc3eb15f 100644 (file)
@@ -4478,8 +4478,32 @@ namespace Mono.CSharp
                protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
-                       true_expr = true_expr.Resolve (ec);
-                       false_expr = false_expr.Resolve (ec);
+
+                       //
+                       // Unreachable code needs different resolve path. For instance for await
+                       // expression to not generate unreachable resumable statement
+                       //
+                       Constant c = expr as Constant;
+                       if (c != null && ec.CurrentBranching != null) {
+                               bool unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
+
+                               if (c.IsDefaultValue) {
+                                       ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
+                                       true_expr = true_expr.Resolve (ec);
+                                       ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
+
+                                       false_expr = false_expr.Resolve (ec);
+                               } else {
+                                       true_expr = true_expr.Resolve (ec);
+
+                                       ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
+                                       false_expr = false_expr.Resolve (ec);
+                                       ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
+                               }
+                       } else {
+                               true_expr = true_expr.Resolve (ec);
+                               false_expr = false_expr.Resolve (ec);
+                       }
 
                        if (true_expr == null || false_expr == null || expr == null)
                                return null;
@@ -4519,11 +4543,17 @@ namespace Mono.CSharp
                                }
                        }                       
 
-                       // Dead code optimalization
-                       Constant c = expr as Constant;
-                       if (c != null){
+                       if (c != null) {
                                bool is_false = c.IsDefaultValue;
-                               ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected");
+
+                               //
+                               // Don't issue the warning for constant expressions
+                               //
+                               if (!(is_false ? true_expr is Constant : false_expr is Constant)) {
+                                       ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location,
+                                               "Unreachable expression code detected");
+                               }
+
                                return ReducedExpression.Create (
                                        is_false ? false_expr : true_expr, this,
                                        false_expr is Constant && true_expr is Constant).Resolve (ec);
index 1becb532d4c0159e8395b127f57a95b348427df6..f54f6f1790d7c353e3438c821c7be91677fe4d63 100644 (file)
@@ -251,7 +251,12 @@ namespace Mono.CSharp
                        }
 
                        public bool IsUnreachable {
-                               get { return is_unreachable; }
+                               get {
+                                       return is_unreachable;
+                               }
+                               set {
+                                       is_unreachable = value;
+                               }
                        }
 
                        public void ResetBarrier ()
index 50c587a8a204405858d6a151f48eec18515aa69f..3dda2ede0bebfef358b318165b8e58021617a056 100644 (file)
@@ -1,3 +1,5 @@
+// Compiler options: -warnaserror
+
 using System.Diagnostics;
 
 static class Test
index 264fcb6878b4ed6ab366139d915c261233cca107..303bf8bd9887503eb4ce7da2590b556ceaa8b4eb 100644 (file)
@@ -405,10 +405,7 @@ class Tester : Base
        
        async Task<int> ConditionalTest_1 ()
        {
-               // TODO: problem with Resumable point setup when the expression never emitted
-               //bool b = true;
-               //return true ? await Task.Factory.StartNew (() => 0) : await Task.Factory.StartNew (() => 1);
-               return 0;
+               return true ? await Task.Factory.StartNew (() => 0) : await Task.Factory.StartNew (() => 1);
        }
        
        async Task<int> ConditionalTest_2 ()
index d6da0b3089c9d986d881fc4a1f8c28c781134cd9..f617e20c5fc3a0fa625f4bf5d1424c6ee7adb823 100644 (file)
     </type>
     <type name="Tester+&lt;ConditionalTest_1&gt;c__async19">
       <method name="Void MoveNext()">
-        <size>41</size>
+        <size>201</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>332</size>
       </method>
-      <method name="Int32 &lt;&gt;m__3F()">
-        <size>2</size>
-      </method>
       <method name="Int32 &lt;&gt;m__40()">
         <size>2</size>
       </method>
       <method name="Void MoveNext()">
         <size>352</size>
       </method>
-      <method name="Boolean &lt;&gt;m__41()">
-        <size>2</size>
-      </method>
-      <method name="Int32 &lt;&gt;m__42()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>249</size>
       </method>
-      <method name="Int32 &lt;&gt;m__43()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>277</size>
       </method>
-      <method name="Int32 &lt;&gt;m__44(Int32)">
-        <size>4</size>
-      </method>
-      <method name="Int32 &lt;&gt;m__45()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>221</size>
       </method>
-      <method name="System.Action &lt;&gt;m__46()">
-        <size>15</size>
-      </method>
-      <method name="Void &lt;&gt;m__47()">
-        <size>8</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>540</size>
       </method>
-      <method name="Int32 &lt;&gt;m__48()">
-        <size>2</size>
-      </method>
       <method name="Int32 &lt;&gt;m__49()">
         <size>2</size>
       </method>
       <method name="Void MoveNext()">
         <size>229</size>
       </method>
-      <method name="Int32 &lt;&gt;m__4A()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>338</size>
       </method>
-      <method name="Int32 &lt;&gt;m__4B()">
-        <size>2</size>
-      </method>
       <method name="Int32 &lt;&gt;m__4C()">
         <size>2</size>
       </method>
       <method name="Void MoveNext()">
         <size>369</size>
       </method>
-      <method name="Int32 &lt;&gt;m__4D()">
-        <size>18</size>
-      </method>
       <method name="Int32 &lt;&gt;m__4E()">
-        <size>2</size>
+        <size>18</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>397</size>
       </method>
-      <method name="Int32 &lt;&gt;m__4F()">
-        <size>18</size>
-      </method>
       <method name="Int32 &lt;&gt;m__50()">
-        <size>3</size>
+        <size>18</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>501</size>
       </method>
-      <method name="Int32 &lt;&gt;m__51()">
-        <size>18</size>
-      </method>
       <method name="Int32 &lt;&gt;m__52()">
-        <size>3</size>
+        <size>18</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>548</size>
       </method>
-      <method name="Int32 &lt;&gt;m__53()">
-        <size>3</size>
-      </method>
       <method name="Int32 &lt;&gt;m__54()">
-        <size>2</size>
+        <size>3</size>
       </method>
       <method name="Int32 &lt;&gt;m__55()">
-        <size>3</size>
+        <size>2</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>263</size>
       </method>
-      <method name="Int32 &lt;&gt;m__56()">
-        <size>18</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>246</size>
       </method>
-      <method name="Tester &lt;&gt;m__57()">
-        <size>6</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>239</size>
       </method>
-      <method name="Nullable`1 &lt;&gt;m__58()">
-        <size>7</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>389</size>
       </method>
-      <method name="Base &lt;&gt;m__59()">
-        <size>6</size>
-      </method>
       <method name="Base &lt;&gt;m__5A()">
         <size>6</size>
       </method>
       <method name="Void MoveNext()">
         <size>298</size>
       </method>
-      <method name="Base &lt;&gt;m__5B()">
-        <size>6</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>388</size>
       </method>
-      <method name="Base &lt;&gt;m__5C()">
-        <size>6</size>
-      </method>
       <method name="Base &lt;&gt;m__5D()">
         <size>6</size>
       </method>
       <method name="Void MoveNext()">
         <size>259</size>
       </method>
-      <method name="Int32 &lt;&gt;m__5E()">
-        <size>3</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>353</size>
       </method>
-      <method name="Int32 &lt;&gt;m__5F()">
-        <size>3</size>
-      </method>
-      <method name="System.String &lt;&gt;m__60()">
-        <size>6</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>1006</size>
       </method>
-      <method name="Int32 &lt;&gt;m__61()">
-        <size>3</size>
-      </method>
       <method name="Int32 &lt;&gt;m__62()">
         <size>3</size>
       </method>
       <method name="Void MoveNext()">
         <size>742</size>
       </method>
-      <method name="System.String &lt;&gt;m__67()">
-        <size>6</size>
-      </method>
       <method name="System.String &lt;&gt;m__68()">
         <size>6</size>
       </method>
-      <method name="Int32 &lt;&gt;m__69()">
-        <size>3</size>
-      </method>
       <method name="Int32 &lt;&gt;m__6A()">
         <size>3</size>
       </method>
       <method name="Void MoveNext()">
         <size>239</size>
       </method>
-      <method name="Int32 &lt;&gt;m__6B()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>353</size>
       </method>
-      <method name="Int32 &lt;&gt;m__6C()">
-        <size>2</size>
-      </method>
       <method name="Int32 &lt;&gt;m__6D()">
         <size>2</size>
       </method>
       <method name="Void MoveNext()">
         <size>259</size>
       </method>
-      <method name="Byte &lt;&gt;m__6E()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>439</size>
       </method>
-      <method name="UInt16 &lt;&gt;m__6F()">
-        <size>2</size>
-      </method>
       <method name="UInt16 &lt;&gt;m__70()">
         <size>2</size>
       </method>
       <method name="Void MoveNext()">
         <size>277</size>
       </method>
-      <method name="S &lt;&gt;m__71()">
-        <size>18</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>279</size>
       </method>
-      <method name="Int32 &lt;&gt;m__72()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>226</size>
       </method>
-      <method name="Int32 &lt;&gt;m__73()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>294</size>
       </method>
-      <method name="Int32 &lt;&gt;m__74()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>642</size>
       </method>
-      <method name="Int32 &lt;&gt;m__75()">
-        <size>3</size>
-      </method>
       <method name="Int32 &lt;&gt;m__76()">
-        <size>2</size>
+        <size>3</size>
       </method>
       <method name="Int32 &lt;&gt;m__77()">
         <size>2</size>
       <method name="Void MoveNext()">
         <size>452</size>
       </method>
-      <method name="System.String &lt;&gt;m__78()">
-        <size>6</size>
-      </method>
       <method name="System.String &lt;&gt;m__79()">
         <size>6</size>
       </method>
       <method name="System.String &lt;&gt;m__7A()">
-        <size>2</size>
+        <size>6</size>
       </method>
       <method name="Void .ctor()">
         <size>36</size>
       <method name="Void MoveNext()">
         <size>239</size>
       </method>
-      <method name="Int32 &lt;&gt;m__7B()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>339</size>
       </method>
-      <method name="Nullable`1 &lt;&gt;m__7C()">
-        <size>7</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>375</size>
       </method>
-      <method name="Int32 &lt;&gt;m__7D()">
-        <size>2</size>
-      </method>
       <method name="Void .ctor()">
         <size>36</size>
       </method>
       <method name="Void MoveNext()">
         <size>351</size>
       </method>
-      <method name="Int32 &lt;&gt;m__7E()">
-        <size>2</size>
-      </method>
       <method name="Int32 &lt;&gt;m__7F()">
         <size>2</size>
       </method>
         <size>36</size>
       </method>
     </type>
+    <type name="Tester+&lt;ConditionalTest_1&gt;c__async19">
+      <method name="Int32 &lt;&gt;m__3F()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;ConditionalTest_2&gt;c__async1A">
+      <method name="Int32 &lt;&gt;m__41()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;ConditionalTest_3&gt;c__async1B">
+      <method name="Boolean &lt;&gt;m__42()">
+        <size>2</size>
+      </method>
+      <method name="Int32 &lt;&gt;m__43()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;ConditionalTest_4&gt;c__async1C">
+      <method name="Int32 &lt;&gt;m__44()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;DelegateInvoke_4&gt;c__async1D">
+      <method name="Int32 &lt;&gt;m__45(Int32)">
+        <size>4</size>
+      </method>
+      <method name="Int32 &lt;&gt;m__46()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;EventInvoke_1&gt;c__async1E">
+      <method name="System.Action &lt;&gt;m__47()">
+        <size>15</size>
+      </method>
+      <method name="Void &lt;&gt;m__48()">
+        <size>8</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;FieldTest_1&gt;c__async1F">
+      <method name="Int32 &lt;&gt;m__4A()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_1&gt;c__async20">
+      <method name="Int32 &lt;&gt;m__4B()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_2&gt;c__async21">
+      <method name="Int32 &lt;&gt;m__4D()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_3&gt;c__async22">
+      <method name="Int32 &lt;&gt;m__4F()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_4&gt;c__async23">
+      <method name="Int32 &lt;&gt;m__51()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_5&gt;c__async24">
+      <method name="Int32 &lt;&gt;m__53()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_6&gt;c__async25">
+      <method name="Int32 &lt;&gt;m__56()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IndexerTest_7&gt;c__async26">
+      <method name="Int32 &lt;&gt;m__57()">
+        <size>18</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IsTest_1&gt;c__async27">
+      <method name="Tester &lt;&gt;m__58()">
+        <size>6</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;IsTest_2&gt;c__async28">
+      <method name="Nullable`1 &lt;&gt;m__59()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;LogicalUserOperator_1&gt;c__async29">
+      <method name="Base &lt;&gt;m__5B()">
+        <size>6</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;LogicalUserOperator_2&gt;c__async2A">
+      <method name="Base &lt;&gt;m__5C()">
+        <size>6</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;LogicalUserOperator_3&gt;c__async2B">
+      <method name="Base &lt;&gt;m__5E()">
+        <size>6</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewTest_1&gt;c__async2C">
+      <method name="Int32 &lt;&gt;m__5F()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewTest_2&gt;c__async2D">
+      <method name="Int32 &lt;&gt;m__60()">
+        <size>3</size>
+      </method>
+      <method name="System.String &lt;&gt;m__61()">
+        <size>6</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewInitTest_1&gt;c__async2E">
+      <method name="Int32 &lt;&gt;m__67()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewInitTest_2&gt;c__async2F">
+      <method name="System.String &lt;&gt;m__69()">
+        <size>6</size>
+      </method>
+      <method name="Int32 &lt;&gt;m__6B()">
+        <size>3</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_1&gt;c__async30">
+      <method name="Int32 &lt;&gt;m__6C()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_2&gt;c__async31">
+      <method name="Int32 &lt;&gt;m__6E()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_3&gt;c__async32">
+      <method name="Byte &lt;&gt;m__6F()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_4&gt;c__async33">
+      <method name="UInt16 &lt;&gt;m__71()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_5&gt;c__async34">
+      <method name="S &lt;&gt;m__72()">
+        <size>18</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;NewArrayInitTest_6&gt;c__async35">
+      <method name="Int32 &lt;&gt;m__73()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;PropertyTest_1&gt;c__async36">
+      <method name="Int32 &lt;&gt;m__74()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;PropertyTest_2&gt;c__async37">
+      <method name="Int32 &lt;&gt;m__75()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;PropertyTest_3&gt;c__async38">
+      <method name="Int32 &lt;&gt;m__78()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;StringConcatTest_1&gt;c__async39">
+      <method name="System.String &lt;&gt;m__7B()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;UnaryTest_1&gt;c__async3A">
+      <method name="Int32 &lt;&gt;m__7C()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;UnaryTest_2&gt;c__async3B">
+      <method name="Nullable`1 &lt;&gt;m__7D()">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;UnaryTest_3&gt;c__async3C">
+      <method name="Int32 &lt;&gt;m__7E()">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;VariableInitializer_1&gt;c__async3D">
+      <method name="Int32 &lt;&gt;m__80()">
+        <size>2</size>
+      </method>
+    </type>
   </test>
   <test name="test-async-14.cs">
     <type name="C">