The denouement! Fix #324708
authorRaja R Harinath <harinath@hurrynot.org>
Sat, 5 Apr 2008 20:14:00 +0000 (20:14 -0000)
committerRaja R Harinath <harinath@hurrynot.org>
Sat, 5 Apr 2008 20:14:00 +0000 (20:14 -0000)
* iterators.cs (Iterator.EmitMoveNext): Reset $PC to -1 on entry.
(Iterator.EmitYieldBreak): We no longer need to reset $PC.
* statement.cs (ExceptionStatement.DoEmit): Actually emit the
'finally' inside the finally clause.

svn path=/trunk/mcs/; revision=99929

mcs/mcs/ChangeLog
mcs/mcs/iterators.cs
mcs/mcs/statement.cs
mcs/tests/ChangeLog
mcs/tests/gtest-381.cs [new file with mode: 0644]

index 1a7fa8f316682b55e6d65d08d0b96fc0082f3a7c..8914fbb5cb819399c16e7b4eb5ff0e9e046a35fb 100644 (file)
@@ -1,5 +1,11 @@
 2008-04-06  Raja R Harinath  <harinath@hurrynot.org>
 
+       The denouement!  Fix #324708
+       * iterators.cs (Iterator.EmitMoveNext): Reset $PC to -1 on entry.
+       (Iterator.EmitYieldBreak): We no longer need to reset $PC.
+       * statement.cs (ExceptionStatement.DoEmit): Actually emit the
+       'finally' inside the finally clause.
+
        * statement.cs (ExceptionStatement.DoEmit): Emit try/finally block
        inside an iterator.  Don't emit the body of the 'finally' inside
        the finally clause yet.
index 0d80382049d2d7f4d3fa2ac00ca187445ebe5201..d671e21898027a9d09261d693d073114a1d6f6b3 100644 (file)
@@ -642,9 +642,6 @@ namespace Mono.CSharp {
 
                public void EmitYieldBreak (ILGenerator ig, bool unwind_protect)
                {
-                       ig.Emit (OpCodes.Ldarg_0);
-                       IntConstant.EmitInt (ig, (int) State.After);
-                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
                        ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error);
                }
 
@@ -688,6 +685,11 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
                        ig.Emit (OpCodes.Stloc, current_pc);
 
+                       // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit
+                       ig.Emit (OpCodes.Ldarg_0);
+                       IntConstant.EmitInt (ig, (int) State.After);
+                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
+
                        Label [] labels = new Label [1 + resume_points.Count];
                        labels [0] = ig.DefineLabel ();
 
index cce1d976ffc5ecf8056f057da9f090d5f7d7b5c6..baad333f83c430c567e14699aaaf12d7e7eef531 100644 (file)
@@ -3850,22 +3850,18 @@ namespace Mono.CSharp {
 
                        EmitTryBody (ec);
 
-                       if (emit_finally)
-                               ig.BeginFinallyBlock ();
+                       ig.BeginFinallyBlock ();
 
-                       Label end_finally = ec.ig.DefineLabel ();
+                       Label start_finally = ec.ig.DefineLabel ();
                        if (resume_points != null) {
                                ig.Emit (OpCodes.Ldloc, ec.CurrentIterator.SkipFinally);
-                               ig.Emit (OpCodes.Brtrue, end_finally);
-                               // should be: ig.Emit (OpCodes.Endfinally);
+                               ig.Emit (OpCodes.Brfalse_S, start_finally);
+                               ig.Emit (OpCodes.Endfinally);
                        }
 
+                       ig.MarkLabel (start_finally);
                        EmitFinallyBody (ec);
-                       ig.MarkLabel (end_finally);
 
-                       // yeah, it's empty -- but we'll kill this soon enough
-                       if (!emit_finally)
-                               ig.BeginFinallyBlock ();
                        ig.EndExceptionBlock ();
                }
 
index 4ba579e36035fa43af7756b939a231e83fa90602..d4c31f3621767b2e17942f150f375e6eaa729177 100644 (file)
@@ -1,3 +1,7 @@
+2008-04-06  Raja R Harinath  <harinath@hurrynot.org>
+
+       * gtest-381.cs: New test from #324708.
+
 2008-03-25  Zoltan Varga  <vargaz@gmail.com>
 
        * Makefile (check): Add a standard 'check' target which is the same as run-test.
diff --git a/mcs/tests/gtest-381.cs b/mcs/tests/gtest-381.cs
new file mode 100644 (file)
index 0000000..0a6275d
--- /dev/null
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+
+class TestGoto
+{
+  static int x = 2;
+
+  static void Main(string[] args)
+    {
+      foreach (bool b in test())
+       ;
+      if (x != 0)
+       throw new System.Exception ();
+    }
+
+  static IEnumerable<bool> setX()
+  {
+    x = 1;
+    try {
+      yield return true;
+    } finally {
+      x = 0;
+    }
+  }
+
+  static IEnumerable<bool> test()
+  {
+    foreach (bool b in setX()) {
+      yield return true;
+      // Change "goto label" to "break" to show the correct result.
+      goto label;
+    }
+  label:
+    yield break;
+  }
+}