Merge pull request #155 from andreazevedo/patch-1
authorRolf Bjarne Kvinge <rolfbjarne@gmail.com>
Wed, 10 Aug 2011 10:30:57 +0000 (03:30 -0700)
committerRolf Bjarne Kvinge <rolfbjarne@gmail.com>
Wed, 10 Aug 2011 10:30:57 +0000 (03:30 -0700)
Corrected word spelling

mcs/mcs/context.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/statement.cs
mcs/tests/test-async-17.cs
mcs/tests/ver-il-net_4_0.xml

index 921770cce7820a54293a952da7d94f83c30c18d4..4c52e7615532083bc73ff4474c73ac14986ce660 100644 (file)
@@ -132,9 +132,9 @@ namespace Mono.CSharp
                        return branching;
                }
 
-               public FlowBranchingException StartFlowBranching (ExceptionStatement stmt)
+               public FlowBranchingTryFinally StartFlowBranching (TryFinallyBlock stmt)
                {
-                       FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt);
+                       FlowBranchingTryFinally branching = new FlowBranchingTryFinally (CurrentBranching, stmt);
                        current_flow_branching = branching;
                        return branching;
                }
index 3eba78a5374557a7ce1d0fe782effdb9588e8ca1..61eb508bddf2ac7a33f809f3a8bc2aa56773d8fb 100644 (file)
@@ -730,12 +730,12 @@ namespace Mono.CSharp
 
        public class FlowBranchingTryCatch : FlowBranchingBlock
        {
-               TryCatch stmt;
+               readonly TryCatch tc;
 
                public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt)
                        : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc)
                {
-                       this.stmt = stmt;
+                       this.tc = stmt;
                }
 
                public override bool CheckRethrow (Location loc)
