* 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
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.
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);
}
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 ();
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 ();
}
+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.
--- /dev/null
+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;
+ }
+}