Emit iterators finally block only once. Fixes #4052.
authorMarek Safar <marek.safar@gmail.com>
Mon, 26 Mar 2012 16:30:03 +0000 (17:30 +0100)
committerMarek Safar <marek.safar@gmail.com>
Tue, 27 Mar 2012 08:36:38 +0000 (09:36 +0100)
mcs/errors/cs0219-6.cs [new file with mode: 0644]
mcs/mcs/iterators.cs
mcs/mcs/statement.cs
mcs/tests/gtest-iter-21.cs [new file with mode: 0644]
mcs/tests/test-debug-21-ref.xml [new file with mode: 0644]
mcs/tests/test-debug-21.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/cs0219-6.cs b/mcs/errors/cs0219-6.cs
new file mode 100644 (file)
index 0000000..a5246cd
--- /dev/null
@@ -0,0 +1,17 @@
+// CS0219: The variable `i' is assigned but its value is never used
+// Line: 14
+// Compiler options: -warn:3 -warnaserror
+
+using System.Collections.Generic;
+
+class C
+{
+       IEnumerable<int> Test ()
+       {
+               try {
+                       yield return 1;
+               } finally {
+                       int i = 100;
+               }
+       }
+}
\ No newline at end of file
index a906103eec76d87eb79bf87b691a1c5be8e4fbf5..705599f8d1796c4b5ba5176669f50cd8988d93e8 100644 (file)
@@ -903,13 +903,43 @@ namespace Mono.CSharp
        }
 
        //
-       // Iterators are implemented as hidden anonymous block
+       // Iterators are implemented as state machine blocks
        //
        public class Iterator : StateMachineInitializer
        {
+               sealed class TryFinallyBlockProxyStatement : Statement
+               {
+                       TryFinallyBlock block;
+                       Iterator iterator;
+
+                       public TryFinallyBlockProxyStatement (Iterator iterator, TryFinallyBlock block)
+                       {
+                               this.iterator = iterator;
+                               this.block = block;
+                       }
+
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
+                       {
+                               throw new NotSupportedException ();
+                       }
+
+                       protected override void DoEmit (EmitContext ec)
+                       {
+                               //
+                               // Restore redirection for any captured variables
+                               //
+                               ec.CurrentAnonymousMethod = iterator;
+
+                               using (ec.With (BuilderContext.Options.OmitDebugInfo, false)) {
+                                       block.EmitFinallyBody (ec);
+                               }
+                       }
+               }
+
                public readonly IMethodData OriginalMethod;
                public readonly bool IsEnumerable;
                public readonly TypeSpec OriginalIteratorType;
+               int finally_hosts_counter;
 
                public Iterator (ParametersBlock block, IMethodData method, TypeDefinition host, TypeSpec iterator_type, bool is_enumerable)
                        : base (block, host, host.Compiler.BuiltinTypes.Bool)
@@ -920,6 +950,8 @@ namespace Mono.CSharp
                        this.type = method.ReturnType;
                }
 
+               #region Properties
+
                public ToplevelBlock Container {
                        get { return OriginalMethod.Block; }
                }
@@ -932,6 +964,22 @@ namespace Mono.CSharp
                        get { return true; }
                }
 
+               #endregion
+
+               public Method CreateFinallyHost (TryFinallyBlock block)
+               {
+                       var method = new Method (storey, new TypeExpression (storey.Compiler.BuiltinTypes.Void, loc),
+                               Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, null, "Finally", finally_hosts_counter++), loc),
+                               ParametersCompiled.EmptyReadOnlyParameters, null);
+
+                       method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc);
+                       method.Block.IsCompilerGenerated = true;
+                       method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
+
+                       storey.AddMember (method);
+                       return method;
+               }
+
                public void EmitYieldBreak (EmitContext ec, bool unwind_protect)
                {
                        ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error);