@@ -746,11 +746,13 @@ namespace Mono.CSharp
                public override bool AddResumePoint (ResumableStatement stmt, out int pc)
                {
                        int errors = Report.Errors;
-                       Parent.AddResumePoint (stmt, out pc);
+                       Parent.AddResumePoint (tc.IsTryCatchFinally ? stmt : tc, out pc);
                        if (errors == Report.Errors) {
                                if (stmt is AwaitStatement) {
                                        if (CurrentUsageVector.Next != null) {
                                                Report.Error (1985, stmt.loc, "The `await' operator cannot be used in the body of a catch clause");
+                                       } else {
+                                               this.tc.AddResumePoint (stmt, pc);
                                        }
                                } else {
                                        if (CurrentUsageVector.Next == null)
@@ -766,21 +768,21 @@ namespace Mono.CSharp
                public override bool AddBreakOrigin (UsageVector vector, Location loc)
                {
                        Parent.AddBreakOrigin (vector, loc);
-                       stmt.SomeCodeFollows ();
+                       tc.SomeCodeFollows ();
                        return true;
                }
 
                public override bool AddContinueOrigin (UsageVector vector, Location loc)
                {
                        Parent.AddContinueOrigin (vector, loc);
-                       stmt.SomeCodeFollows ();
+                       tc.SomeCodeFollows ();
                        return true;
                }
 
                public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
                {
                        Parent.AddReturnOrigin (vector, exit_stmt);
-                       stmt.SomeCodeFollows ();
+                       tc.SomeCodeFollows ();
                        return true;
                }
 
@@ -837,7 +839,7 @@ namespace Mono.CSharp
                }
        }
 
-       public class FlowBranchingException : FlowBranching
+       public class FlowBranchingTryFinally : FlowBranching
        {
                ExceptionStatement stmt;
                UsageVector current_vector;
@@ -923,7 +925,7 @@ namespace Mono.CSharp
 
                SavedOrigin saved_origins;
 
-               public FlowBranchingException (FlowBranching parent,
+               public FlowBranchingTryFinally (FlowBranching parent,
                                               ExceptionStatement stmt)
                        : base (parent, BranchingType.Exception, SiblingType.Try,
                                null, stmt.loc)
index 9420088039e644f803dfc4916dcf328bd738f537..2e18221c4242fa7c43a385ebbc15397c06669ca4 100644 (file)
@@ -3950,22 +3950,16 @@ namespace Mono.CSharp {
                }
        }
 
-       // Base class for statements that are implemented in terms of try...finally
-       public abstract class ExceptionStatement : ResumableStatement
+       public abstract class TryFinallyBlock : ExceptionStatement
        {
-#if !STATIC
-               bool code_follows;
-#endif
-               List<ResumableStatement> resume_points;
-               int first_resume_pc;
                protected Statement stmt;
                Label dispose_try_block;
                bool prepared_for_dispose, emitted_dispose;
 
-               protected ExceptionStatement (Statement stmt, Location loc)
+               protected TryFinallyBlock (Statement stmt, Location loc)
+                       : base (loc)
                {
                        this.stmt = stmt;
-                       this.loc = loc;
                }
 
                #region Properties
@@ -3978,45 +3972,29 @@ namespace Mono.CSharp {
 
                #endregion
 
-               protected abstract void EmitPreTryBody (EmitContext ec);
                protected abstract void EmitTryBody (EmitContext ec);
                protected abstract void EmitFinallyBody (EmitContext ec);
 
-               protected sealed override void DoEmit (EmitContext ec)
+               public override Label PrepareForDispose (EmitContext ec, Label end)
                {
-                       EmitPreTryBody (ec);
-
-                       StateMachineInitializer state_machine = null;
-                       if (resume_points != null) {
-                               state_machine = (StateMachineInitializer) ec.CurrentAnonymousMethod;
-
-                               ec.EmitInt ((int) IteratorStorey.State.Running);
-                               ec.Emit (OpCodes.Stloc, state_machine.CurrentPC);
-                       }
-
-                       ec.BeginExceptionBlock ();
-
-                       if (resume_points != null) {
-                               ec.MarkLabel (resume_point);
-
-                               // For normal control flow, we want to fall-through the Switch
-                               // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above
-                               ec.Emit (OpCodes.Ldloc, state_machine.CurrentPC);
-                               ec.EmitInt (first_resume_pc);
-                               ec.Emit (OpCodes.Sub);
-
-                               Label [] labels = new Label [resume_points.Count];
-                               for (int i = 0; i < resume_points.Count; ++i)
-                                       labels [i] = resume_points [i].PrepareForEmit (ec);
-                               ec.Emit (OpCodes.Switch, labels);
+                       if (!prepared_for_dispose) {
+                               prepared_for_dispose = true;
+                               dispose_try_block = ec.DefineLabel ();
                        }
+                       return dispose_try_block;
+               }
 
+               protected sealed override void DoEmit (EmitContext ec)
+               {
+                       EmitTryBodyPrepare (ec);
                        EmitTryBody (ec);
 
                        ec.BeginFinallyBlock ();
 
                        Label start_finally = ec.DefineLabel ();
                        if (resume_points != null) {
+                               var state_machine = (StateMachineInitializer) ec.CurrentAnonymousMethod;
+
                                ec.Emit (OpCodes.Ldloc, state_machine.SkipFinally);
                                ec.Emit (OpCodes.Brfalse_S, start_finally);
                                ec.Emit (OpCodes.Endfinally);
@@ -4028,46 +4006,6 @@ namespace Mono.CSharp {
                        ec.EndExceptionBlock ();
                }
 
-               public void SomeCodeFollows ()
-               {
-#if !STATIC
-                       code_follows = true;
-#endif
-               }
-
-               public override bool Resolve (BlockContext ec)
-               {
-#if !STATIC
-                       // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause
-                       // So, ensure there's some IL code after this statement.
-                       if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable)
-                               ec.NeedReturnLabel ();
-#endif
-                       return true;
-               }
-
-               public void AddResumePoint (ResumableStatement stmt, int pc)
-               {
-                       if (resume_points == null) {
-                               resume_points = new List<ResumableStatement> ();
-                               first_resume_pc = pc;
-                       }
-
-                       if (pc != first_resume_pc + resume_points.Count)
-                               throw new InternalErrorException ("missed an intervening AddResumePoint?");
-
-                       resume_points.Add (stmt);
-               }
-
-               public override Label PrepareForDispose (EmitContext ec, Label end)
-               {
-                       if (!prepared_for_dispose) {
-                               prepared_for_dispose = true;
-                               dispose_try_block = ec.DefineLabel ();
-                       }
-                       return dispose_try_block;
-               }
-
                public override void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher)
                {
                        if (emitted_dispose)
@@ -4085,24 +4023,24 @@ namespace Mono.CSharp {
 
                        ec.MarkLabel (dispose_try_block);
 
-                       Label [] labels = null;
+                       Label[] labels = null;
                        for (int i = 0; i < resume_points.Count; ++i) {
-                               ResumableStatement s = resume_points [i];
+                               ResumableStatement s = resume_points[i];
                                Label ret = s.PrepareForDispose (ec, end_of_try);
                                if (ret.Equals (end_of_try) && labels == null)
                                        continue;
                                if (labels == null) {
-                                       labels = new Label [resume_points.Count];
+                                       labels = new Label[resume_points.Count];
                                        for (int j = 0; j < i; ++j)
-                                               labels [j] = end_of_try;
+                                               labels[j] = end_of_try;
                                }
-                               labels [i] = ret;
+                               labels[i] = ret;
                        }
 
                        if (labels != null) {
                                int j;
                                for (j = 1; j < labels.Length; ++j)
-                                       if (!labels [0].Equals (labels [j]))
+                                       if (!labels[0].Equals (labels[j]))
                                                break;
                                bool emit_dispatcher = j < labels.Length;
 
@@ -4129,7 +4067,84 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Lock : ExceptionStatement
+       //
+       // Base class for blocks using exception handling
+       //
+       public abstract class ExceptionStatement : ResumableStatement
+       {
+#if !STATIC
+               bool code_follows;
+#endif
+               protected List<ResumableStatement> resume_points;
+               protected int first_resume_pc;
+
+               protected ExceptionStatement (Location loc)
+               {
+                       this.loc = loc;
+               }
+
+               protected virtual void EmitTryBodyPrepare (EmitContext ec)
+               {
+                       StateMachineInitializer state_machine = null;
+                       if (resume_points != null) {
+                               state_machine = (StateMachineInitializer) ec.CurrentAnonymousMethod;
+
+                               ec.EmitInt ((int) IteratorStorey.State.Running);
+                               ec.Emit (OpCodes.Stloc, state_machine.CurrentPC);
+                       }
+
+                       ec.BeginExceptionBlock ();
+
+                       if (resume_points != null) {
+                               ec.MarkLabel (resume_point);
+
+                               // For normal control flow, we want to fall-through the Switch
+                               // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above
+                               ec.Emit (OpCodes.Ldloc, state_machine.CurrentPC);
+                               ec.EmitInt (first_resume_pc);
+                               ec.Emit (OpCodes.Sub);
+
+                               Label[] labels = new Label[resume_points.Count];
+                               for (int i = 0; i < resume_points.Count; ++i)
+                                       labels[i] = resume_points[i].PrepareForEmit (ec);
+                               ec.Emit (OpCodes.Switch, labels);
+                       }
+               }
+
+               public void SomeCodeFollows ()
+               {
+#if !STATIC
+                       code_follows = true;
+#endif
+               }
+
+               public override bool Resolve (BlockContext ec)
+               {
+#if !STATIC
+                       // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause
+                       // So, ensure there's some IL code after this statement.
+                       if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable)
+                               ec.NeedReturnLabel ();
+#endif
+                       return true;
+               }
+
+               public void AddResumePoint (ResumableStatement stmt, int pc)
+               {
+                       if (resume_points == null) {
+                               resume_points = new List<ResumableStatement> ();
+                               first_resume_pc = pc;
+                       }
+
+                       if (pc != first_resume_pc + resume_points.Count)
+                               throw new InternalErrorException ("missed an intervening AddResumePoint?");
+
+                       resume_points.Add (stmt);
+               }
+
+       }
+
+       public class Lock : TryFinallyBlock
        {
                Expression expr;
                TemporaryVariableReference expr_copy;
@@ -4197,7 +4212,7 @@ namespace Mono.CSharp {
                        return true;
                }
                
-               protected override void EmitPreTryBody (EmitContext ec)
+               protected override void EmitTryBodyPrepare (EmitContext ec)
                {
                        expr_copy.EmitAssign (ec, expr);
 
@@ -4213,6 +4228,8 @@ namespace Mono.CSharp {
                                expr_copy.Emit (ec);
                                ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter.Get ());
                        }
+
+                       base.EmitTryBodyPrepare (ec);
                }
 
                protected override void EmitTryBody (EmitContext ec)
@@ -4772,7 +4789,8 @@ namespace Mono.CSharp {
                }
        }
 
-       public class TryFinally : ExceptionStatement {
+       public class TryFinally : TryFinallyBlock
+       {
                Block fini;
 
                public TryFinally (Statement stmt, Block fini, Location loc)
@@ -4804,10 +4822,6 @@ namespace Mono.CSharp {
                        return ok;
                }
 
-               protected override void EmitPreTryBody (EmitContext ec)
-               {
-               }
-
                protected override void EmitTryBody (EmitContext ec)
                {
                        stmt.Emit (ec);
@@ -4828,16 +4842,15 @@ namespace Mono.CSharp {
                }
        }
 
-       public class TryCatch : Statement {
+       public class TryCatch : ExceptionStatement
+       {
                public Block Block;
                public List<Catch> Specific;
                public Catch General;
-               bool inside_try_finally;
-#if !STATIC
-               bool code_follows;
-#endif
+               readonly bool inside_try_finally;
 
                public TryCatch (Block block, List<Catch> catch_clauses, Location l, bool inside_try_finally)
+                       : base (l)
                {
                        this.Block = block;
                        this.Specific = catch_clauses;
@@ -4848,8 +4861,12 @@ namespace Mono.CSharp {
                                this.General = c;                       
                                catch_clauses.RemoveAt (0);
                        }
+               }
 
-                       loc = l;
+               public bool IsTryCatchFinally {
+                       get {
+                               return inside_try_finally;
+                       }
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4907,27 +4924,13 @@ namespace Mono.CSharp {
 
                        ec.EndFlowBranching ();
 
-#if !STATIC
-                       // System.Reflection.Emit automatically emits a 'leave' at the end of a try/catch clause
-                       // So, ensure there's some IL code after this statement
-                       if (!inside_try_finally && !code_follows && ec.CurrentBranching.CurrentUsageVector.IsUnreachable)
-                               ec.NeedReturnLabel ();
-#endif
-
-                       return ok;
+                       return base.Resolve (ec) && ok;
                }
 
-               public void SomeCodeFollows ()
-               {
-#if !STATIC
-                       code_follows = true;
-#endif
-               }
-               
-               protected override void DoEmit (EmitContext ec)
+               protected sealed override void DoEmit (EmitContext ec)
                {
                        if (!inside_try_finally)
-                               ec.BeginExceptionBlock ();
+                               EmitTryBodyPrepare (ec);
 
                        Block.Emit (ec);
 
@@ -4956,7 +4959,7 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Using : ExceptionStatement
+       public class Using : TryFinallyBlock
        {
                public class VariableDeclaration : BlockVariableDeclaration
                {
@@ -5130,9 +5133,10 @@ namespace Mono.CSharp {
 
                #endregion
 
-               protected override void EmitPreTryBody (EmitContext ec)
+               protected override void EmitTryBodyPrepare (EmitContext ec)
                {
                        decl.Emit (ec);
+                       base.EmitTryBodyPrepare (ec);
                }
 
                protected override void EmitTryBody (EmitContext ec)
index 3848b77d1ace8aa4b2c49938c18a843a7299243e..f0dccf548b22e5268f9bf1aa8413d0d3185bc163 100644 (file)
@@ -34,6 +34,33 @@ class Tester
                }
        }
        
+       async Task<int> TestException_5 ()
+       {
+               int state = 0;
+               try {
+                       await Task.Factory.StartNew (() => { throw new ArgumentException (); });
+                       state = 1;
+               } catch (ArgumentException) {
+                       state = 2;
+               } finally {
+                       if (state == 2)
+                               throw new ApplicationException ();      
+               }
+               
+               return 1;
+       }
+       
+       async Task<int> TestException_6 ()
+       {
+               try {
+                       await Task.Factory.StartNew (() => { throw new ArgumentException (); });
+               } catch (ArgumentException) {
+                       throw new ApplicationException ();      
+               }
+               
+               return 1;
+       }
+       
        static bool RunTest (MethodInfo test)
        {
                Console.Write ("Running test {0, -25}", test.Name);
index 2234762bee83810e3548579de8e9b691215c4500..c8c7de3ca6905366ef8b894c5a5c8374d1ce8221 100644 (file)
         <size>36</size>
       </method>
     </type>
-    <type name="Tester+&lt;TestException_3&gt;c__async2+&lt;TestException_3&gt;c__async4">
+    <type name="Tester">
+      <method name="System.Threading.Tasks.Task`1[System.Int32] TestException_5()">
+        <size>27</size>
+      </method>
+      <method name="System.Threading.Tasks.Task`1[System.Int32] TestException_6()">
+        <size>27</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;TestException_5&gt;c__async4">
+      <method name="Void MoveNext()">
+        <size>279</size>
+      </method>
+      <method name="Void &lt;&gt;m__9()">
+        <size>6</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>36</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;TestException_6&gt;c__async5">
+      <method name="Void MoveNext()">
+        <size>236</size>
+      </method>
+      <method name="Void &lt;&gt;m__A()">
+        <size>6</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>36</size>
+      </method>
+    </type>
+    <type name="Tester+&lt;TestException_3&gt;c__async2+&lt;TestException_3&gt;c__async6">
       <method name="Void MoveNext()">
         <size>195</size>
       </method>