index f189c2fc40194c07708396a244e762b6a1bba764..cb1da27d81feeb5330a5fcd87999fd30db8392e6 100644 (file)
@@ -4420,6 +4420,7 @@ namespace Mono.CSharp {
                protected Statement stmt;
                Label dispose_try_block;
                bool prepared_for_dispose, emitted_dispose;
+               Method finally_host;
 
                protected TryFinallyBlock (Statement stmt, Location loc)
                        : base (loc)
@@ -4438,7 +4439,7 @@ namespace Mono.CSharp {
                #endregion
 
                protected abstract void EmitTryBody (EmitContext ec);
-               protected abstract void EmitFinallyBody (EmitContext ec);
+               public abstract void EmitFinallyBody (EmitContext ec);
 
                public override Label PrepareForDispose (EmitContext ec, Label end)
                {
@@ -4466,7 +4467,14 @@ namespace Mono.CSharp {
                        }
 
                        ec.MarkLabel (start_finally);
-                       EmitFinallyBody (ec);
+
+                       if (finally_host != null) {
+                               var ce = new CallEmitter ();
+                               ce.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
+                               ce.EmitPredefined (ec, finally_host.Spec, new Arguments (0));
+                       } else {
+                               EmitFinallyBody (ec);
+                       }
 
                        ec.EndExceptionBlock ();
                }
@@ -4510,12 +4518,10 @@ namespace Mono.CSharp {
                                bool emit_dispatcher = j < labels.Length;
 
                                if (emit_dispatcher) {
-                                       //SymbolWriter.StartIteratorDispatcher (ec.ig);
                                        ec.Emit (OpCodes.Ldloc, pc);
                                        ec.EmitInt (first_resume_pc);
                                        ec.Emit (OpCodes.Sub);
                                        ec.Emit (OpCodes.Switch, labels);
-                                       //SymbolWriter.EndIteratorDispatcher (ec.ig);
                                }
 
                                foreach (ResumableStatement s in resume_points)
@@ -4526,10 +4532,32 @@ namespace Mono.CSharp {
 
                        ec.BeginFinallyBlock ();
 
-                       EmitFinallyBody (ec);
+                       if (finally_host != null) {
+                               var ce = new CallEmitter ();
+                               ce.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
+                               ce.EmitPredefined (ec, finally_host.Spec, new Arguments (0));
+                       } else {
+                               EmitFinallyBody (ec);
+                       }
 
                        ec.EndExceptionBlock ();
                }
+
+               public override bool Resolve (BlockContext bc)
+               {
+                       //
+                       // Finally block inside iterator is called from MoveNext and
+                       // Dispose methods that means we need to lift the block into
+                       // newly created host method to emit the body only once. The
+                       // original block then simply calls the newly generated method.
+                       //
+                       if (bc.CurrentIterator != null && !bc.IsInProbingMode) {
+                               var iterator = bc.CurrentIterator;
+                               finally_host = iterator.CreateFinallyHost (this);
+                       }
+
+                       return base.Resolve (bc);
+               }
        }
 
        //
@@ -4718,7 +4746,7 @@ namespace Mono.CSharp {
                        Statement.Emit (ec);
                }
 
-               protected override void EmitFinallyBody (EmitContext ec)
+               public override void EmitFinallyBody (EmitContext ec)
                {
                        //
                        // if (lock_taken) Monitor.Exit (expr_copy)
@@ -5312,6 +5340,7 @@ namespace Mono.CSharp {
 
                        if (ok)
                                ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally);
+
                        using (ec.With (ResolveContext.Options.FinallyScope, true)) {
                                if (!fini.Resolve (ec))
                                        ok = false;
@@ -5329,7 +5358,7 @@ namespace Mono.CSharp {
                        stmt.Emit (ec);
                }
 
-               protected override void EmitFinallyBody (EmitContext ec)
+               public override void EmitFinallyBody (EmitContext ec)
                {
                        fini.Emit (ec);
                }
@@ -5673,7 +5702,7 @@ namespace Mono.CSharp {
                        stmt.Emit (ec);
                }
 
-               protected override void EmitFinallyBody (EmitContext ec)
+               public override void EmitFinallyBody (EmitContext ec)
                {
                        decl.EmitDispose (ec);
                }
diff --git a/mcs/tests/gtest-iter-21.cs b/mcs/tests/gtest-iter-21.cs
new file mode 100644 (file)
index 0000000..5265dd4
--- /dev/null
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+
+class C
+{
+       IEnumerable<int> Test ()
+       {
+               Console.WriteLine ("init");
+               try {
+                       yield return 1;
+               } finally {
+                       int oo = 4;
+                       Action a = () => Console.WriteLine (oo);
+               }
+               
+               yield return 2;
+       }
+
+       public static int Main ()
+       {
+               var c = new C ();
+               foreach (var a in c.Test ())
+               {
+               }
+               
+               return 0;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-debug-21-ref.xml b/mcs/tests/test-debug-21-ref.xml
new file mode 100644 (file)
index 0000000..ce4fbe3
--- /dev/null
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<symbols>
+  <files>
+    <file id="1" name="test-debug-21.cs" checksum="4d61ccab0e08defc5c9c97012b30aa70" />
+  </files>
+  <methods>
+    <method token="0x6000001">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000002">
+      <sequencepoints>
+        <entry il="0x0" row="22" file_ref="1" hidden="false" />
+        <entry il="0x1" row="23" file_ref="1" hidden="false" />
+      </sequencepoints>
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000003">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000004">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000005">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000006">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000007">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x6000008">
+      <sequencepoints>
+        <entry il="0x0" row="14" file_ref="1" hidden="false" />
+        <entry il="0x1" row="15" file_ref="1" hidden="false" />
+        <entry il="0xb" row="16" file_ref="1" hidden="false" />
+      </sequencepoints>
+      <locals />
+      <scopes>
+        <entry index="0" start="0x1" end="0xb" />
+      </scopes>
+    </method>
+    <method token="0x6000009">
+      <sequencepoints>
+        <entry il="0x27" row="7" file_ref="1" hidden="false" />
+        <entry il="0x28" row="8" file_ref="1" hidden="false" />
+        <entry il="0x32" row="9" file_ref="1" hidden="false" />
+        <entry il="0x41" row="10" file_ref="1" hidden="false" />
+        <entry il="0x42" row="11" file_ref="1" hidden="false" />
+        <entry il="0x5f" row="12" file_ref="1" hidden="false" />
+        <entry il="0x70" row="18" file_ref="1" hidden="false" />
+        <entry il="0x8b" row="19" file_ref="1" hidden="false" />
+      </sequencepoints>
+      <locals />
+      <scopes>
+        <entry index="0" start="0x42" end="0x5f" />
+      </scopes>
+    </method>
+    <method token="0x600000a">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x600000b">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+    <method token="0x600000c">
+      <sequencepoints />
+      <locals />
+      <scopes />
+    </method>
+  </methods>
+</symbols>
\ No newline at end of file
diff --git a/mcs/tests/test-debug-21.cs b/mcs/tests/test-debug-21.cs
new file mode 100644 (file)
index 0000000..76727b5
--- /dev/null
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+
+class C
+{
+       IEnumerable<int> Test ()
+       {
+               Console.WriteLine ("init");
+               try
+               {
+                       yield return 1;
+               }
+               finally
+               {
+                       Console.WriteLine ("aa");
+               }
+               
+               yield return 2;
+       }
+
+       public static void Main ()
+       {
+       }
+}
\ No newline at end of file
index 00d1f77f4b24dbcbea64f021c9b6f9aafd43dc50..763ac62ef110c87c5eb32f1bc2ffe1bac39a3640 100644 (file)
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>215</size>
+        <size>199</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="MyTest+&lt;Map&gt;c__Iterator0`4[Aa,Af,Rf,Rr]">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-218.cs">
     <type name="Foo">
         <size>26</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>117</size>
+        <size>115</size>
       </method>
       <method name="Void Dispose()" attrs="486">
         <size>53</size>
         <size>26</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>189</size>
+        <size>173</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="TestGoto+&lt;setX&gt;c__Iterator0">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>9</size>
+      </method>
+    </type>
+    <type name="TestGoto+&lt;test&gt;c__Iterator1">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-382.cs">
     <type name="C">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>211</size>
+        <size>181</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>83</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="Test+&lt;Select&gt;c__Iterator0`1[T]">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>37</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-autoproperty-01.cs">
     <type name="Test">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>303</size>
+        <size>287</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
     </type>
   </test>
   <test name="gtest-etree-15.cs">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>204</size>
+        <size>188</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>232</size>
+        <size>221</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>64</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="Test+&lt;Annotations&gt;c__Iterator0`1[T]">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
+    <type name="Test+&lt;Annotations&gt;c__Iterator1">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>18</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-iter-04.cs">
     <type name="TestClass">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>197</size>
+        <size>181</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
     </type>
   </test>
   <test name="gtest-iter-06.cs">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>197</size>
+        <size>186</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>64</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>18</size>
+      </method>
     </type>
   </test>
   <test name="gtest-iter-08.cs">
         <size>19</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>184</size>
+        <size>173</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>64</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>18</size>
+      </method>
     </type>
   </test>
   <test name="gtest-iter-12.cs">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>225</size>
+        <size>195</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>83</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>37</size>
+      </method>
     </type>
   </test>
   <test name="gtest-iter-14.cs">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>189</size>
+        <size>173</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
     </type>
   </test>
   <test name="gtest-iter-16.cs">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>195</size>
+        <size>179</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>195</size>
+        <size>179</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="Test.Derived+&lt;GetStuff&gt;c__Iterator1">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
+    <type name="Test.SpecialDerived+&lt;GetStuff&gt;c__Iterator2">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-iter-17.cs">
     <type name="Test">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>203</size>
+        <size>187</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>69</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
         <size>7</size>
       </method>
     </type>
+    <type name="IEnumerableTransform+&lt;Transform&gt;c__Iterator0`1[TOut]">
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+    </type>
   </test>
   <test name="gtest-iter-20.cs">
     <type name="X">
       </method>
     </type>
   </test>
+  <test name="gtest-iter-21.cs">
+    <type name="C">
+      <method name="IEnumerable`1 Test()" attrs="129">
+        <size>23</size>
+      </method>
+      <method name="Int32 Main()" attrs="150">
+        <size>72</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C+&lt;Test&gt;c__Iterator0">
+      <method name="Int32 System.Collections.Generic.IEnumerator&lt;int&gt;.get_Current()" attrs="2529">
+        <size>14</size>
+      </method>
+      <method name="System.Object System.Collections.IEnumerator.get_Current()" attrs="2529">
+        <size>19</size>
+      </method>
+      <method name="IEnumerator System.Collections.IEnumerable.GetEnumerator()" attrs="481">
+        <size>14</size>
+      </method>
+      <method name="IEnumerator`1 System.Collections.Generic.IEnumerable&lt;int&gt;.GetEnumerator()" attrs="481">
+        <size>26</size>
+      </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+      <method name="Boolean MoveNext()" attrs="486">
+        <size>150</size>
+      </method>
+      <method name="Void Dispose()" attrs="486">
+        <size>57</size>
+      </method>
+      <method name="Void Reset()" attrs="486">
+        <size>6</size>
+      </method>
+      <method name="Void &lt;&gt;m__0()" attrs="131">
+        <size>12</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="gtest-lambda-01.cs">
     <type name="IntFunc">
       <method name="Int32 Invoke(Int32)" attrs="454">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>197</size>
+        <size>181</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>73</size>
+        <size>57</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
     </type>
   </test>
   <test name="test-anon-108.cs">
         <size>14</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>207</size>
+        <size>177</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>83</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>37</size>
+      </method>
     </type>
   </test>
   <test name="test-anon-50.cs">
       </method>
     </type>
   </test>
+  <test name="test-debug-21.cs">
+    <type name="C">
+      <method name="IEnumerable`1 Test()" attrs="129">
+        <size>23</size>
+      </method>
+      <method name="Void Main()" attrs="150">
+        <size>2</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="C+&lt;Test&gt;c__Iterator0">
+      <method name="Int32 System.Collections.Generic.IEnumerator&lt;int&gt;.get_Current()" attrs="2529">
+        <size>14</size>
+      </method>
+      <method name="System.Object System.Collections.IEnumerator.get_Current()" attrs="2529">
+        <size>19</size>
+      </method>
+      <method name="IEnumerator System.Collections.IEnumerable.GetEnumerator()" attrs="481">
+        <size>14</size>
+      </method>
+      <method name="IEnumerator`1 System.Collections.Generic.IEnumerable&lt;int&gt;.GetEnumerator()" attrs="481">
+        <size>26</size>
+      </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>13</size>
+      </method>
+      <method name="Boolean MoveNext()" attrs="486">
+        <size>150</size>
+      </method>
+      <method name="Void Dispose()" attrs="486">
+        <size>57</size>
+      </method>
+      <method name="Void Reset()" attrs="486">
+        <size>6</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-externalias-01.cs">
     <type name="Test">
       <method name="Int32 Main()" attrs="145">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>282</size>
+        <size>264</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>119</size>
+        <size>107</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>13</size>
+      </method>
+      <method name="Void &lt;&gt;__Finally1()" attrs="129">
+        <size>13</size>
+      </method>
+      <method name="Void &lt;&gt;__Finally2()" attrs="129">
+        <size>13</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-08.cs">
         <size>52</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>393</size>
+        <size>361</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>109</size>
+        <size>77</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>23</size>
+      </method>
+      <method name="Void &lt;&gt;__Finally1()" attrs="129">
+        <size>23</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-09.cs">
         <size>14</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>693</size>
+        <size>663</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>103</size>
+        <size>73</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>37</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-10.cs">
         <size>40</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>203</size>
+        <size>190</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>70</size>
+        <size>57</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>20</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-13.cs">
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>20</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-14.cs">
         <size>26</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>38</size>
+        <size>42</size>
       </method>
       <method name="Void Dispose()" attrs="486">
         <size>15</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>3</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-17.cs">
         <size>14</size>
       </method>
       <method name="Boolean MoveNext()" attrs="486">
-        <size>207</size>
+        <size>177</size>
       </method>
       <method name="Void Dispose()" attrs="486">
-        <size>83</size>
+        <size>53</size>
       </method>
       <method name="Void Reset()" attrs="486">
         <size>6</size>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void &lt;&gt;__Finally0()" attrs="129">
+        <size>37</size>
+      </method>
     </type>
   </test>
   <test name="test-iter-23.cs">