[mcs] Reachability and flow analysis rewrite to work on resolved statements and expre...
authorMarek Safar <marek.safar@gmail.com>
Thu, 21 Nov 2013 13:41:58 +0000 (14:41 +0100)
committerMarek Safar <marek.safar@gmail.com>
Thu, 21 Nov 2013 13:43:08 +0000 (14:43 +0100)
40 files changed:
mcs/errors/cs0161-4.cs [deleted file]
mcs/errors/cs0162-17.cs [deleted file]
mcs/errors/cs0162-19.cs [deleted file]
mcs/errors/cs0162-20.cs [new file with mode: 0644]
mcs/errors/cs0162-7.cs
mcs/errors/cs0163-2.cs [new file with mode: 0644]
mcs/errors/cs0163.cs
mcs/errors/cs0165-22.cs [new file with mode: 0644]
mcs/errors/cs0165-23.cs [new file with mode: 0644]
mcs/errors/cs0165-24.cs [new file with mode: 0644]
mcs/errors/cs0201-10.cs [new file with mode: 0644]
mcs/errors/cs0429-4.cs [new file with mode: 0644]
mcs/errors/cs1632-2.cs [new file with mode: 0644]
mcs/errors/cs1632-3.cs [new file with mode: 0644]
mcs/errors/cs1632-4.cs [new file with mode: 0644]
mcs/errors/known-issues-net_4_5
mcs/mcs/anonymous.cs
mcs/mcs/argument.cs
mcs/mcs/assign.cs
mcs/mcs/async.cs
mcs/mcs/complete.cs
mcs/mcs/context.cs
mcs/mcs/cs-parser.jay
mcs/mcs/delegate.cs
mcs/mcs/dynamic.cs
mcs/mcs/ecore.cs
mcs/mcs/eval.cs
mcs/mcs/expression.cs
mcs/mcs/flowanalysis.cs
mcs/mcs/iterators.cs
mcs/mcs/linq.cs
mcs/mcs/method.cs
mcs/mcs/nullable.cs
mcs/mcs/statement.cs
mcs/tests/known-issues-net_4_5
mcs/tests/test-519.cs
mcs/tests/test-579.cs
mcs/tests/test-874.cs [new file with mode: 0644]
mcs/tests/test-876.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/cs0161-4.cs b/mcs/errors/cs0161-4.cs
deleted file mode 100644 (file)
index faeaf57..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// CS0161: `T.Main()': not all code paths return a value
-// Line: 6
-// CSC bug: The error is not reported even if it should as in other unreachable cases
-
-class T {
-       public static int Main ()
-       {
-               switch (1) {
-               case 1:
-                       return 0;
-               default:
-                       break;
-               }
-       }
-}
diff --git a/mcs/errors/cs0162-17.cs b/mcs/errors/cs0162-17.cs
deleted file mode 100644 (file)
index 821c741..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// CS0162: Unreachable code detected
-// Line: 10
-// Compiler options: -warnaserror
-
-public class X
-{
-       public static void Main ()
-       {
-               return;
-               1+1;
-       }
-}
\ No newline at end of file
diff --git a/mcs/errors/cs0162-19.cs b/mcs/errors/cs0162-19.cs
deleted file mode 100644 (file)
index b1f6ea3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// CS0162: Unreachable code detected
-// Line: 12
-// Compiler options: -warnaserror
-
-public class X
-{
-       static void test (int stop)
-       {
-               int pos = 0;
-               do {
-                       break;
-               } while (pos < stop);
-       }
-}
diff --git a/mcs/errors/cs0162-20.cs b/mcs/errors/cs0162-20.cs
new file mode 100644 (file)
index 0000000..e2bb4dc
--- /dev/null
@@ -0,0 +1,21 @@
+// CS0162: Unreachable code detected
+// Line: 14
+// Compiler options: -warnaserror
+
+using System;
+
+class X
+{
+
+       public static void Main ()
+       {
+               goto X;
+       A:
+               bool b = false;
+               if (b) {
+                       goto A;
+               }
+       X:
+               return;
+       }
+}
\ No newline at end of file
index d8ae75fb0c50b0a238eff8e0999cd4c1a8dd97ac..3eb8bcfdb3f5adc8a90bff945f19218a319522bc 100644 (file)
@@ -2,9 +2,6 @@
 // Line: 9
 // Compiler options: -warnaserror -warn:2
 
-// this requires a multi-pass algorithm for unreachable code detection
-// punting for now
-
 class Foo {
        static void Main ()
        {
diff --git a/mcs/errors/cs0163-2.cs b/mcs/errors/cs0163-2.cs
new file mode 100644 (file)
index 0000000..dfdd9c1
--- /dev/null
@@ -0,0 +1,20 @@
+// CS0163: Control cannot fall through from one case label `case 1:' to another
+// Line: 14
+
+using System;
+using System.Collections.Generic;
+
+static class C
+{
+       public static IEnumerable<int> Test (int key)
+       {
+               switch (key) {
+               case 1:
+                       yield return 0;
+               case 2:
+                       yield return 2;
+               default:
+                       throw new ArgumentOutOfRangeException ("symbol:" + key);
+               }
+       }
+}
\ No newline at end of file
index 7596a4fceae1d81e68bf8eb4759dfdc805682510..1f65f60490e53176c04c189e6e0466e1ae0ab355 100644 (file)
@@ -1,6 +1,5 @@
-// CS0163: Control cannot fall through from one case label to another
-// Line: 17
-
+// CS0163: Control cannot fall through from one case label `case 3:' to another
+// Line: 21
 
 public class Foo
 {
diff --git a/mcs/errors/cs0165-22.cs b/mcs/errors/cs0165-22.cs
new file mode 100644 (file)
index 0000000..6b76beb
--- /dev/null
@@ -0,0 +1,34 @@
+// CS0165: Use of unassigned local variable `x'
+// Line: 17
+
+using System;
+
+class Program
+{
+       static int Main ()
+       {
+               int foo = 9;
+               int x;
+
+               switch (foo) {
+               case 1:
+                       x = 1;
+                       gotoTarget: 
+                       {
+                               Console.WriteLine (x);
+                       }
+                       break;
+               default:
+                       {
+                               if (foo != 0) {
+                                       goto gotoTarget;
+                               }
+
+                               break;
+                       }
+               }
+
+               return 1;
+       }
+}
+
diff --git a/mcs/errors/cs0165-23.cs b/mcs/errors/cs0165-23.cs
new file mode 100644 (file)
index 0000000..8c947a2
--- /dev/null
@@ -0,0 +1,23 @@
+// CS0165: Use of unassigned local variable `retval'
+// Line: 9
+
+class Test
+{
+       static string DoStuff (string msg)
+       {
+               string retval;
+
+               switch (msg) {
+               case "hello":
+                       retval = "goodbye";
+                       return retval;
+               case "goodbye":
+                       return retval;
+               case "other":
+                       retval = "other";
+               case "":
+                       return msg;
+               }
+               return "";
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0165-24.cs b/mcs/errors/cs0165-24.cs
new file mode 100644 (file)
index 0000000..cbc9c97
--- /dev/null
@@ -0,0 +1,18 @@
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+class X
+{
+       public static void Main ()
+       {
+               int i = 3;
+               switch (i) {
+               case 1:
+                       float a = 7.0f;
+                       break;
+               default:
+                       float b = a + 99.0f;
+                       break;
+               }
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0201-10.cs b/mcs/errors/cs0201-10.cs
new file mode 100644 (file)
index 0000000..a76e80a
--- /dev/null
@@ -0,0 +1,11 @@
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
+// Line: 9
+
+public class X
+{
+       public static void Main ()
+       {
+               return;
+               1+1;
+       }
+}
\ No newline at end of file
diff --git a/mcs/errors/cs0429-4.cs b/mcs/errors/cs0429-4.cs
new file mode 100644 (file)
index 0000000..d808039
--- /dev/null
@@ -0,0 +1,14 @@
+// CS0429: Unreachable expression code detected
+// Line: 12
+// Compiler options: -warnaserror
+
+public class X
+{
+       static void test (int stop)
+       {
+               int pos = 0;
+               do {
+                       break;
+               } while (pos < stop);
+       }
+}
diff --git a/mcs/errors/cs1632-2.cs b/mcs/errors/cs1632-2.cs
new file mode 100644 (file)
index 0000000..fe6c1c2
--- /dev/null
@@ -0,0 +1,16 @@
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 12
+
+using System;
+
+class X
+{
+       public static void Main ()
+       {
+               while (true) {
+                       Action a = () => {
+                               break;
+                       };
+               }
+       }
+}
diff --git a/mcs/errors/cs1632-3.cs b/mcs/errors/cs1632-3.cs
new file mode 100644 (file)
index 0000000..b7e457b
--- /dev/null
@@ -0,0 +1,20 @@
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 14
+
+using System;
+
+class X
+{
+       public static void Main ()
+       {
+               int b = 0;
+               switch (b) {
+                       case 1:
+                       Action a = () => {
+                               break;
+                       };
+                       
+                       break;
+               }
+       }
+}
diff --git a/mcs/errors/cs1632-4.cs b/mcs/errors/cs1632-4.cs
new file mode 100644 (file)
index 0000000..a9127d5
--- /dev/null
@@ -0,0 +1,22 @@
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 14
+
+using System;
+
+class X
+{
+       public static void Main ()
+       {
+               int b = 0;
+               switch (b) {
+               case 1:
+                       Action a = () => {
+                               goto case 2;
+                       };
+                       
+                       break;
+               case 2:
+                       break;
+               }
+       }
+}
index cbad5a36cf827d4e439d0aa053eac24762d86eea..1e07f7c667ee0b12c339540088bf027700452b7b 100644 (file)
@@ -14,9 +14,6 @@
 # Parser problems
 cs0080.cs 
 
-cs0162-7.cs NO ERROR
-cs0165-3.cs
-
 # Operators
 cs0457-2.cs
 cs0457.cs
index 27b1485f56a92473f0ca42559ea8b3edb8b4620d..0e440a0f7c9f71aea162943bc045dadd7056efdc 100644 (file)
@@ -214,6 +214,11 @@ namespace Mono.CSharp {
                                hoisted_this.EmitAssign (ec, source, false, false);
                        }
 
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               return false;
+                       }
+
                        protected override void CloneTo (CloneContext clonectx, Statement target)
                        {
                                // Nothing to clone
@@ -1339,13 +1344,6 @@ namespace Mono.CSharp {
                        if (!DoResolveParameters (ec))
                                return null;
 
-#if !STATIC
-                       // FIXME: The emitted code isn't very careful about reachability
-                       // so, ensure we have a 'ret' at the end
-                       BlockContext bc = ec as BlockContext;
-                       if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
-                               bc.NeedReturnLabel ();
-#endif
                        return this;
                }
 
@@ -1521,12 +1519,25 @@ namespace Mono.CSharp {
                        }
 
                        var bc = ec as BlockContext;
-                       if (bc != null)
+
+                       if (bc != null) {
                                aec.AssignmentInfoOffset = bc.AssignmentInfoOffset;
+                               aec.EnclosingLoop = bc.EnclosingLoop;
+                               aec.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch;
+                               aec.Switch = bc.Switch;
+                       }
 
                        var errors = ec.Report.Errors;
 
-                       bool res = Block.Resolve (ec.CurrentBranching, aec, null);
+                       bool res = Block.Resolve (aec);
+
+                       if (res) {
+                               MarkReachable (new Reachability ());
+
+                               if (!CheckReachableExit (ec.Report)) {
+                                       return null;
+                               }
+                       }
 
                        if (am != null && am.ReturnTypeInference != null) {
                                am.ReturnTypeInference.FixAllTypes (ec);
@@ -1557,6 +1568,43 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               bool CheckReachableExit (Report report)
+               {
+                       if (block.HasReachableClosingBrace && ReturnType.Kind != MemberKind.Void) {
+                               // FIXME: Flow-analysis on MoveNext generated code
+                               if (!IsIterator) {
+                                       report.Error (1643, StartLocation,
+                                                       "Not all code paths return a value in anonymous method of type `{0}'", GetSignatureForError ());
+
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       // We are reachable, mark block body reachable too
+                       MarkReachable (new Reachability ());
+
+                       CheckReachableExit (fc.Report);
+
+                       var das = fc.BranchDefiniteAssignment ();
+                       var prev_pb = fc.ParametersBlock;
+                       fc.ParametersBlock = Block;
+
+                       block.FlowAnalysis (fc);
+
+                       fc.ParametersBlock = prev_pb;
+                       fc.DefiniteAssignment = das;
+               }
+
+               public override void MarkReachable (Reachability rc)
+               {
+                       block.MarkReachable (rc);
+               }
+
                public void SetHasThisAccess ()
                {
                        ExplicitBlock b = block;
index facb0eb28c092e4d3f0ecdab9071bd8524306aeb..c516ffde5b0f080798142ce2e2d361745c4f6104 100644 (file)
@@ -127,6 +127,29 @@ namespace Mono.CSharp
                        return this;
                }
 
+               public void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (ArgType == AType.Out) {
+                               var vr = Expr as VariableReference;
+                               if (vr != null) {
+                                       if (vr.VariableInfo != null)
+                                               fc.SetVariableAssigned (vr.VariableInfo);
+
+                                       return;
+                               }
+
+                               var fe = Expr as FieldExpr;
+                               if (fe != null) {
+                                       fe.SetFieldAssigned (fc);
+                                       return;
+                               }
+
+                               return;
+                       }
+
+                       Expr.FlowAnalysis (fc);
+               }
+
                public string GetSignatureForError ()
                {
                        if (Expr.eclass == ExprClass.MethodGroup)
@@ -152,18 +175,16 @@ namespace Mono.CSharp
 
                public void Resolve (ResolveContext ec)
                {
-//                     using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) {
-                               // Verify that the argument is readable
-                               if (ArgType != AType.Out)
-                                       Expr = Expr.Resolve (ec);
+                       // Verify that the argument is readable
+                       if (ArgType != AType.Out)
+                               Expr = Expr.Resolve (ec);
 
-                               // Verify that the argument is writeable
-                               if (Expr != null && IsByRef)
-                                       Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
+                       // Verify that the argument is writeable
+                       if (Expr != null && IsByRef)
+                               Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
 
-                               if (Expr == null)
-                                       Expr = ErrorExpression.Instance;
-//                     }
+                       if (Expr == null)
+                               Expr = ErrorExpression.Instance;
                }
        }
 
@@ -476,6 +497,12 @@ namespace Mono.CSharp
                        return null;
                }
 
+               public void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       foreach (var arg in args)
+                               arg.FlowAnalysis (fc);
+               }
+
                public List<Argument>.Enumerator GetEnumerator ()
                {
                        return args.GetEnumerator ();
index 49595edd0f473212d53faef69c0af454ae60bfbf..0f4d914faabfd1f773c66c4c2d15441fc4acbcd3 100644 (file)
@@ -417,6 +417,14 @@ namespace Mono.CSharp {
                        Emit (ec, true);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       source.FlowAnalysis (fc);
+
+                       if (target is ArrayAccess || target is IndexerExpr || target is PropertyExpr)
+                               target.FlowAnalysis (fc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Assign _target = (Assign) t;
@@ -465,6 +473,32 @@ namespace Mono.CSharp {
 
                        return this;
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       base.FlowAnalysis (fc);
+
+                       var vr = target as VariableReference;
+                       if (vr != null) {
+                               if (vr.VariableInfo != null)
+                                       fc.SetVariableAssigned (vr.VariableInfo);
+
+                               return;
+                       }
+
+                       var fe = target as FieldExpr;
+                       if (fe != null) {
+                               fe.SetFieldAssigned (fc);
+                               return;
+                       }
+               }
+
+               public override void MarkReachable (Reachability rc)
+               {
+                       var es = source as ExpressionStatement;
+                       if (es != null)
+                               es.MarkReachable (rc);
+               }
        }
 
        public class RuntimeExplicitAssign : Assign
@@ -593,6 +627,11 @@ namespace Mono.CSharp {
                        else
                                base.EmitStatement (ec);
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       source.FlowAnalysis (fc);
+               }
                
                public bool IsDefaultInitializer {
                        get {
@@ -780,6 +819,12 @@ namespace Mono.CSharp {
                        return base.DoResolve (ec);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       target.FlowAnalysis (fc);
+                       source.FlowAnalysis (fc);
+               }
+
                protected override Expression ResolveConversions (ResolveContext ec)
                {
                        //
index daa0073136204c4679d02a28290e89e11654c31b..ca39017696d7a61b6d2b9dc650e7ffb903ff78c6 100644 (file)
@@ -65,8 +65,19 @@ namespace Mono.CSharp
                        return true;
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+
+                       stmt.RegisterResumePoint ();
+               }
+
                protected override Expression DoResolve (ResolveContext rc)
                {
+                       if (rc.HasSet (ResolveContext.Options.FinallyScope)) {
+                               rc.Report.Error (1984, loc,  "The `await' operator cannot be used in the body of a finally clause");
+                       }
+
                        if (rc.HasSet (ResolveContext.Options.LockScope)) {
                                rc.Report.Error (1996, loc,
                                        "The `await' operator cannot be used in the body of a lock statement");
@@ -115,6 +126,12 @@ namespace Mono.CSharp
                        stmt.EmitStatement (ec);
                }
 
+               public override void MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       stmt.MarkReachable (rc);
+               }
+
                public override object Accept (StructuralVisitor visitor)
                {
                        return visitor.Visit (this);
@@ -175,6 +192,7 @@ namespace Mono.CSharp
                public AwaitStatement (Expression expr, Location loc)
                        : base (expr, loc)
                {
+                       unwind_protect = true;
                }
 
                #region Properties
@@ -306,6 +324,10 @@ namespace Mono.CSharp
                                return false;
                        }
 
+                       if (bc.HasSet (ResolveContext.Options.CatchScope)) {
+                               bc.Report.Error (1985, loc, "The `await' operator cannot be used in the body of a catch clause");
+                       }
+
                        if (!base.Resolve (bc))
                                return false;
 
@@ -363,6 +385,47 @@ namespace Mono.CSharp
                }
        }
 
+       class AsyncInitializerStatement : StatementExpression
+       {
+               public AsyncInitializerStatement (AsyncInitializer expr)
+                       : base (expr)
+               {
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       base.DoFlowAnalysis (fc);
+
+                       var init = (AsyncInitializer) Expr;
+                       var res = !init.Block.HasReachableClosingBrace;
+                       var storey = (AsyncTaskStorey) init.Storey;
+
+                       if (storey.ReturnType.IsGenericTask)
+                               return res;
+
+                       return true;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (!rc.IsUnreachable)
+                               reachable = true;
+
+                       var init = (AsyncInitializer) Expr;
+                       rc = init.Block.MarkReachable (rc);
+
+                       var storey = (AsyncTaskStorey) init.Storey;
+
+                       //
+                       // Explicit return is required for Task<T> state machine
+                       //
+                       if (storey.ReturnType != null && storey.ReturnType.IsGenericTask)
+                               return rc;
+
+                   return Reachability.CreateUnreachable ();
+               }
+       }
+
        public class AsyncInitializer : StateMachineInitializer
        {
                TypeInferenceContext return_inference;
@@ -398,14 +461,15 @@ namespace Mono.CSharp
 
                #endregion
 
-               protected override BlockContext CreateBlockContext (ResolveContext rc)
+               protected override BlockContext CreateBlockContext (BlockContext bc)
                {
-                       var ctx = base.CreateBlockContext (rc);
-                       var lambda = rc.CurrentAnonymousMethod as LambdaMethod;
+                       var ctx = base.CreateBlockContext (bc);
+                       var lambda = bc.CurrentAnonymousMethod as LambdaMethod;
                        if (lambda != null)
                                return_inference = lambda.ReturnTypeInference;
 
-                       ctx.StartFlowBranching (this, rc.CurrentBranching);
+                       ctx.Set (ResolveContext.Options.TryScope);
+
                        return ctx;
                }
 
@@ -426,6 +490,13 @@ namespace Mono.CSharp
                        storey.EmitInitializer (ec);
                        ec.Emit (OpCodes.Ret);
                }
+
+               public override void MarkReachable (Reachability rc)
+               {
+                       //
+                       // Reachability has been done in AsyncInitializerStatement
+                       //
+               }
        }
 
        class AsyncTaskStorey : StateMachine
index 6eb42cddada0a51de2f96f54fe9c35b0b6cd294e..2931d137f737917aa2fab3e74fe0c6ac1c44b5c2 100644 (file)
@@ -114,32 +114,22 @@ namespace Mono.CSharp {
                        var sn = expr as SimpleName;
                        const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
 
-                       //
-                       // Resolve the expression with flow analysis turned off, we'll do the definite
-                       // assignment checks later.  This is because we don't know yet what the expression
-                       // will resolve to - it may resolve to a FieldExpr and in this case we must do the
-                       // definite assignment check on the actual field and not on the whole struct.
-                       //
-                       using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
-                               if (sn != null) {
-                                       expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
-
-                                       //
-                                       // Resolve expression which does have type set as we need expression type
-                                       // with disable flow analysis as we don't know whether left side expression
-                                       // is used as variable or type
-                                       //
-                                       if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
-                                               using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       expr = expr.Resolve (rc);
-                                               }
-                                       } else if (expr is TypeParameterExpr) {
-                                               expr.Error_UnexpectedKind (rc, flags, sn.Location);
-                                               expr = null;
-                                       }
-                               } else {
-                                       expr = expr.Resolve (rc, flags);
+                       if (sn != null) {
+                               expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+
+                               //
+                               // Resolve expression which does have type set as we need expression type
+                               // with disable flow analysis as we don't know whether left side expression
+                               // is used as variable or type
+                               //
+                               if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+                                       expr = expr.Resolve (rc);
+                               } else if (expr is TypeParameterExpr) {
+                                       expr.Error_UnexpectedKind (rc, flags, sn.Location);
+                                       expr = null;
                                }
+                       } else {
+                               expr = expr.Resolve (rc, flags);
                        }
 
                        if (expr == null)
index 06d6994c04a1b95905d75f22f29c832f53acce7f..eea1a3a99f6fa7dbdc194f942c6c858a2e0553b6 100644 (file)
@@ -69,8 +69,6 @@ namespace Mono.CSharp
        //
        public class BlockContext : ResolveContext
        {
-               FlowBranching current_flow_branching;
-
                readonly TypeSpec return_type;
 
                //
@@ -112,124 +110,17 @@ namespace Mono.CSharp
                                flags |= ResolveContext.Options.BaseInitializer;
                }
 
-               public override FlowBranching CurrentBranching {
-                       get { return current_flow_branching; }
-               }
-
-               public TypeSpec ReturnType {
-                       get { return return_type; }
-               }
-
-               public bool IsUnreachable {
-                       get {
-                               return HasSet (Options.UnreachableScope);
-                       }
-                       set {
-                               flags = value ? flags | Options.UnreachableScope : flags & ~Options.UnreachableScope;
-                       }
-               }
-
-               public bool UnreachableReported {
-                       get {
-                               return HasSet (Options.UnreachableReported);
-                       }
-                       set {
-                               flags = value ? flags | Options.UnreachableReported : flags & ~Options.UnreachableScope;
-                       }
-               }
-
-               // <summary>
-               //   Starts a new code branching.  This inherits the state of all local
-               //   variables and parameters from the current branching.
-               // </summary>
-               public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
-               {
-                       current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc);
-                       return current_flow_branching;
-               }
-
-               // <summary>
-               //   Starts a new code branching for block `block'.
-               // </summary>
-               public FlowBranching StartFlowBranching (Block block)
-               {
-                       Set (Options.DoFlowAnalysis);
-
-                       current_flow_branching = FlowBranching.CreateBranching (
-                               CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation);
-                       return current_flow_branching;
-               }
-
-               public FlowBranchingTryCatch StartFlowBranching (TryCatch stmt)
-               {
-                       FlowBranchingTryCatch branching = new FlowBranchingTryCatch (CurrentBranching, stmt);
-                       current_flow_branching = branching;
-                       return branching;
-               }
-
-               public FlowBranchingTryFinally StartFlowBranching (TryFinallyBlock stmt)
-               {
-                       FlowBranchingTryFinally branching = new FlowBranchingTryFinally (CurrentBranching, stmt);
-                       current_flow_branching = branching;
-                       return branching;
-               }
-
-               public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt)
-               {
-                       FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt);
-                       current_flow_branching = branching;
-                       return branching;
-               }
-
-               public FlowBranchingIterator StartFlowBranching (Iterator iterator, FlowBranching parent)
-               {
-                       FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator);
-                       current_flow_branching = branching;
-                       return branching;
-               }
-
-               public FlowBranchingAsync StartFlowBranching (AsyncInitializer asyncBody, FlowBranching parent)
-               {
-                       var branching = new FlowBranchingAsync (parent, asyncBody);
-                       current_flow_branching = branching;
-                       return branching;
-               }
-
-               public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent)
-               {
-                       FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt);
-                       current_flow_branching = branching;
-                       return branching;
-               }
+               public ExceptionStatement CurrentTryBlock { get; set; }
 
-               // <summary>
-               //   Ends a code branching.  Merges the state of locals and parameters
-               //   from all the children of the ending branching.
-               // </summary>
-               public bool EndFlowBranching ()
-               {
-                       FlowBranching old = current_flow_branching;
-                       current_flow_branching = current_flow_branching.Parent;
+               public LoopStatement EnclosingLoop { get; set; }
 
-                       FlowBranching.UsageVector vector = current_flow_branching.MergeChild (old);
-                       return vector.IsUnreachable;
-               }
+               public LoopStatement EnclosingLoopOrSwitch { get; set; }
 
-               // <summary>
-               //   Kills the current code branching.  This throws away any changed state
-               //   information and should only be used in case of an error.
-               // </summary>
-               // FIXME: this is evil
-               public void KillFlowBranching ()
-               {
-                       current_flow_branching = current_flow_branching.Parent;
-               }
+               public Switch Switch { get; set; }
 
-#if !STATIC
-               public void NeedReturnLabel ()
-               {
+               public TypeSpec ReturnType {
+                       get { return return_type; }
                }
-#endif
        }
 
        //
@@ -290,20 +181,9 @@ namespace Mono.CSharp
 
                        LockScope = 1 << 13,
 
-                       UnreachableScope = 1 << 14,
+                       TryScope = 1 << 14,
 
-                       UnreachableReported = 1 << 15,
-
-                       /// <summary>
-                       ///   Whether control flow analysis is enabled
-                       /// </summary>
-                       DoFlowAnalysis = 1 << 20,
-
-                       /// <summary>
-                       ///   Whether control flow analysis is disabled on structs
-                       ///   (only meaningful when DoFlowAnalysis is set)
-                       /// </summary>
-                       OmitStructFlowAnalysis = 1 << 21,
+                       TryWithCatchScope = 1 << 15,
 
                        ///
                        /// Indicates the current context is in probing mode, no errors are reported. 
@@ -372,11 +252,6 @@ namespace Mono.CSharp
 
                public readonly IMemberContext MemberContext;
 
-               /// <summary>
-               ///   If this is non-null, points to the current switch statement
-               /// </summary>
-               public Switch Switch;
-
                public ResolveContext (IMemberContext mc)
                {
                        if (mc == null)
@@ -416,10 +291,6 @@ namespace Mono.CSharp
                        }
                }
 
-               public virtual FlowBranching CurrentBranching {
-                       get { return null; }
-               }
-
                //
                // The current iterator
                //
@@ -443,10 +314,6 @@ namespace Mono.CSharp
                        get { return (flags & Options.ConstantCheckState) != 0; }
                }
 
-               public bool DoFlowAnalysis {
-                       get { return (flags & Options.DoFlowAnalysis) != 0; }
-               }
-
                public bool IsInProbingMode {
                        get {
                                return (flags & Options.ProbingMode) != 0;
@@ -480,7 +347,7 @@ namespace Mono.CSharp
 
                public bool IsVariableCapturingRequired {
                        get {
-                               return !IsInProbingMode && (CurrentBranching == null || !CurrentBranching.CurrentUsageVector.IsUnreachable);
+                               return !IsInProbingMode;
                        }
                }
 
@@ -490,10 +357,6 @@ namespace Mono.CSharp
                        }
                }
 
-               public bool OmitStructFlowAnalysis {
-                       get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
-               }
-
                public Report Report {
                        get {
                                return Module.Compiler.Report;
@@ -573,6 +436,65 @@ namespace Mono.CSharp
                #endregion
        }
 
+       public class FlowAnalysisContext
+       {
+               readonly CompilerContext ctx;
+
+               public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock)
+               {
+                       this.ctx = ctx;
+                       this.ParametersBlock = parametersBlock;
+
+                       DefiniteAssignment = new DefiniteAssignmentBitSet ();
+               }
+
+               public DefiniteAssignmentBitSet DefiniteAssignment { get; set; }
+
+               public List<LabeledStatement> LabelStack { get; set; }
+
+               public ParametersBlock ParametersBlock { get; set; }
+
+               public Report Report {
+                       get {
+                               return ctx.Report;
+                       }
+               }
+
+               public DefiniteAssignmentBitSet SwitchInitialDefinitiveAssignment { get; set; }
+
+               public TryFinally TryFinally { get; set; }
+
+               public bool UnreachableReported { get; set; }
+
+               public DefiniteAssignmentBitSet BranchDefiniteAssignment ()
+               {
+                       var dat = DefiniteAssignment;
+                       DefiniteAssignment = new DefiniteAssignmentBitSet (dat);
+                       return dat;
+               }
+
+               public bool IsDefinitelyAssigned (VariableInfo variable)
+               {
+                       return variable.IsAssigned (DefiniteAssignment);
+               }
+
+               public bool IsStructFieldDefinitelyAssigned (VariableInfo variable, string name)
+               {
+                       return variable.IsStructFieldAssigned (DefiniteAssignment, name);
+               }
+
+               public void SetVariableAssigned (VariableInfo variable, bool generatedAssignment = false)
+               {
+                       variable.SetAssigned (DefiniteAssignment, generatedAssignment);
+               }
+
+               public void SetStructFieldAssigned (VariableInfo variable, string name)
+               {
+                       variable.SetStructFieldAssigned (DefiniteAssignment, name);
+               }
+       }
+
+
        //
        // This class is used during the Statement.Clone operation
        // to remap objects that have been cloned.
index 0c4aa6be32a6aa3447b4eeab19fc27597840d521..a64e4a86a8851e9e1a12ad6680f6c4d6c42c190e 100644 (file)
@@ -5900,12 +5900,12 @@ try_statement
          }
        | TRY block FINALLY block
          {
-               $$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1));
+               $$ = new TryFinally ((Statement) $2, (ExplicitBlock) $4, GetLocation ($1));
                lbag.AddStatement ($$, GetLocation ($3));
          }
        | TRY block catch_clauses FINALLY block
          {
-               $$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, Location.Null, true), (Block) $5, GetLocation ($1));
+               $$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, Location.Null, true), (ExplicitBlock) $5, GetLocation ($1));
                lbag.AddStatement ($$, GetLocation ($4));
          }
        | TRY block error
@@ -5945,12 +5945,12 @@ opt_identifier
 catch_clause 
        : CATCH block
          {
-               $$ = new Catch ((Block) $2, GetLocation ($1));
+               $$ = new Catch ((ExplicitBlock) $2, GetLocation ($1));
          }
        | CATCH open_parens_any type opt_identifier CLOSE_PARENS
          {
                start_block (GetLocation ($2));
-               var c = new Catch (current_block, GetLocation ($1));
+               var c = new Catch ((ExplicitBlock) current_block, GetLocation ($1));
                c.TypeExpression = (FullNamedExpression) $3;
 
                if ($4 != null) {
index cabb7dff00e4939721b22f07060adef398eabdf0..a927e9ee1b7662f77c17ba9f2d90cb74fa84ac46 100644 (file)
@@ -828,6 +828,13 @@ namespace Mono.CSharp {
                        return CreateExpressionFactoryCall (ec, "Invoke", args);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       InstanceExpr.FlowAnalysis (fc);
+                       if (arguments != null)
+                               arguments.FlowAnalysis (fc);
+               }
+
                protected override Expression DoResolve (ResolveContext ec)
                {               
                        TypeSpec del_type = InstanceExpr.Type;
index 2124f0fda088d89e5febb0092edb68e3dd115246..e4acde34d662be6d153da9cc22291ec02350ce70 100644 (file)
@@ -532,6 +532,11 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       arguments.FlowAnalysis (fc);
+               }
+
                public static MemberAccess GetBinderNamespace (Location loc)
                {
                        return new MemberAccess (new MemberAccess (
@@ -612,6 +617,11 @@ namespace Mono.CSharp
                                stmt.Emit (ec);
                        }
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       invoke.FlowAnalysis (fc);
+               }
        }
 
        class DynamicConversion : DynamicExpressionStatement, IDynamicBinder
index f01a1486bd5c8ea102b9fd11875bfa9a14184675..88b7a619d887cb432ffd9f6056f50e4fd84eb2a9 100644 (file)
@@ -923,6 +923,10 @@ namespace Mono.CSharp {
                        ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
                }
 
+               public virtual void FlowAnalysis (FlowAnalysisContext fc)
+               {
+               }
+
                /// <summary>
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
@@ -1175,6 +1179,10 @@ namespace Mono.CSharp {
        /// </summary>
        public abstract class ExpressionStatement : Expression
        {
+               public virtual void MarkReachable (Reachability rc)
+               {
+               }
+
                public ExpressionStatement ResolveStatement (BlockContext ec)
                {
                        Expression e = Resolve (ec);
@@ -1310,6 +1318,11 @@ namespace Mono.CSharp {
                        child.Emit (ec);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       child.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
 #if STATIC
@@ -2141,6 +2154,11 @@ namespace Mono.CSharp {
                        {
                                stm.EmitStatement (ec);
                        }
+
+                       public override void FlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               stm.FlowAnalysis (fc);
+                       }
                }
 
                readonly Expression expr, orig_expr;
@@ -2244,6 +2262,11 @@ namespace Mono.CSharp {
                        expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        return orig_expr.MakeExpression (ctx);
@@ -2339,7 +2362,38 @@ namespace Mono.CSharp {
                {
                        throw new InternalErrorException ("Missing Resolve call");
                }
+       }
+
+       public class UnreachableExpression : Expression
+       {
+               public UnreachableExpression (Expression expr)
+               {
+                       this.loc = expr.Location;
+               }
+
+               public override Expression CreateExpressionTree (ResolveContext ec)
+               {
+                       // TODO: is it ok
+                       throw new NotImplementedException ();
+               }
 
+               protected override Expression DoResolve (ResolveContext rc)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       fc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+
+               public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
+               {
+               }
        }
 
        //
@@ -2470,14 +2524,7 @@ namespace Mono.CSharp {
 
                protected override Expression DoResolve (ResolveContext rc)
                {
-                       var e = SimpleNameResolve (rc, null);
-
-                       var fe = e as FieldExpr;
-                       if (fe != null) {
-                               fe.VerifyAssignedStructField (rc, null);
-                       }
-
-                       return e;
+                       return SimpleNameResolve (rc, null);
                }
 
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
@@ -3162,6 +3209,12 @@ namespace Mono.CSharp {
                                member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (InstanceExpression != null)
+                               InstanceExpression.FlowAnalysis (fc);
+               }
+
                public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs)
                {
                        if (!ResolveInstanceExpressionCore (rc, rhs))
@@ -3264,15 +3317,7 @@ namespace Mono.CSharp {
                                                DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
                                }
 
-                               InstanceExpression = new This (loc);
-                               if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
-                                       using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
-                                               InstanceExpression = InstanceExpression.Resolve (rc);
-                                       }
-                               } else {
-                                       InstanceExpression = InstanceExpression.Resolve (rc);
-                               }
-
+                               InstanceExpression = new This (loc).Resolve (rc);
                                return false;
                        }
 
@@ -3280,29 +3325,17 @@ namespace Mono.CSharp {
                        if (me != null) {
                                me.ResolveInstanceExpressionCore (rc, rhs);
 
-                               // Using this check to detect probing instance expression resolve
-                               if (!rc.OmitStructFlowAnalysis) {
-                                       var fe = me as FieldExpr;
-                                       if (fe != null && fe.IsMarshalByRefAccess (rc)) {
-                                               rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
-                                               rc.Report.Warning (1690, 1, loc,
-                                                       "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
-                                                       me.GetSignatureForError ());
-                                       }
+                               var fe = me as FieldExpr;
+                               if (fe != null && fe.IsMarshalByRefAccess (rc)) {
+                                       rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
+                                       rc.Report.Warning (1690, 1, loc,
+                                               "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
+                                               me.GetSignatureForError ());
                                }
 
                                return true;
                        }
 
-                       //
-                       // Run member-access postponed check once we know that
-                       // the expression is not field expression which is the only
-                       // expression which can use uninitialized this
-                       //
-                       if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
-                               ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
-                       }
-
                        //
                        // Additional checks for l-value member access
                        //
@@ -5696,18 +5729,14 @@ namespace Mono.CSharp {
                                        // "a.b" is initialized, not whether the whole struct "a" is initialized.
 
                                        if (lvalue_instance) {
-                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
+                                               bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
 
-                                                       Expression right_side =
-                                                               out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+                                               Expression right_side =
+                                                       out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
 
-                                                       InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
-                                               }
+                                               InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
                                        } else {
-                                               using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
-                                               }
+                                               InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
                                        }
 
                                        if (InstanceExpression == null)
@@ -5720,10 +5749,6 @@ namespace Mono.CSharp {
                        var fb = spec as FixedFieldSpec;
                        IVariableReference var = InstanceExpression as IVariableReference;
 
-                       if (lvalue_instance && var != null && var.VariableInfo != null) {
-                               var.VariableInfo.SetStructFieldAssigned (ec, Name);
-                       }
-
                        if (fb != null) {
                                IFixedExpression fe = InstanceExpression as IFixedExpression;
                                if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
@@ -5747,15 +5772,50 @@ namespace Mono.CSharp {
                        //
                        if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
                                variable_info = var.VariableInfo.GetStructFieldInfo (Name);
-                               if (rhs != null && variable_info != null)
-                                       variable_info.SetStructFieldAssigned (ec, Name);
                        }
 
                        eclass = ExprClass.Variable;
                        return this;
                }
 
-               public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
+               public void SetFieldAssigned (FlowAnalysisContext fc)
+               {
+                       if (!IsInstance)
+                               return;
+
+                       bool lvalue_instance = spec.DeclaringType.IsStruct;
+                       if (lvalue_instance) {
+                               var var = InstanceExpression as IVariableReference;
+                               if (var != null && var.VariableInfo != null) {
+                                       fc.SetStructFieldAssigned (var.VariableInfo, Name);
+                               }
+                       }
+
+                       var fe = InstanceExpression as FieldExpr;
+                       if (fe != null || lvalue_instance) {
+                               if (fe == null)
+                                       return;
+
+                               /*
+                               while (fe.InstanceExpression is FieldExpr) {
+                                       fe = (FieldExpr) fe.InstanceExpression;
+                                       if (!fe.Spec.DeclaringType.IsStruct)
+                                               continue;
+
+                                       if (fe.VariableInfo != null && fc.IsStructFieldDefinitelyAssigned (fe.VariableInfo, fe.Name)) {
+                                               fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+                                       }
+                               }
+
+                               fe.InstanceExpression.FlowAnalysis (fc);
+                               */
+                       } else {
+                               InstanceExpression.FlowAnalysis (fc);
+                       }
+               }
+
+
+               public void VerifyAssignedStructField (FlowAnalysisContext fc)
                {
                        var fe = this;
 
@@ -5764,14 +5824,8 @@ namespace Mono.CSharp {
                                if (var != null) {
                                        var vi = var.VariableInfo;
 
-                                       if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
-                                               if (rhs != null) {
-                                                       rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
-                                               } else {
-                                                       rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
-                                               }
-
-                                               return;
+                                       if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, fe.Name) && !fe.type.IsStruct) {
+                                               fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
                                        }
                                }
 
@@ -5809,7 +5863,6 @@ namespace Mono.CSharp {
                                        rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
                                                GetSignatureForError ());
                                }
-
                                return null;
                        }
 
@@ -5875,6 +5928,23 @@ namespace Mono.CSharp {
                        return this;
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var var = InstanceExpression as IVariableReference;
+                       if (var != null) {
+                               var vi = var.VariableInfo;
+                               if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, Name)) {
+                                       fc.Report.Error (170, loc, "Use of possibly unassigned field `{0}'", Name);
+                                       return;
+                               }
+
+                               if (TypeSpec.IsValueType (InstanceExpression.Type))
+                                       return;
+                       }
+
+                       base.FlowAnalysis (fc);
+               }
+
                public override int GetHashCode ()
                {
                        return spec.GetHashCode ();
@@ -6742,6 +6812,11 @@ namespace Mono.CSharp {
                                DoEmit (ec);
                        }
 
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               return false;
+                       }
+
                        protected override void CloneTo (CloneContext clonectx, Statement target)
                        {
                                // Nothing
@@ -6843,10 +6918,6 @@ namespace Mono.CSharp {
                public override VariableInfo VariableInfo {
                        get { return null; }
                }
-
-               public override void VerifyDefiniteAssignment (ResolveContext rc)
-               {
-               }
        }
 
        /// 
index 3ae03c0f14bb602d30ec9846d9904f8664a89701..26e4f5d8d90ca2e1d004e5b20c60b9259ccdd78d 100644 (file)
@@ -389,7 +389,7 @@ namespace Mono.CSharp
                                BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void);
 
                                try {
-                                       method.Block.Resolve (null, bc, method);
+                                       method.Block.Resolve (bc, method);
                                } catch (CompletionResult cr) {
                                        prefix = cr.BaseText;
                                        return cr.Result;
index 695739bd1e6eebdf862af6cca8d307c42686e5f6..f647adab791e2aeedcfa8802aa30281873aca784 100644 (file)
@@ -83,6 +83,11 @@ namespace Mono.CSharp
                        call.EmitPredefined (ec, oper, arguments, loc);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       arguments.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
 #if STATIC
@@ -572,6 +577,19 @@ namespace Mono.CSharp
                        Expr.EmitSideEffect (ec);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (Oper == Operator.AddressOf) {
+                               var vr = Expr as VariableReference;
+                               if (vr != null && vr.VariableInfo != null)
+                                       fc.SetVariableAssigned (vr.VariableInfo);
+
+                               return;
+                       }
+
+                       Expr.FlowAnalysis (fc);
+               }
+
                //
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
                //
@@ -1274,6 +1292,11 @@ namespace Mono.CSharp
                        EmitCode (ec, false);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                //
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
                //
@@ -1367,6 +1390,11 @@ namespace Mono.CSharp
                        return this;
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                protected abstract string OperatorName { get; }
 
                protected override void CloneTo (CloneContext clonectx, Expression t)
@@ -2518,6 +2546,12 @@ namespace Mono.CSharp
                        Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       left.FlowAnalysis (fc);
+                       right.FlowAnalysis (fc);
+               }
+
                //
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
                //
@@ -4890,6 +4924,11 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       arguments.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        if (arguments.Count != 2)
@@ -5259,32 +5298,8 @@ namespace Mono.CSharp
                protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = 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);
-                       }
+                       true_expr = true_expr.Resolve (ec);
+                       false_expr = false_expr.Resolve (ec);
 
                        if (true_expr == null || false_expr == null || expr == null)
                                return null;
@@ -5345,8 +5360,9 @@ namespace Mono.CSharp
                                                true_type.GetSignatureForError (), false_type.GetSignatureForError ());
                                        return null;
                                }
-                       }                       
+                       }
 
+                       Constant c = expr as Constant;
                        if (c != null) {
                                bool is_false = c.IsDefaultValue;
 
@@ -5392,6 +5408,14 @@ namespace Mono.CSharp
                        ec.MarkLabel (end_target);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       // FIXME: Need to branch
+                       expr.FlowAnalysis (fc);
+                       true_expr.FlowAnalysis (fc);
+                       false_expr.FlowAnalysis (fc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        Conditional target = (Conditional) t;
@@ -5409,7 +5433,6 @@ namespace Mono.CSharp
                #region Abstract
                public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
                public abstract void SetHasAddressTaken ();
-               public abstract void VerifyDefiniteAssignment (ResolveContext rc);
 
                public abstract bool IsLockedByStatement { get; set; }
 
@@ -5642,17 +5665,17 @@ namespace Mono.CSharp
 
                #endregion
 
-               public override void VerifyDefiniteAssignment (ResolveContext rc)
+               public override void FlowAnalysis (FlowAnalysisContext fc)
                {
                        VariableInfo variable_info = VariableInfo;
                        if (variable_info == null)
                                return;
 
-                       if (variable_info.IsAssigned (rc))
+                       if (fc.IsDefinitelyAssigned (variable_info))
                                return;
 
-                       rc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
-                       variable_info.SetAssigned (rc);
+                       fc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
+                       variable_info.SetAssigned (fc.DefiniteAssignment, true);
                }
 
                public override void SetHasAddressTaken ()
@@ -5689,8 +5712,6 @@ namespace Mono.CSharp
                {
                        local_info.SetIsUsed ();
 
-                       VerifyDefiniteAssignment (ec);
-
                        DoResolveBase (ec);
                        return this;
                }
@@ -5721,8 +5742,6 @@ namespace Mono.CSharp
                                        }
                                        ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
                                }
-                       } else if (VariableInfo != null) {
-                               VariableInfo.SetAssigned (ec);
                        }
 
                        if (eclass == ExprClass.Unresolved)
@@ -5842,15 +5861,6 @@ namespace Mono.CSharp
                        Parameter.HasAddressTaken = true;
                }
 
-               void SetAssigned (ResolveContext ec)
-               {
-                       if (Parameter.HoistedVariant != null)
-                               Parameter.HoistedVariant.IsAssigned = true;
-
-                       if (HasOutModifier && ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetAssigned (VariableInfo);
-               }
-
                bool DoResolveBase (ResolveContext ec)
                {
                        if (eclass != ExprClass.Unresolved)
@@ -5916,7 +5926,6 @@ namespace Mono.CSharp
                        if (!DoResolveBase (ec))
                                return null;
 
-                       VerifyDefiniteAssignment (ec);
                        return this;
                }
 
@@ -5925,21 +5934,23 @@ namespace Mono.CSharp
                        if (!DoResolveBase (ec))
                                return null;
 
-                       SetAssigned (ec);
+                       if (Parameter.HoistedVariant != null)
+                               Parameter.HoistedVariant.IsAssigned = true;
+
                        return base.DoResolveLValue (ec, right_side);
                }
 
-               public override void VerifyDefiniteAssignment (ResolveContext rc)
+               public override void FlowAnalysis (FlowAnalysisContext fc)
                {
                        VariableInfo variable_info = VariableInfo;
                        if (variable_info == null)
                                return;
 
-                       if (variable_info.IsAssigned (rc))
+                       if (fc.IsDefinitelyAssigned (variable_info))
                                return;
 
-                       rc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
-                       variable_info.SetAssigned (rc);
+                       fc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
+                       fc.SetVariableAssigned (variable_info);
                }
        }
        
@@ -6203,6 +6214,14 @@ namespace Mono.CSharp
                        return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       mg.FlowAnalysis (fc);
+
+                       if (arguments != null)
+                               arguments.FlowAnalysis (fc);
+               }
+
                public override string GetSignatureForError ()
                {
                        return mg.GetSignatureForError ();
@@ -6628,6 +6647,12 @@ namespace Mono.CSharp
                                ec.Emit (OpCodes.Pop);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (arguments != null)
+                               arguments.FlowAnalysis (fc);
+               }
+
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        EmitAddressOf (ec, mode);
@@ -6788,6 +6813,11 @@ namespace Mono.CSharp
                {
                        throw new InternalErrorException ("Missing Resolve call");
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       throw new InternalErrorException ("Missing Resolve call");
+               }
                
                public override object Accept (StructuralVisitor visitor)
                {
@@ -7049,6 +7079,17 @@ namespace Mono.CSharp
                        ec.Report.Error (248, loc, "Cannot create an array with a negative size");
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       foreach (var arg in arguments)
+                               arg.FlowAnalysis (fc);
+
+                       if (array_data != null) {
+                               foreach (var ad in array_data)
+                                       ad.FlowAnalysis (fc);
+                       }
+               }
+
                bool InitializersContainAwait ()
                {
                        if (array_data == null)
@@ -7693,7 +7734,7 @@ namespace Mono.CSharp
 
                #endregion
 
-               public void CheckStructThisDefiniteAssignment (ResolveContext rc)
+               void CheckStructThisDefiniteAssignment (FlowAnalysisContext fc)
                {
                        //
                        // It's null for all cases when we don't need to check `this'
@@ -7702,13 +7743,10 @@ namespace Mono.CSharp
                        if (variable_info == null)
                                return;
 
-                       if (rc.OmitStructFlowAnalysis)
+                       if (fc.IsDefinitelyAssigned (variable_info))
                                return;
 
-                       if (!variable_info.IsAssigned (rc)) {
-                               rc.Report.Error (188, loc,
-                                       "The `this' object cannot be used before all of its fields are assigned to");
-                       }
+                       fc.Report.Error (188, loc, "The `this' object cannot be used before all of its fields are assigned to");
                }
 
                protected virtual void Error_ThisNotAvailable (ResolveContext ec)
@@ -7724,6 +7762,11 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       CheckStructThisDefiniteAssignment (fc);
+               }
+
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
                {
                        if (ae == null)
@@ -7781,9 +7824,6 @@ namespace Mono.CSharp
                protected override Expression DoResolve (ResolveContext ec)
                {
                        ResolveBase (ec);
-
-                       CheckStructThisDefiniteAssignment (ec);
-
                        return this;
                }
 
@@ -7792,9 +7832,6 @@ namespace Mono.CSharp
                        if (eclass == ExprClass.Unresolved)
                                ResolveBase (ec);
 
-                       if (variable_info != null)
-                               variable_info.SetAssigned (ec);
-
                        if (type.IsClass){
                                if (right_side == EmptyExpression.UnaryAddress)
                                        ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
@@ -7830,10 +7867,6 @@ namespace Mono.CSharp
                {
                        // Nothing
                }
-
-               public override void VerifyDefiniteAssignment (ResolveContext rc)
-               {
-               }
                
                public override object Accept (StructuralVisitor visitor)
                {
@@ -8616,50 +8649,25 @@ namespace Mono.CSharp
 
                protected override Expression DoResolve (ResolveContext rc)
                {
-                       var e = DoResolveName (rc, null);
-
-                       if (!rc.OmitStructFlowAnalysis) {
-                               var fe = e as FieldExpr;
-                               if (fe != null) {
-                                       fe.VerifyAssignedStructField (rc, null);
-                               }
-                       }
+                       var e = LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess);
+                       if (e != null)
+                               e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
 
                        return e;
                }
 
                public override Expression DoResolveLValue (ResolveContext rc, Expression rhs)
                {
-                       var e = DoResolveName (rc, rhs);
-
-                       if (!rc.OmitStructFlowAnalysis) {
-                               var fe = e as FieldExpr;
-                               if (fe != null && fe.InstanceExpression is FieldExpr) {
-                                       fe = (FieldExpr) fe.InstanceExpression;
-                                       fe.VerifyAssignedStructField (rc, rhs);
-                               }
-                       }
-
-                       return e;
-               }
+                       var e = LookupNameExpression (rc, MemberLookupRestrictions.None);
 
-               Expression DoResolveName (ResolveContext rc, Expression right_side)
-               {
-                       Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
-                       if (e == null)
+                       if (e is TypeExpr) {
+                               e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
                                return null;
-
-                       if (right_side != null) {
-                               if (e is TypeExpr) {
-                                       e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
-                                       return null;
-                               }
-
-                               e = e.ResolveLValue (rc, right_side);
-                       } else {
-                               e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
                        }
 
+                       if (e != null)
+                               e = e.ResolveLValue (rc, rhs);
+
                        return e;
                }
 
@@ -8684,32 +8692,22 @@ namespace Mono.CSharp
                        var sn = expr as SimpleName;
                        const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
 
-                       //
-                       // Resolve the expression with flow analysis turned off, we'll do the definite
-                       // assignment checks later.  This is because we don't know yet what the expression
-                       // will resolve to - it may resolve to a FieldExpr and in this case we must do the
-                       // definite assignment check on the actual field and not on the whole struct.
-                       //
-                       using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
-                               if (sn != null) {
-                                       expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+                       if (sn != null) {
+                               expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
 
-                                       //
-                                       // Resolve expression which does have type set as we need expression type
-                                       // with disable flow analysis as we don't know whether left side expression
-                                       // is used as variable or type
-                                       //
-                                       if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
-                                               using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
-                                                       expr = expr.Resolve (rc);
-                                               }
-                                       } else if (expr is TypeParameterExpr) {
-                                               expr.Error_UnexpectedKind (rc, flags, sn.Location);
-                                               expr = null;
-                                       }
-                               } else {
-                                       expr = expr.Resolve (rc, flags);
+                               //
+                               // Resolve expression which does have type set as we need expression type
+                               // with disable flow analysis as we don't know whether left side expression
+                               // is used as variable or type
+                               //
+                               if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+                                       expr = expr.Resolve (rc);
+                               } else if (expr is TypeParameterExpr) {
+                                       expr.Error_UnexpectedKind (rc, flags, sn.Location);
+                                       expr = null;
                                }
+                       } else {
+                               expr = expr.Resolve (rc, flags);
                        }
 
                        if (expr == null)
@@ -8737,16 +8735,6 @@ namespace Mono.CSharp
                                if (me != null)
                                        me.ResolveInstanceExpression (rc, null);
 
-                               //
-                               // Run defined assigned checks on expressions resolved with
-                               // disabled flow-analysis
-                               //
-                               if (sn != null) {
-                                       var vr = expr as VariableReference;
-                                       if (vr != null)
-                                               vr.VerifyDefiniteAssignment (rc);
-                               }
-
                                Arguments args = new Arguments (1);
                                args.Add (new Argument (expr));
                                return new DynamicMemberBinder (Name, args, loc);
@@ -8777,16 +8765,6 @@ namespace Mono.CSharp
                                                                emg.SetTypeArguments (rc, targs);
                                                        }
 
-                                                       //
-                                                       // Run defined assigned checks on expressions resolved with
-                                                       // disabled flow-analysis
-                                                       //
-                                                       if (sn != null && !errorMode) {
-                                                               var vr = expr as VariableReference;
-                                                               if (vr != null)
-                                                                       vr.VerifyDefiniteAssignment (rc);
-                                                       }
-
                                                        // TODO: it should really skip the checks bellow
                                                        return emg.Resolve (rc);
                                                }
@@ -8859,16 +8837,6 @@ namespace Mono.CSharp
                                me.SetTypeArguments (rc, targs);
                        }
 
-                       //
-                       // Run defined assigned checks on expressions resolved with
-                       // disabled flow-analysis
-                       //
-                       if (sn != null && !(me is FieldExpr && TypeSpec.IsValueType (expr_type))) {
-                               var vr = expr as VariableReference;
-                               if (vr != null)
-                                       vr.VerifyDefiniteAssignment (rc);
-                       }
-
                        return me;
                }
 
@@ -9081,6 +9049,11 @@ namespace Mono.CSharp
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Expr.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        using (ctx.With (BuilderContext.Options.CheckedScope, true)) {
@@ -9153,6 +9126,11 @@ namespace Mono.CSharp
                                Expr.EmitBranchable (ec, target, on_true);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Expr.FlowAnalysis (fc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        UnCheckedExpr target = (UnCheckedExpr) t;
@@ -9291,6 +9269,12 @@ namespace Mono.CSharp
                        Report.Error (1742, na.Location, "An element access expression cannot use named argument");
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Expr.FlowAnalysis (fc);
+                       Arguments.FlowAnalysis (fc);
+               }
+
                public override string GetSignatureForError ()
                {
                        return Expr.GetSignatureForError ();
@@ -9393,6 +9377,11 @@ namespace Mono.CSharp
                        ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       ea.FlowAnalysis (fc);
+               }
+
                //
                // Load the array arguments into the stack.
                //
@@ -9690,6 +9679,13 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       // TODO: Check the order
+                       base.FlowAnalysis (fc);
+                       arguments.FlowAnalysis (fc);
+               }
+
                public override string GetSignatureForError ()
                {
                        return best_candidate.GetSignatureForError ();
@@ -10100,6 +10096,11 @@ namespace Mono.CSharp
                        ec.Emit (OpCodes.Call, method);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       source.FlowAnalysis (fc);
+               }
+
                public override string GetSignatureForError ()
                {
                        return TypeManager.CSharpSignature (method);
@@ -10801,6 +10802,12 @@ namespace Mono.CSharp
                                e.EmitStatement (ec);
                        }
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       foreach (var initializer in initializers)
+                               initializer.FlowAnalysis (fc);
+               }
        }
        
        //
@@ -10995,6 +11002,12 @@ namespace Mono.CSharp
                        return instance;
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       base.FlowAnalysis (fc);
+                       initializers.FlowAnalysis (fc);
+               }
+
                public override object Accept (StructuralVisitor visitor)
                {
                        return visitor.Visit (this);
index 3e2b2c82dab33511775ee9740b9964bab188c3b2..4878341e3f8dee692015971435ab9ca9c17d35e4 100644 (file)
@@ -17,1055 +17,6 @@ using System.Collections.Generic;
 
 namespace Mono.CSharp
 {
-       // <summary>
-       //   A new instance of this class is created every time a new block is resolved
-       //   and if there's branching in the block's control flow.
-       // </summary>
-       public abstract class FlowBranching
-       {
-               // <summary>
-               //   The type of a FlowBranching.
-               // </summary>
-               public enum BranchingType : byte {
-                       // Normal (conditional or toplevel) block.
-                       Block,
-
-                       // Conditional.
-                       Conditional,
-
-                       // A loop block.
-                       Loop,
-
-                       // The statement embedded inside a loop
-                       Embedded,
-
-                       // part of a block headed by a jump target
-                       Labeled,
-
-                       // TryCatch block.
-                       TryCatch,
-
-                       // TryFinally, Using, Lock, CollectionForeach
-                       Exception,
-
-                       // Switch block.
-                       Switch,
-
-                       // The toplevel block of a function
-                       Toplevel,
-
-                       // An iterator block
-                       Iterator
-               }
-
-               // <summary>
-               //   The type of one sibling of a branching.
-               // </summary>
-               public enum SiblingType : byte {
-                       Block,
-                       Conditional,
-                       SwitchSection,
-                       Try,
-                       Catch,
-                       Finally
-               }
-
-               public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc)
-               {
-                       switch (type) {
-                       case BranchingType.Exception:
-                       case BranchingType.Labeled:
-                       case BranchingType.Toplevel:
-                       case BranchingType.TryCatch:
-                               throw new InvalidOperationException ();
-
-                       case BranchingType.Switch:
-                               return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc);
-
-                       case BranchingType.Block:
-                               return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
-
-                       case BranchingType.Loop:
-                               return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc);
-
-                       case BranchingType.Embedded:
-                               return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc);
-
-                       default:
-                               return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc);
-                       }
-               }
-
-               // <summary>
-               //   The type of this flow branching.
-               // </summary>
-               public readonly BranchingType Type;
-
-               // <summary>
-               //   The block this branching is contained in.  This may be null if it's not
-               //   a top-level block and it doesn't declare any local variables.
-               // </summary>
-               public readonly Block Block;
-
-               // <summary>
-               //   The parent of this branching or null if this is the top-block.
-               // </summary>
-               public readonly FlowBranching Parent;
-
-               // <summary>
-               //   Start-Location of this flow branching.
-               // </summary>
-               public readonly Location Location;
-
-               static int next_id;
-               int id;
-
-               // <summary>
-               //   The vector contains a BitArray with information about which local variables
-               //   and parameters are already initialized at the current code position.
-               // </summary>
-               public class UsageVector {
-                       // <summary>
-                       //   The type of this branching.
-                       // </summary>
-                       public readonly SiblingType Type;
-
-                       // <summary>
-                       //   Start location of this branching.
-                       // </summary>
-                       public Location Location;
-
-                       // <summary>
-                       //   This is only valid for SwitchSection, Try, Catch and Finally.
-                       // </summary>
-                       public readonly Block Block;
-
-                       // <summary>
-                       //   The number of locals in this block.
-                       // </summary>
-                       public readonly int CountLocals;
-
-                       // <summary>
-                       //   If not null, then we inherit our state from this vector and do a
-                       //   copy-on-write.  If null, then we're the first sibling in a top-level
-                       //   block and inherit from the empty vector.
-                       // </summary>
-                       public readonly UsageVector InheritsFrom;
-
-                       // <summary>
-                       //   This is used to construct a list of UsageVector's.
-                       // </summary>
-                       public UsageVector Next;
-
-                       //
-                       // Private.
-                       //
-                       MyBitVector locals;
-                       bool is_unreachable;
-
-                       static int next_id;
-                       int id;
-
-                       //
-                       // Normally, you should not use any of these constructors.
-                       //
-                       public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals)
-                       {
-                               this.Type = type;
-                               this.Block = block;
-                               this.Location = loc;
-                               this.InheritsFrom = parent;
-                               this.CountLocals = num_locals;
-
-                               locals = num_locals == 0 
-                                       ? MyBitVector.Empty
-                                       : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals);
-
-                               if (parent != null)
-                                       is_unreachable = parent.is_unreachable;
-
-                               id = ++next_id;
-
-                       }
-
-                       public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc)
-                               : this (type, parent, block, loc, parent.CountLocals)
-                       { }
-
-                       private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc)
-                       {
-                               this.Type = SiblingType.Block;
-                               this.Location = loc;
-                               this.Block = block;
-
-                               this.is_unreachable = is_unreachable;
-
-                               this.locals = locals;
-
-                               id = ++next_id;
-
-                       }
-
-                       // <summary>
-                       //   This does a deep copy of the usage vector.
-                       // </summary>
-                       public UsageVector Clone ()
-                       {
-                               UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals);
-
-                               retval.locals = locals.Clone ();
-                               retval.is_unreachable = is_unreachable;
-
-                               return retval;
-                       }
-
-                       public bool IsAssigned (VariableInfo var, bool ignoreReachability)
-                       {
-                               if (!ignoreReachability && !var.IsParameter && IsUnreachable)
-                                       return true;
-
-                               return var.IsAssigned (locals);
-                       }
-
-                       public void SetAssigned (VariableInfo var)
-                       {
-                               if (!var.IsParameter && IsUnreachable)
-                                       return;
-
-                               var.SetAssigned (locals);
-                       }
-
-                       public bool IsFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (/*!var.IsParameter &&*/ IsUnreachable)
-                                       return true;
-
-                               return var.IsStructFieldAssigned (locals, name);
-                       }
-
-                       public void SetFieldAssigned (VariableInfo var, string name)
-                       {
-                               if (/*!var.IsParameter &&*/ IsUnreachable)
-                                       return;
-
-                               var.SetStructFieldAssigned (locals, name);
-                       }
-
-                       public bool IsUnreachable {
-                               get {
-                                       return is_unreachable;
-                               }
-                               set {
-                                       is_unreachable = value;
-                               }
-                       }
-
-                       public void ResetBarrier ()
-                       {
-                               is_unreachable = false;
-                       }
-
-                       public void Goto ()
-                       {
-                               is_unreachable = true;
-                       }
-
-                       public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc)
-                       {
-                               if (sibling_list.Next == null)
-                                       return sibling_list;
-
-                               MyBitVector locals = null;
-                               bool is_unreachable = sibling_list.is_unreachable;
-
-                               if (!sibling_list.IsUnreachable)
-                                       locals &= sibling_list.locals;
-
-                               for (UsageVector child = sibling_list.Next; child != null; child = child.Next) {
-                                       is_unreachable &= child.is_unreachable;
-
-                                       if (!child.IsUnreachable)
-                                               locals &= child.locals;
-                               }
-
-                               return new UsageVector (locals, is_unreachable, null, loc);
-                       }
-
-                       // <summary>
-                       //   Merges a child branching.
-                       // </summary>
-                       public UsageVector MergeChild (UsageVector child, bool overwrite)
-                       {
-                               Report.Debug (2, "    MERGING CHILD EFFECTS", this, child, Type);
-
-                               bool new_isunr = child.is_unreachable;
-
-                               //
-                               // We've now either reached the point after the branching or we will
-                               // never get there since we always return or always throw an exception.
-                               //
-                               // If we can reach the point after the branching, mark all locals and
-                               // parameters as initialized which have been initialized in all branches
-                               // we need to look at (see above).
-                               //
-
-                               if ((Type == SiblingType.SwitchSection) && !new_isunr) {
-                                       Report.Error (163, Location,
-                                                     "Control cannot fall through from one " +
-                                                     "case label to another");
-                                       return child;
-                               }
-
-                               locals |= child.locals;
-
-                               // throw away un-necessary information about variables in child blocks
-                               if (locals.Count != CountLocals)
-                                       locals = new MyBitVector (locals, CountLocals);
-
-                               if (overwrite)
-                                       is_unreachable = new_isunr;
-                               else
-                                       is_unreachable |= new_isunr;
-
-                               return child;
-                       }
-
-                       public void MergeOrigins (UsageVector o_vectors)
-                       {
-                               Report.Debug (1, "  MERGING BREAK ORIGINS", this);
-
-                               if (o_vectors == null)
-                                       return;
-
-                               if (IsUnreachable && locals != null)
-                                       locals.SetAll (true);
-
-                               for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) {
-                                       Report.Debug (1, "    MERGING BREAK ORIGIN", vector);
-                                       if (vector.IsUnreachable)
-                                               continue;
-                                       locals &= vector.locals;
-                                       is_unreachable &= vector.is_unreachable;
-                               }
-
-                               Report.Debug (1, "  MERGING BREAK ORIGINS DONE", this);
-                       }
-
-                       //
-                       // Debugging stuff.
-                       //
-
-                       public override string ToString ()
-                       {
-                               return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals);
-                       }
-               }
-
-               // <summary>
-               //   Creates a new flow branching which is contained in `parent'.
-               //   You should only pass non-null for the `block' argument if this block
-               //   introduces any new variables - in this case, we need to create a new
-               //   usage vector with a different size than our parent's one.
-               // </summary>
-               protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype,
-                                        Block block, Location loc)
-               {
-                       Parent = parent;
-                       Block = block;
-                       Location = loc;
-                       Type = type;
-                       id = ++next_id;
-
-                       UsageVector vector;
-                       if (Block != null) {
-                               UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
-                               vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots);
-                       } else {
-                               vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc);
-                       }
-
-                       AddSibling (vector);
-               }
-
-               public abstract UsageVector CurrentUsageVector {
-                       get;
-               }                               
-
-               // <summary>
-               //   Creates a sibling of the current usage vector.
-               // </summary>
-               public void CreateSibling (Block block, SiblingType type)
-               {
-                       UsageVector vector = new UsageVector (
-                               type, Parent.CurrentUsageVector, block, Location);
-                       AddSibling (vector);
-
-                       Report.Debug (1, "  CREATED SIBLING", CurrentUsageVector);
-               }
-
-               public void CreateSibling ()
-               {
-                       CreateSibling (null, SiblingType.Conditional);
-               }
-
-               protected abstract void AddSibling (UsageVector uv);
-
-               protected abstract UsageVector Merge ();
-
-               public UsageVector MergeChild (FlowBranching child)
-               {
-                       return CurrentUsageVector.MergeChild (child.Merge (), true);
-               }
-
-               public virtual bool CheckRethrow (Location loc)
-               {
-                       return Parent.CheckRethrow (loc);
-               }
-
-               public virtual bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       return Parent.AddResumePoint (stmt, current, out pc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       return Parent.AddBreakOrigin (vector, loc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       return Parent.AddContinueOrigin (vector, loc);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
-               {
-                       return Parent.AddReturnOrigin (vector, stmt);
-               }
-
-               // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
-               public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       return Parent.AddGotoOrigin (vector, goto_stmt);
-               }
-
-               public bool IsAssigned (VariableInfo vi)
-               {
-                       return CurrentUsageVector.IsAssigned (vi, false);
-               }
-
-               public bool IsStructFieldAssigned (VariableInfo vi, string field_name)
-               {
-                       return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name);
-               }
-
-               protected static Report Report {
-                       get { return RootContext.ToplevelTypes.Compiler.Report; }
-               }
-
-               public void SetAssigned (VariableInfo vi)
-               {
-                       CurrentUsageVector.SetAssigned (vi);
-               }
-
-               public void SetFieldAssigned (VariableInfo vi, string name)
-               {
-                       CurrentUsageVector.SetFieldAssigned (vi, name);
-               }
-
-#if DEBUG
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ();
-                       sb.Append (GetType ());
-                       sb.Append (" (");
-
-                       sb.Append (id);
-                       sb.Append (",");
-                       sb.Append (Type);
-                       if (Block != null) {
-                               sb.Append (" - ");
-                               sb.Append (Block.ID);
-                               sb.Append (" - ");
-                               sb.Append (Block.StartLocation);
-                       }
-                       sb.Append (" - ");
-                       // sb.Append (Siblings.Length);
-                       // sb.Append (" - ");
-                       sb.Append (CurrentUsageVector);
-                       sb.Append (")");
-                       return sb.ToString ();
-               }
-#endif
-
-               public string Name {
-                       get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); }
-               }
-       }
-
-       public class FlowBranchingBlock : FlowBranching
-       {
-               UsageVector sibling_list = null;
-
-               public FlowBranchingBlock (FlowBranching parent, BranchingType type,
-                                          SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override UsageVector CurrentUsageVector {
-                       get { return sibling_list; }
-               }
-
-               protected override void AddSibling (UsageVector sibling)
-               {
-                       if (sibling_list != null && sibling_list.Type == SiblingType.Block)
-                               throw new InternalErrorException ("Blocks don't have sibling flow paths");
-                       sibling.Next = sibling_list;
-                       sibling_list = sibling;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target);
-                       if (stmt == null)
-                               return Parent.AddGotoOrigin (vector, goto_stmt);
-
-                       // forward jump
-                       goto_stmt.SetResolvedTarget (stmt);
-                       stmt.AddUsageVector (vector);
-                       return false;
-               }
-               
-               public static void Error_UnknownLabel (Location loc, string label, Report Report)
-               {
-                       Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
-                               label);
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       Report.Debug (2, "  MERGING SIBLINGS", Name);
-                       UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location);
-                       Report.Debug (2, "  MERGING SIBLINGS DONE", Name, vector);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingBreakable : FlowBranchingBlock
-       {
-               UsageVector break_origins;
-
-               public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       vector = vector.Clone ();
-                       vector.Next = break_origins;
-                       break_origins = vector;
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-                       vector.MergeOrigins (break_origins);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingContinuable : FlowBranchingBlock
-       {
-               UsageVector continue_origins;
-
-               public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
-                       : base (parent, type, stype, block, loc)
-               { }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       vector = vector.Clone ();
-                       vector.Next = continue_origins;
-                       continue_origins = vector;
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-                       vector.MergeOrigins (continue_origins);
-                       return vector;
-               }
-       }
-
-       public class FlowBranchingLabeled : FlowBranchingBlock
-       {
-               LabeledStatement stmt;
-               UsageVector actual;
-
-               public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt)
-                       : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc)
-               {
-                       this.stmt = stmt;
-                       CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
-                       actual = CurrentUsageVector.Clone ();
-
-                       // stand-in for backward jumps
-                       CurrentUsageVector.ResetBarrier ();
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       if (goto_stmt.Target != stmt.Name)
-                               return Parent.AddGotoOrigin (vector, goto_stmt);
-
-                       // backward jump
-                       goto_stmt.SetResolvedTarget (stmt);
-                       actual.MergeOrigins (vector.Clone ());
-
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = base.Merge ();
-
-                       if (actual.IsUnreachable)
-                               Report.Warning (162, 2, stmt.loc, "Unreachable code detected");
-
-                       actual.MergeChild (vector, false);
-                       return actual;
-               }
-       }
-
-       public class FlowBranchingIterator : FlowBranchingBlock
-       {
-               readonly Iterator iterator;
-
-               public FlowBranchingIterator (FlowBranching parent, Iterator iterator)
-                       : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location)
-               {
-                       this.iterator = iterator;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       pc = iterator.AddResumePoint (current);
-                       return false;
-               }
-       }
-
-       public class FlowBranchingToplevel : FlowBranchingBlock
-       {
-               UsageVector return_origins;
-
-               public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt)
-                       : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc)
-               {
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause");
-                       return false;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       throw new InternalErrorException ("A yield in a non-iterator block");
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Report.Error (139, loc, "No enclosing loop out of which to break or continue");
-                       return false;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Report.Error (139, loc, "No enclosing loop out of which to break or continue");
-                       return false;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
-               {
-                       vector = vector.Clone ();
-                       vector.Location = stmt.loc;
-                       vector.Next = return_origins;
-                       return_origins = vector;
-                       return false;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       string name = goto_stmt.Target;
-                       LabeledStatement s = Block.LookupLabel (name);
-                       if (s != null)
-                               throw new InternalErrorException ("Shouldn't get here");
-
-                       if (Parent == null) {
-                               Error_UnknownLabel (goto_stmt.loc, name, Report);
-                               return false;
-                       }
-
-                       int errors = Report.Errors;
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       if (errors == Report.Errors)
-                               Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method");
-                       return false;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       for (UsageVector origin = return_origins; origin != null; origin = origin.Next)
-                               Block.ParametersBlock.CheckOutParameters (origin);
-
-                       UsageVector vector = base.Merge ();
-                       Block.ParametersBlock.CheckOutParameters (vector);
-                       // Note: we _do_not_ merge in the return origins
-                       return vector;
-               }
-
-               public bool End ()
-               {
-                       return Merge ().IsUnreachable;
-               }
-       }
-
-       public class FlowBranchingTryCatch : FlowBranchingBlock
-       {
-               readonly TryCatch tc;
-
-               public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt)
-                       : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc)
-               {
-                       this.tc = stmt;
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       int errors = Report.Errors;
-                       Parent.AddResumePoint (stmt, tc.IsTryCatchFinally ? current : 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 (current, pc);
-                                       }
-                               } else {
-                                       if (CurrentUsageVector.Next == null)
-                                               Report.Error (1626, stmt.loc, "Cannot yield a value in the body of a try block with a catch clause");
-                                       else
-                                               Report.Error (1631, stmt.loc, "Cannot yield a value in the body of a catch clause");
-                               }
-                       }
-
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddBreakOrigin (vector, loc);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddContinueOrigin (vector, loc);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       Parent.AddReturnOrigin (vector, exit_stmt);
-                       tc.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       return true;
-               }
-       }
-
-       public class FlowBranchingAsync : FlowBranchingBlock
-       {
-               readonly AsyncInitializer async_init;
-
-               public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init)
-                       : base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location)
-               {
-                       this.async_init = async_init;
-               }
-/*
-               public override bool CheckRethrow (Location loc)
-               {
-                       return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
-               }
-*/
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       pc = async_init.AddResumePoint (current);
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddBreakOrigin (vector, loc);
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       Parent.AddContinueOrigin (vector, loc);
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       Parent.AddReturnOrigin (vector, exit_stmt);
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       Parent.AddGotoOrigin (vector, goto_stmt);
-                       return true;
-               }
-       }
-
-       public class FlowBranchingTryFinally : FlowBranching
-       {
-               ExceptionStatement stmt;
-               UsageVector current_vector;
-               UsageVector try_vector;
-               UsageVector finally_vector;
-
-               abstract class SavedOrigin {
-                       public readonly SavedOrigin Next;
-                       public readonly UsageVector Vector;
-
-                       protected SavedOrigin (SavedOrigin next, UsageVector vector)
-                       {
-                               Next = next;
-                               Vector = vector.Clone ();
-                       }
-
-                       protected abstract void DoPropagateFinally (FlowBranching parent);
-                       public void PropagateFinally (UsageVector finally_vector, FlowBranching parent)
-                       {
-                               if (finally_vector != null)
-                                       Vector.MergeChild (finally_vector, false);
-                               DoPropagateFinally (parent);
-                       }
-               }
-
-               class BreakOrigin : SavedOrigin {
-                       Location Loc;
-                       public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc)
-                               : base (next, vector)
-                       {
-                               Loc = loc;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddBreakOrigin (Vector, Loc);
-                       }
-               }
-
-               class ContinueOrigin : SavedOrigin {
-                       Location Loc;
-                       public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc)
-                               : base (next, vector)
-                       {
-                               Loc = loc;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddContinueOrigin (Vector, Loc);
-                       }
-               }
-
-               class ReturnOrigin : SavedOrigin {
-                       public ExitStatement Stmt;
-
-                       public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt)
-                               : base (next, vector)
-                       {
-                               Stmt = stmt;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddReturnOrigin (Vector, Stmt);
-                       }
-               }
-
-               class GotoOrigin : SavedOrigin {
-                       public Goto Stmt;
-
-                       public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt)
-                               : base (next, vector)
-                       {
-                               Stmt = stmt;
-                       }
-
-                       protected override void DoPropagateFinally (FlowBranching parent)
-                       {
-                               parent.AddGotoOrigin (Vector, Stmt);
-                       }
-               }
-
-               SavedOrigin saved_origins;
-
-               public FlowBranchingTryFinally (FlowBranching parent,
-                                              ExceptionStatement stmt)
-                       : base (parent, BranchingType.Exception, SiblingType.Try,
-                               null, stmt.loc)
-               {
-                       this.stmt = stmt;
-               }
-
-               protected override void AddSibling (UsageVector sibling)
-               {
-                       switch (sibling.Type) {
-                       case SiblingType.Try:
-                               try_vector = sibling;
-                               break;
-                       case SiblingType.Finally:
-                               finally_vector = sibling;
-                               break;
-                       default:
-                               throw new InvalidOperationException ();
-                       }
-                       current_vector = sibling;
-               }
-
-               public override UsageVector CurrentUsageVector {
-                       get { return current_vector; }
-               }
-
-               public override bool CheckRethrow (Location loc)
-               {
-                       if (!Parent.CheckRethrow (loc))
-                               return false;
-                       if (finally_vector == null)
-                               return true;
-                       Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause");
-                       return false;
-               }
-
-               public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
-               {
-                       int errors = Report.Errors;
-                       Parent.AddResumePoint (stmt, this.stmt, out pc);
-                       if (errors == Report.Errors) {
-                               if (finally_vector == null)
-                                       this.stmt.AddResumePoint (current, pc);
-                               else {
-                                       if (stmt is AwaitStatement) {
-                                               Report.Error (1984, stmt.loc, "The `await' operator cannot be used in the body of a finally clause");
-                                       } else {
-                                               Report.Error (1625, stmt.loc, "Cannot yield in the body of a finally clause");
-                                       }
-                               }
-                       }
-                       return true;
-               }
-
-               public override bool AddBreakOrigin (UsageVector vector, Location loc)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddBreakOrigin (vector, loc);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new BreakOrigin (saved_origins, vector, loc);
-                       }
-
-                       // either the loop test or a back jump will follow code
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddContinueOrigin (UsageVector vector, Location loc)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddContinueOrigin (vector, loc);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new ContinueOrigin (saved_origins, vector, loc);
-                       }
-
-                       // either the loop test or a back jump will follow code
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
-               {
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddReturnOrigin (vector, exit_stmt);
-                               if (errors == Report.Errors)
-                                       exit_stmt.Error_FinallyClause (Report);
-                       } else {
-                               saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt);
-                       }
-
-                       // sets ec.NeedReturnLabel()
-                       stmt.SomeCodeFollows ();
-                       return true;
-               }
-
-               public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
-               {
-                       LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target);
-                       if (s != null)
-                               throw new InternalErrorException ("Shouldn't get here");
-
-                       if (finally_vector != null) {
-                               int errors = Report.Errors;
-                               Parent.AddGotoOrigin (vector, goto_stmt);
-                               if (errors == Report.Errors)
-                                       Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause");
-                       } else {
-                               saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt);
-                       }
-                       return true;
-               }
-
-               protected override UsageVector Merge ()
-               {
-                       UsageVector vector = try_vector.Clone ();
-
-                       if (finally_vector != null)
-                               vector.MergeChild (finally_vector, false);
-
-                       for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next)
-                               origin.PropagateFinally (finally_vector, Parent);
-
-                       return vector;
-               }
-       }
-
        // <summary>
        //   This is used by the flow analysis code to keep track of the type of local variables.
        //
@@ -1178,23 +129,22 @@ namespace Mono.CSharp
                //   A struct's constructor must always assign all fields.
                //   This method checks whether it actually does so.
                // </summary>
-               public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc)
+               public bool IsFullyInitialized (FlowAnalysisContext fc, VariableInfo vi, Location loc)
                {
                        if (struct_info == null)
                                return true;
 
                        bool ok = true;
-                       FlowBranching branching = ec.CurrentBranching;
                        for (int i = 0; i < struct_info.Count; i++) {
-                               var field = struct_info.Fields [i];
+                               var field = struct_info.Fields[i];
 
-                               if (!branching.IsStructFieldAssigned (vi, field.Name)) {
+                               if (!fc.IsStructFieldDefinitelyAssigned (vi, field.Name)) {
                                        if (field.MemberDefinition is Property.BackingField) {
-                                               ec.Report.Error (843, loc,
+                                               fc.Report.Error (843, loc,
                                                        "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer",
                                                        field.GetSignatureForError ());
                                        } else {
-                                               ec.Report.Error (171, loc,
+                                               fc.Report.Error (171, loc,
                                                        "Field `{0}' must be fully assigned before control leaves the constructor",
                                                        field.GetSignatureForError ());
                                        }
@@ -1401,12 +351,7 @@ namespace Mono.CSharp
                        return info;
                }
 
-               public bool IsAssigned (ResolveContext ec)
-               {
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
-               }
-
-               public bool IsAssigned (MyBitVector vector)
+               public bool IsAssigned (DefiniteAssignmentBitSet vector)
                {
                        if (vector == null)
                                return true;
@@ -1445,23 +390,18 @@ namespace Mono.CSharp
                                        return false;
                        }
                        
-                       vector [Offset] = true;
+                       vector.Set (Offset);
                        return true;
                }
 
                public bool IsEverAssigned { get; set; }
 
-               public bool IsStructFieldAssigned (ResolveContext ec, string name)
-               {
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsStructFieldAssigned (this, name);
-               }
-
-               public bool IsFullyInitialized (BlockContext bc, Location loc)
+               public bool IsFullyInitialized (FlowAnalysisContext fc, Location loc)
                {
-                       return TypeInfo.IsFullyInitialized (bc, this, loc);
+                       return TypeInfo.IsFullyInitialized (fc, this, loc);
                }
 
-               public bool IsStructFieldAssigned (MyBitVector vector, string field_name)
+               public bool IsStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
                {
                        int field_idx = TypeInfo.GetFieldIndex (field_name);
 
@@ -1471,31 +411,20 @@ namespace Mono.CSharp
                        return vector [Offset + field_idx];
                }
 
-               public void SetStructFieldAssigned (ResolveContext ec, string name)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetFieldAssigned (this, name);
-               }
-
-               public void SetAssigned (ResolveContext ec)
-               {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetAssigned (this);
-               }
-
-               public void SetAssigned (MyBitVector vector)
+               public void SetAssigned (DefiniteAssignmentBitSet vector, bool generatedAssignment)
                {
                        if (Length == 1)
-                               vector[Offset] = true;
+                               vector.Set (Offset);
                        else
-                               vector.SetRange (Offset, Length);
+                               vector.Set (Offset, Length);
 
-                       IsEverAssigned = true;
+                       if (!generatedAssignment)
+                               IsEverAssigned = true;
                }
 
-               public void SetStructFieldAssigned (MyBitVector vector, string field_name)
+               public void SetStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
                {
-                       if (vector[Offset])
+                       if (vector [Offset])
                                return;
 
                        int field_idx = TypeInfo.GetFieldIndex (field_name);
@@ -1505,15 +434,15 @@ namespace Mono.CSharp
 
                        var complex_field = TypeInfo.GetStructField (field_name);
                        if (complex_field != null) {
-                               vector.SetRange (Offset + complex_field.Offset, complex_field.TotalLength);
+                               vector.Set (Offset + complex_field.Offset, complex_field.TotalLength);
                        } else {
-                               vector[Offset + field_idx] = true;
+                               vector.Set (Offset + field_idx);
                        }
 
                        IsEverAssigned = true;
 
                        //
-                       // Each field must be assigned
+                       // Each field must be assigned before setting master bit
                        //
                        for (int i = Offset + 1; i < TypeInfo.TotalLength + Offset; i++) {
                                if (!vector[i])
@@ -1524,7 +453,7 @@ namespace Mono.CSharp
                        // Set master struct flag to assigned when all tested struct
                        // fields have been assigned
                        //
-                       vector[Offset] = true;
+                       vector.Set (Offset);
                }
 
                public VariableInfo GetStructFieldInfo (string fieldName)
@@ -1539,274 +468,124 @@ namespace Mono.CSharp
 
                public override string ToString ()
                {
-                       return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
-                                             Name, TypeInfo, Offset, Length, IsParameter);
+                       return String.Format ("Name={0} Offset={1} Length={2} {3})", Name, Offset, Length, TypeInfo);
                }
        }
 
-       // <summary>
-       //   This is a special bit vector which can inherit from another bit vector doing a
-       //   copy-on-write strategy.  The inherited vector may have a smaller size than the
-       //   current one.
-       // </summary>
-       public class MyBitVector {
-               public readonly int Count;
-               public static readonly MyBitVector Empty = new MyBitVector ();
-
-               // Invariant: vector != null => vector.Count == Count
-               // Invariant: vector == null || shared == null
-               //            i.e., at most one of 'vector' and 'shared' can be non-null.  They can both be null -- that means all-ones
-               // The object in 'shared' cannot be modified, while 'vector' can be freely modified
-               System.Collections.BitArray vector, shared;
+       public struct Reachability
+       {
+               readonly bool unreachable;
 
-               MyBitVector ()
+               Reachability (bool unreachable)
                {
-                       shared = new System.Collections.BitArray (0, false);
+                       this.unreachable = unreachable;
                }
 
-               public MyBitVector (MyBitVector InheritsFrom, int Count)
-               {
-                       if (InheritsFrom != null)
-                               shared = InheritsFrom.MakeShared (Count);
-
-                       this.Count = Count;
+               public bool IsUnreachable {
+                       get {
+                               return unreachable;
+                       }
                }
 
-               System.Collections.BitArray MakeShared (int new_count)
+               public static Reachability CreateUnreachable ()
                {
-                       // Post-condition: vector == null
-
-                       // ensure we don't leak out dirty bits from the BitVector we inherited from
-                       if (new_count > Count &&
-                           ((shared != null && shared.Count > Count) ||
-                            (shared == null && vector == null)))
-                               initialize_vector ();
-
-                       if (vector != null) {
-                               shared = vector;
-                               vector = null;
-                       }
-
-                       return shared;
+                       return new Reachability (true);
                }
 
-               // <summary>
-               //   Get/set bit `index' in the bit vector.
-               // </summary>
-               public bool this [int index] {
-                       get {
-                               if (index >= Count)
-                                       // FIXME: Disabled due to missing anonymous method flow analysis
-                                       // throw new ArgumentOutOfRangeException ();
-                                       return true; 
-
-                               if (vector != null)
-                                       return vector [index];
-                               if (shared == null)
-                                       return true;
-                               if (index < shared.Count)
-                                       return shared [index];
-                               return false;
-                       }
-
-                       set {
-                               // Only copy the vector if we're actually modifying it.
-                               if (this [index] != value) {
-                                       if (vector == null)
-                                               initialize_vector ();
-                                       vector [index] = value;
-                               }
-                       }
+               public static Reachability operator & (Reachability a, Reachability b)
+               {
+                   return new Reachability (a.unreachable && b.unreachable);
                }
 
-               // <summary>
-               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
-               //   different size than the current one.
-               // </summary>
-               private MyBitVector Or (MyBitVector new_vector)
+               public static Reachability operator | (Reachability a, Reachability b)
                {
-                       if (Count == 0 || new_vector.Count == 0)
-                               return this;
-
-                       var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
-
-                       if (o == null) {
-                               int n = new_vector.Count;
-                               if (n < Count) {
-                                       for (int i = 0; i < n; ++i)
-                                               this [i] = true;
-                               } else {
-                                       SetAll (true);
-                               }
-                               return this;
-                       }
-
-                       if (Count == o.Count) {
-                               if (vector == null) {
-                                       if (shared == null)
-                                               return this;
-                                       initialize_vector ();
-                               }
-                               vector.Or (o);
-                               return this;
-                       }
+                       return new Reachability (a.unreachable | b.unreachable);
+               }
+       }
 
-                       int min = o.Count;
-                       if (Count < min)
-                               min = Count;
+       public class DefiniteAssignmentBitSet
+       {
+               // Make it
+               // int bits;
+               // int int[] bits_extended; // when bits overflows
 
-                       for (int i = 0; i < min; i++) {
-                               if (o [i])
-                                       this [i] = true;
-                       }
+               System.Collections.BitArray bits;
+               bool copy_on_write;
 
-                       return this;
+               public DefiniteAssignmentBitSet ()
+               {
+                       bits = new System.Collections.BitArray (4096); // TODO:
                }
 
-               // <summary>
-               //   Performs an `and' operation on the bit vector.  The `new_vector' may have
-               //   a different size than the current one.
-               // </summary>
-               private MyBitVector And (MyBitVector new_vector)
+               public DefiniteAssignmentBitSet (DefiniteAssignmentBitSet source)
                {
-                       if (Count == 0)
-                               return this;
-
-                       var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
-
-                       if (o == null) {
-                               for (int i = new_vector.Count; i < Count; ++i)
-                                       this [i] = false;
-                               return this;
-                       }
+                       bits = source.bits;
 
-                       if (o.Count == 0) {
-                               SetAll (false);
-                               return this;
-                       }
-
-                       if (Count == o.Count) {
-                               if (vector == null) {
-                                       if (shared == null) {
-                                               shared = new_vector.MakeShared (Count);
-                                               return this;
-                                       }
-                                       initialize_vector ();
-                               }
-                               vector.And (o);
-                               return this;
-                       }
-
-                       int min = o.Count;
-                       if (Count < min)
-                               min = Count;
-
-                       for (int i = 0; i < min; i++) {
-                               if (! o [i])
-                                       this [i] = false;
-                       }
-
-                       for (int i = min; i < Count; i++)
-                               this [i] = false;
-
-                       return this;
+                       copy_on_write = true;
                }
 
-               public static MyBitVector operator & (MyBitVector a, MyBitVector b)
+               private DefiniteAssignmentBitSet (System.Collections.BitArray bits)
                {
-                       if (a == b)
-                               return a;
-                       if (a == null)
-                               return b.Clone ();
-                       if (b == null)
-                               return a.Clone ();
-                       if (a.Count > b.Count)
-                               return a.Clone ().And (b);
-                       else
-                               return b.Clone ().And (a);                                      
+                       this.bits = bits;
                }
 
-               public static MyBitVector operator | (MyBitVector a, MyBitVector b)
+               public static DefiniteAssignmentBitSet operator & (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       if (a == b)
+                       if (a.bits == b.bits)
                                return a;
-                       if (a == null)
-                               return new MyBitVector (null, b.Count);
-                       if (b == null)
-                               return new MyBitVector (null, a.Count);
-                       if (a.Count > b.Count)
-                               return a.Clone ().Or (b);
-                       else
-                               return b.Clone ().Or (a);
+
+                       return new DefiniteAssignmentBitSet (a.bits.And (b.bits));
                }
 
-               public MyBitVector Clone ()
+               public static DefiniteAssignmentBitSet operator | (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
                {
-                       return Count == 0 ? Empty : new MyBitVector (this, Count);
+                       if (a.bits == b.bits)
+                               return a;
+
+                       return new DefiniteAssignmentBitSet (a.bits.Or (b.bits));
                }
 
-               public void SetRange (int offset, int length)
+               public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
                {
-                       if (offset > Count || offset + length > Count)
-                               throw new ArgumentOutOfRangeException ("flow-analysis");
+                       if (das.Count == 0)
+                               return new DefiniteAssignmentBitSet ();
 
-                       if (shared == null && vector == null)
-                               return;
-
-                       int i = 0;
-                       if (shared != null) {
-                               if (offset + length <= shared.Count) {
-                                       for (; i < length; ++i)
-                                               if (!shared [i+offset])
-                                                   break;
-                                       if (i == length)
-                                               return;
-                               }
-                               initialize_vector ();
+                       DefiniteAssignmentBitSet res = das [0];
+                       for (int i = 1; i < das.Count; ++i) {
+                               res &= das[i];
                        }
-                       for (; i < length; ++i)
-                               vector [i+offset] = true;
 
+                       return res;
                }
 
-               public void SetAll (bool value)
+               public void Set (int index)
                {
-                       // Don't clobber Empty
-                       if (Count == 0)
-                               return;
-                       shared = value ? null : Empty.MakeShared (Count);
-                       vector = null;
+                       if (copy_on_write && !bits[index])
+                               Clone ();
+
+                       bits[index] = true;
                }
 
-               void initialize_vector ()
+               public void Set (int index, int length)
                {
-                       // Post-condition: vector != null
-                       if (shared == null) {
-                               vector = new System.Collections.BitArray (Count, true);
-                               return;
-                       }
+                       for (int i = 0; i < length; ++i) {
+                               if (copy_on_write && !bits[index + i])
+                                       Clone ();
 
-                       vector = new System.Collections.BitArray (shared);
-                       if (Count != vector.Count)
-                               vector.Length = Count;
-                       shared = null;
-               }
+                               bits[index + i] = true;
+                       }
+               }
 
-               StringBuilder Dump (StringBuilder sb)
-               {
-                       var dump = vector == null ? shared : vector;
-                       if (dump == null)
-                               return sb.Append ("/");
-                       if (dump == shared)
-                               sb.Append ("=");
-                       for (int i = 0; i < dump.Count; i++)
-                               sb.Append (dump [i] ? "1" : "0");
-                       return sb;
+               public bool this [int index] {
+                       get {
+                               return bits [index];
+                       }
                }
 
-               public override string ToString ()
+               void Clone ()
                {
-                       return Dump (new StringBuilder ("{")).Append ("}").ToString ();
+                       bits = new System.Collections.BitArray (bits);
+                       copy_on_write = false;
                }
        }
 }
index 82ded9174c551a96a680ea7c2495cc9e9087b52c..4f2a3429713c45db806d83c5520e8cc2c76e183e 100644 (file)
@@ -29,6 +29,7 @@ namespace Mono.CSharp
                protected bool unwind_protect;
                protected T machine_initializer;
                int resume_pc;
+               ExceptionStatement inside_try_block;
 
                protected YieldStatement (Expression expr, Location l)
                {
@@ -51,6 +52,15 @@ namespace Mono.CSharp
                        machine_initializer.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+
+                       RegisterResumePoint ();
+
+                       return false;
+               }
+
                public override bool Resolve (BlockContext bc)
                {
                        expr = expr.Resolve (bc);
@@ -58,12 +68,20 @@ namespace Mono.CSharp
                                return false;
 
                        machine_initializer = bc.CurrentAnonymousMethod as T;
-
-                       if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
-                               unwind_protect = bc.CurrentBranching.AddResumePoint (this, this, out resume_pc);
-
+                       inside_try_block = bc.CurrentTryBlock;
                        return true;
                }
+
+               public void RegisterResumePoint ()
+               {
+                       if (inside_try_block == null) {
+                               resume_pc = machine_initializer.AddResumePoint (this);
+                       } else {
+                               resume_pc = inside_try_block.AddResumePoint (this, resume_pc, machine_initializer);
+                               unwind_protect = true;
+                               inside_try_block = null;
+                       }
+               }
        }
 
        public class Yield : YieldStatement<Iterator>
@@ -73,14 +91,19 @@ namespace Mono.CSharp
                {
                }
 
-               public static bool CheckContext (ResolveContext ec, Location loc)
+               public static bool CheckContext (BlockContext bc, Location loc)
                {
-                       if (!ec.CurrentAnonymousMethod.IsIterator) {
-                               ec.Report.Error (1621, loc,
+                       if (!bc.CurrentAnonymousMethod.IsIterator) {
+                               bc.Report.Error (1621, loc,
                                        "The yield statement cannot be used inside anonymous method blocks");
                                return false;
                        }
 
+                       if (bc.HasSet (ResolveContext.Options.FinallyScope)) {
+                               bc.Report.Error (1625, loc, "Cannot yield in the body of a finally clause");
+                               return false;
+                       }
+
                        return true;
                }
 
@@ -89,6 +112,14 @@ namespace Mono.CSharp
                        if (!CheckContext (bc, loc))
                                return false;
 
+                       if (bc.HasAny (ResolveContext.Options.TryWithCatchScope)) {
+                               bc.Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause");
+                       }
+
+                       if (bc.HasSet (ResolveContext.Options.CatchScope)) {
+                               bc.Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
+                       }
+
                        if (!base.Resolve (bc))
                                return false;
 
@@ -117,9 +148,10 @@ namespace Mono.CSharp
                        loc = l;
                }
 
-               public override void Error_FinallyClause (Report Report)
-               {
-                       Report.Error (1625, loc, "Cannot yield in the body of a finally clause");
+               protected override bool IsLocalExit {
+                       get {
+                               return false;
+                       }
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -127,16 +159,27 @@ namespace Mono.CSharp
                        throw new NotSupportedException ();
                }
 
-               protected override bool DoResolve (BlockContext ec)
+               protected override bool DoResolve (BlockContext bc)
                {
-                       iterator = ec.CurrentIterator;
-                       return Yield.CheckContext (ec, loc);
+                       iterator = bc.CurrentIterator;
+                       return Yield.CheckContext (bc, loc);
                }
 
                protected override void DoEmit (EmitContext ec)
                {
                        iterator.EmitYieldBreak (ec, unwind_protect);
                }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return true;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Reachability.CreateUnreachable ();
+               }
                
                public override object Accept (StructuralVisitor visitor)
                {
@@ -265,7 +308,6 @@ namespace Mono.CSharp
                                        if (new_storey != null)
                                                new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc);
 
-                                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                                        return true;
                                }
 
@@ -293,10 +335,21 @@ namespace Mono.CSharp
                                        new_storey.Emit (ec);
                                        ec.Emit (OpCodes.Ret);
                                }
+
+                               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public override Reachability MarkReachable (Reachability rc)
+                               {
+                                       base.MarkReachable (rc);
+                                       return Reachability.CreateUnreachable ();
+                               }
                        }
 
                        GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name)
-                               : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name)
+                               : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name, ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis)
                        {
                        }
 
@@ -310,7 +363,6 @@ namespace Mono.CSharp
                                var m = new GetEnumeratorMethod (host, returnType, name);
                                var stmt = statement ?? new GetEnumeratorStatement (host, m);
                                m.block.AddStatement (stmt);
-                               m.block.IsCompilerGenerated = true;
                                return m;
                        }
                }
@@ -342,16 +394,20 @@ namespace Mono.CSharp
                                        ec.CurrentAnonymousMethod = iterator;
                                        iterator.EmitDispose (ec);
                                }
+
+                               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                               {
+                                       throw new NotImplementedException ();
+                               }
                        }
 
                        public DisposeMethod (IteratorStorey host)
                                : base (host, null, new TypeExpression (host.Compiler.BuiltinTypes.Void, host.Location), Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
-                                       new MemberName ("Dispose", host.Location))
+                                       new MemberName ("Dispose", host.Location), ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis)
                        {
                                host.Members.Add (this);
 
                                Block.AddStatement (new DisposeMethodStatement (host.Iterator));
-                               Block.IsCompilerGenerated = true;
                        }
                }
 
@@ -546,9 +602,8 @@ namespace Mono.CSharp
 
                        var name = new MemberName ("Current", null, explicit_iface, Location);
 
-                       ToplevelBlock get_block = new ToplevelBlock (Compiler, Location) {
-                               IsCompilerGenerated = true
-                       };
+                       ToplevelBlock get_block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location,
+                               Block.Flags.CompilerGenerated | Block.Flags.NoFlowAnalysis);
                        get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location));
                                
                        Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN | Modifiers.COMPILER_GENERATED, name, null);
@@ -567,9 +622,8 @@ namespace Mono.CSharp
                                ParametersCompiled.EmptyReadOnlyParameters, null);
                        Members.Add (reset);
 
-                       reset.Block = new ToplevelBlock (Compiler, Location) {
-                               IsCompilerGenerated = true
-                       };
+                       reset.Block = new ToplevelBlock (Compiler, reset.ParameterInfo, Location,
+                               Block.Flags.CompilerGenerated | Block.Flags.NoFlowAnalysis);
 
                        TypeSpec ex_type = Module.PredefinedTypes.NotSupportedException.Resolve ();
                        if (ex_type == null)
@@ -590,12 +644,13 @@ namespace Mono.CSharp
        {
                readonly StateMachineInitializer expr;
 
-               public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType, Modifiers mod, MemberName name)
+               public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType,
+                       Modifiers mod, MemberName name, ToplevelBlock.Flags blockFlags)
                        : base (host, returnType, mod | Modifiers.COMPILER_GENERATED,
                          name, ParametersCompiled.EmptyReadOnlyParameters, null)
                {
                        this.expr = expr;
-                       Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
+                       Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null, blockFlags);
                }
 
                public override EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
@@ -642,6 +697,21 @@ namespace Mono.CSharp
                                // Don't create sequence point
                                DoEmit (ec);
                        }
+
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               return state_machine.ReturnType.Kind != MemberKind.Void;
+                       }
+
+                       public override Reachability MarkReachable (Reachability rc)
+                       {
+                               base.MarkReachable (rc);
+
+                               if (state_machine.ReturnType.Kind != MemberKind.Void)
+                                       rc = Reachability.CreateUnreachable ();
+
+                               return rc;
+                       }
                }
 
                public readonly TypeDefinition Host;
@@ -706,30 +776,27 @@ namespace Mono.CSharp
                        throw new NotSupportedException ("ET");
                }
 
-               protected virtual BlockContext CreateBlockContext (ResolveContext rc)
+               protected virtual BlockContext CreateBlockContext (BlockContext bc)
                {
-                       var ctx = new BlockContext (rc, block, ((BlockContext) rc).ReturnType);
+                       var ctx = new BlockContext (bc, block, bc.ReturnType);
                        ctx.CurrentAnonymousMethod = this;
+
+                       ctx.AssignmentInfoOffset = bc.AssignmentInfoOffset;
+                       ctx.EnclosingLoop = bc.EnclosingLoop;
+                       ctx.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch;
+                       ctx.Switch = bc.Switch;
+
                        return ctx;
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
                {
-                       var ctx = CreateBlockContext (ec);
+                       var ctx = CreateBlockContext ((BlockContext) rc);
 
                        Block.Resolve (ctx);
 
-                       //
-                       // Explicit return is required for Task<T> state machine
-                       //
-                       var task_storey = storey as AsyncTaskStorey;
-                       if (task_storey == null || (task_storey.ReturnType != null && !task_storey.ReturnType.IsGenericTask))
-                               ctx.CurrentBranching.CurrentUsageVector.Goto ();
-
-                       ctx.EndFlowBranching ();
-
-                       if (!ec.IsInProbingMode) {
-                               var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc));
+                       if (!rc.IsInProbingMode) {
+                               var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc), 0);
                                move_next.Block.AddStatement (new MoveNextBodyStatement (this));
                                storey.AddEntryMethod (move_next);
                        }
@@ -936,6 +1003,11 @@ namespace Mono.CSharp
                                throw new NotSupportedException ();
                        }
 
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               throw new NotSupportedException ();
+                       }
+
                        protected override void DoEmit (EmitContext ec)
                        {
                                //
@@ -985,8 +1057,8 @@ namespace Mono.CSharp
                                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 = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc,
+                               ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis);
                        method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
 
                        // Cannot it add to storey because it'd be emitted before nested
@@ -1097,13 +1169,6 @@ namespace Mono.CSharp
                        ec.MarkLabel (resume_point);
                }
 
-               protected override BlockContext CreateBlockContext (ResolveContext rc)
-               {
-                       var bc = base.CreateBlockContext (rc);
-                       bc.StartFlowBranching (this, rc.CurrentBranching);
-                       return bc;
-               }
-
                public static void CreateIterator (IMethodData method, TypeDefinition parent, Modifiers modifiers)
                {
                        bool is_enumerable;
index a1c5ab2f914f4bed7b7938ca2f1f93a4463c3d35..da339fa873deb3bbf4daf7ed4dadc7973a52d31a 100644 (file)
@@ -811,9 +811,8 @@ namespace Mono.CSharp.Linq
                }
 
                public QueryBlock (Block parent, Location start)
-                       : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start)
+                       : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start, Flags.CompilerGenerated)
                {
-                       flags |= Flags.CompilerGenerated;
                }
 
                public void AddRangeVariable (RangeVariable variable)
index 03568fa9230613951753346426259123f20e93b0..1ba33dafb7ba7ca406b4cc6198486d2866d6c061 100644 (file)
@@ -1498,6 +1498,12 @@ namespace Mono.CSharp {
                {
                        Emit (ec);
                }
+
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (argument_list != null)
+                               argument_list.FlowAnalysis (fc);
+               }
        }
 
        public class ConstructorBaseInitializer : ConstructorInitializer {
@@ -1742,7 +1748,7 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               if (block.Resolve (null, bc, this)) {
+                               if (block.Resolve (bc, this)) {
                                        debug_builder = Parent.CreateMethodSymbolEntry ();
                                        EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder);
                                        ec.With (EmitContext.Options.ConstructorScope, true);
@@ -2131,7 +2137,7 @@ namespace Mono.CSharp {
                        ToplevelBlock block = method.Block;
                        if (block != null) {
                                BlockContext bc = new BlockContext (method, block, method.ReturnType);
-                               if (block.Resolve (null, bc, method)) {
+                               if (block.Resolve (bc, method)) {
                                        debug_builder = member.Parent.CreateMethodSymbolEntry ();
                                        EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder);
 
index 1732a9b9c5c46edda117e4104b1d1637ad617bda..4b677e11888787e71e65123a107a385722e1c464 100644 (file)
@@ -201,6 +201,11 @@ namespace Mono.CSharp.Nullable
                        return uw != null && expr.Equals (uw.expr);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                public Expression Original {
                        get {
                                return expr;
@@ -480,6 +485,11 @@ namespace Mono.CSharp.Nullable
                        ec.MarkLabel (end_label);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+               }
+
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        unwrap.AddressOf (ec, mode);
@@ -1008,6 +1018,11 @@ namespace Mono.CSharp.Nullable
                        ec.MarkLabel (end_label);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Binary.FlowAnalysis (fc);
+               }
+
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
                        return Binary.MakeExpression (ctx, Left, Right);
@@ -1221,6 +1236,12 @@ namespace Mono.CSharp.Nullable
                        ec.MarkLabel (end_label);
                }
 
+               public override void FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       left.FlowAnalysis (fc);
+                       right.FlowAnalysis (fc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Expression t)
                {
                        NullCoalescingOperator target = (NullCoalescingOperator) t;
index b9bb8302eaca16d14aba215ba3268124e1577bb6..b3043994dc578939a06dfabb58f5663e03496865 100644 (file)
@@ -24,6 +24,13 @@ namespace Mono.CSharp {
        
        public abstract class Statement {
                public Location loc;
+               protected bool reachable;
+
+               public bool IsUnreachable {
+                       get {
+                               return !reachable;
+                       }
+               }
                
                /// <summary>
                ///   Resolves the statement, true means that all sub-statements
@@ -34,44 +41,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               /// <summary>
-               ///   We already know that the statement is unreachable, but we still
-               ///   need to resolve it to catch errors.
-               /// </summary>
-               public virtual bool ResolveUnreachable (BlockContext ec, bool warn)
-               {
-                       //
-                       // This conflicts with csc's way of doing this, but IMHO it's
-                       // the right thing to do.
-                       //
-                       // If something is unreachable, we still check whether it's
-                       // correct.  This means that you cannot use unassigned variables
-                       // in unreachable code, for instance.
-                       //
-
-                       bool unreachable = false;
-                       if (warn && !ec.UnreachableReported) {
-
-                               // TODO: This is wrong, need to form of flow-analysis branch specific flag
-                               // or multiple unrelared unreachable code won't be reported
-                               // if (false) { // ok } if (false) { // not reported }
-                               ec.UnreachableReported = true;
-                               unreachable = true;
-                               ec.Report.Warning (162, 2, loc, "Unreachable code detected");
-                       }
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       bool ok = Resolve (ec);
-                       ec.KillFlowBranching ();
-
-                       if (unreachable) {
-                               ec.UnreachableReported = false;
-                       }
-
-                       return ok;
-               }
-                               
                /// <summary>
                ///   Return value indicates whether all code paths emitted return.
                /// </summary>
@@ -110,6 +79,64 @@ namespace Mono.CSharp {
                {
                        return visitor.Visit (this);
                }
+
+               //
+               // Return value indicates whether statement has unreachable end
+               //
+               protected abstract bool DoFlowAnalysis (FlowAnalysisContext fc);
+
+               public bool FlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (reachable) {
+                               fc.UnreachableReported = false;
+                               return DoFlowAnalysis (fc);
+                       }
+
+                       //
+                       // Special handling cases
+                       //
+                       if (this is Block || this is SwitchLabel) {
+                               return DoFlowAnalysis (fc);
+                       }
+
+                       if (this is EmptyStatement)
+                               return true;
+
+                       if (fc.UnreachableReported)
+                               return true;
+
+                       fc.Report.Warning (162, 2, loc, "Unreachable code detected");
+                       fc.UnreachableReported = true;
+                       return true;
+               }
+
+               public virtual Reachability MarkReachable (Reachability rc)
+               {
+                       if (!rc.IsUnreachable)
+                               reachable = true;
+
+                       return rc;
+               }
+
+               protected void CheckExitBoundaries (BlockContext bc, Block scope)
+               {
+                       if (bc.CurrentBlock.ParametersBlock.Original != scope.ParametersBlock.Original) {
+                               bc.Report.Error (1632, loc, "Control cannot leave the body of an anonymous method");
+                               return;
+                       }
+
+                       for (var b = bc.CurrentBlock; b != null && b != scope; b = b.Parent) {
+                               if (b.IsFinallyBlock) {
+                                       Error_FinallyClauseExit (bc);
+                                       break;
+                               }
+                       }
+               }
+
+               protected void Error_FinallyClauseExit (BlockContext bc)
+               {
+                       bc.Report.Error (157, loc, "Control cannot leave the body of a finally clause");
+               }
        }
 
        public sealed class EmptyStatement : Statement
@@ -118,13 +145,8 @@ namespace Mono.CSharp {
                {
                        this.loc = loc;
                }
-               
-               public override bool Resolve (BlockContext ec)
-               {
-                       return true;
-               }
 
-               public override bool ResolveUnreachable (BlockContext ec, bool warn)
+               public override bool Resolve (BlockContext ec)
                {
                        return true;
                }
@@ -138,6 +160,11 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return false;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        // nothing needed.
@@ -148,13 +175,13 @@ namespace Mono.CSharp {
                        return visitor.Visit (this);
                }
        }
-       
+
        public class If : Statement {
                Expression expr;
                public Statement TrueStatement;
                public Statement FalseStatement;
 
-               bool is_true_ret;
+               bool true_returns, false_returns;
 
                public If (Expression bool_expr, Statement true_statement, Location l)
                        : this (bool_expr, true_statement, null, l)
@@ -180,51 +207,13 @@ namespace Mono.CSharp {
                
                public override bool Resolve (BlockContext ec)
                {
-                       bool ok = true;
-
                        expr = expr.Resolve (ec);
-                       if (expr == null) {
-                               ok = false;
-                       } else {
-                               //
-                               // Dead code elimination
-                               //
-                               if (expr is Constant) {
-                                       bool take = !((Constant) expr).IsDefaultValue;
-                                       if (take) {
-                                               if (!TrueStatement.Resolve (ec))
-                                                       return false;
-
-                                               if ((FalseStatement != null) &&
-                                                       !FalseStatement.ResolveUnreachable (ec, true))
-                                                       return false;
-                                               FalseStatement = null;
-                                       } else {
-                                               if (!TrueStatement.ResolveUnreachable (ec, true))
-                                                       return false;
-                                               TrueStatement = null;
-
-                                               if ((FalseStatement != null) &&
-                                                       !FalseStatement.Resolve (ec))
-                                                       return false;
-                                       }
-
-                                       return true;
-                               }
-                       }
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
-                       
-                       ok &= TrueStatement.Resolve (ec);
 
-                       is_true_ret = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
+                       var ok = TrueStatement.Resolve (ec);
 
-                       ec.CurrentBranching.CreateSibling ();
-
-                       if (FalseStatement != null)
+                       if (FalseStatement != null) {
                                ok &= FalseStatement.Resolve (ec);
-                                       
-                       ec.EndFlowBranching ();
+                       }
 
                        return ok;
                }
@@ -258,7 +247,7 @@ namespace Mono.CSharp {
                                bool branch_emitted = false;
                                
                                end = ec.DefineLabel ();
-                               if (!is_true_ret){
+                               if (!true_returns){
                                        ec.Emit (OpCodes.Br, end);
                                        branch_emitted = true;
                                }
@@ -273,6 +262,68 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+
+                       var da = fc.BranchDefiniteAssignment ();
+
+                       var res = TrueStatement.FlowAnalysis (fc);
+
+                       if (FalseStatement == null) {
+                               fc.DefiniteAssignment = da;
+                               return false;
+                       }
+
+                       var da_true = fc.DefiniteAssignment;
+                       if (true_returns) {
+                               fc.DefiniteAssignment = da;
+                               return FalseStatement.FlowAnalysis (fc);
+                       }
+
+                       fc.DefiniteAssignment = new DefiniteAssignmentBitSet (da);
+                       res &= FalseStatement.FlowAnalysis (fc);
+
+                       if (false_returns)
+                               fc.DefiniteAssignment = da_true;
+                       else
+                               fc.DefiniteAssignment &= da_true;
+
+                       return res;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       var c = expr as Constant;
+                       if (c != null) {
+                               bool take = !c.IsDefaultValue;
+                               if (take) {
+                                       rc = TrueStatement.MarkReachable (rc);
+                               } else {
+                                       if (FalseStatement != null)
+                                               rc = FalseStatement.MarkReachable (rc);
+                               }
+
+                               return rc;
+                       }
+
+                       var true_rc = TrueStatement.MarkReachable (rc);
+                       true_returns = true_rc.IsUnreachable;
+       
+                       if (FalseStatement == null)
+                               return rc;
+
+                       var false_rc = FalseStatement.MarkReachable (rc);
+                       false_returns = false_rc.IsUnreachable;
+
+                       return true_rc & false_rc;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        If target = (If) t;
@@ -289,14 +340,15 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Do : Statement {
+       public class Do : LoopStatement
+       {
                public Expression expr;
-               public Statement  EmbeddedStatement;
+               bool iterator_reachable, end_reachable;
 
                public Do (Statement statement, BooleanExpression bool_expr, Location doLocation, Location whileLocation)
+                       : base (statement)
                {
                        expr = bool_expr;
-                       EmbeddedStatement = statement;
                        loc = doLocation;
                        WhileLocation = whileLocation;
                }
@@ -305,32 +357,11 @@ namespace Mono.CSharp {
                        get; private set;
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       bool ok = true;
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
-
-                       bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
-                       if (!EmbeddedStatement.Resolve (ec))
-                               ok = false;
-                       ec.EndFlowBranching ();
-
-                       if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable)
-                               ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected");
+                       var ok = base.Resolve (bc);
 
-                       expr = expr.Resolve (ec);
-                       if (expr == null)
-                               ok = false;
-                       else if (expr is Constant){
-                               bool infinite = !((Constant) expr).IsDefaultValue;
-                               if (infinite)
-                                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       }
-
-                       ec.EndFlowBranching ();
+                       expr = expr.Resolve (bc);
 
                        return ok;
                }
@@ -345,7 +376,7 @@ namespace Mono.CSharp {
                        ec.LoopEnd = ec.DefineLabel ();
                                
                        ec.MarkLabel (loop);
-                       EmbeddedStatement.Emit (ec);
+                       Statement.Emit (ec);
                        ec.MarkLabel (ec.LoopBegin);
 
                        // Mark start of while condition
@@ -370,11 +401,53 @@ namespace Mono.CSharp {
                        ec.LoopEnd = old_end;
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var dat = fc.BranchDefiniteAssignment ();
+
+                       var res = Statement.FlowAnalysis (fc);
+
+                       expr.FlowAnalysis (fc);
+
+                       fc.DefiniteAssignment = dat | fc.DefiniteAssignment;
+
+                       if (res && !iterator_reachable)
+                               return !end_reachable;
+
+                       if (!end_reachable) {
+                               var c = expr as Constant;
+                               if (c != null && !c.IsDefaultValue)
+                                       return true;
+                       }
+
+                       return false;
+               }
+               
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       
+                       var body_rc = Statement.MarkReachable (rc);
+
+                       if (body_rc.IsUnreachable && !iterator_reachable) {
+                               expr = new UnreachableExpression (expr);
+                               return end_reachable ? rc : Reachability.CreateUnreachable ();
+                       }
+
+                       if (!end_reachable) {
+                               var c = expr as Constant;
+                               if (c != null && !c.IsDefaultValue)
+                                       return Reachability.CreateUnreachable ();
+                       }
+
+                       return rc;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Do target = (Do) t;
 
-                       target.EmbeddedStatement = EmbeddedStatement.Clone (clonectx);
+                       target.Statement = Statement.Clone (clonectx);
                        target.expr = expr.Clone (clonectx);
                }
                
@@ -382,58 +455,46 @@ namespace Mono.CSharp {
                {
                        return visitor.Visit (this);
                }
+
+               public override void SetEndReachable ()
+               {
+                       end_reachable = true;
+               }
+
+               public override void SetIteratorReachable ()
+               {
+                       iterator_reachable = true;
+               }
        }
 
-       public class While : Statement {
+       public class While : LoopStatement
+       {
                public Expression expr;
-               public Statement Statement;
-               bool infinite, empty;
+               bool empty, infinite, end_reachable;
+               List<DefiniteAssignmentBitSet> end_reachable_das;
 
                public While (BooleanExpression bool_expr, Statement statement, Location l)
+                       : base (statement)
                {
                        this.expr = bool_expr;
-                       Statement = statement;
                        loc = l;
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
                        bool ok = true;
 
-                       expr = expr.Resolve (ec);
+                       expr = expr.Resolve (bc);
                        if (expr == null)
                                ok = false;
 
-                       //
-                       // Inform whether we are infinite or not
-                       //
-                       if (expr is Constant){
-                               bool value = !((Constant) expr).IsDefaultValue;
-
-                               if (value == false){
-                                       if (!Statement.ResolveUnreachable (ec, true))
-                                               return false;
-                                       empty = true;
-                                       return true;
-                               }
-
-                               infinite = true;
+                       var c = expr as Constant;
+                       if (c != null) {
+                               empty = c.IsDefaultValue;
+                               infinite = !empty;
                        }
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
-                       if (!infinite)
-                               ec.CurrentBranching.CreateSibling ();
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
-                       if (!Statement.Resolve (ec))
-                               ok = false;
-                       ec.EndFlowBranching ();
-
-                       // There's no direct control flow from the end of the embedded statement to the end of the loop
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-
-                       ec.EndFlowBranching ();
-
+                       ok &= base.Resolve (bc);
                        return ok;
                }
                
@@ -489,6 +550,58 @@ namespace Mono.CSharp {
                        ec.LoopEnd = old_end;
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+
+                       DefiniteAssignmentBitSet das;
+
+                       das = fc.BranchDefiniteAssignment ();
+
+                       Statement.FlowAnalysis (fc);
+
+                       //
+                       // Special case infinite while with breaks
+                       //
+                       if (end_reachable_das != null) {
+                               das = DefiniteAssignmentBitSet.And (end_reachable_das);
+                               end_reachable_das = null;
+                       }
+
+                       fc.DefiniteAssignment = das;
+
+                       if (infinite && !end_reachable)
+                               return true;
+
+                       return false;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       //
+                       // Special case unreachable while body
+                       //
+                       if (empty) {
+                               Statement.MarkReachable (Reachability.CreateUnreachable ());
+                               return rc;
+                       }
+
+                       Statement.MarkReachable (rc);
+
+                       //
+                       // When infinite while end is unreachable via break anything what follows is unreachable too
+                       //
+                       if (infinite && !end_reachable)
+                               return Reachability.CreateUnreachable ();
+
+                       return rc;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        While target = (While) t;
@@ -501,13 +614,31 @@ namespace Mono.CSharp {
                {
                        return visitor.Visit (this);
                }
+
+               public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+               {
+                       if (!infinite)
+                               return;
+
+                       if (end_reachable_das == null)
+                               end_reachable_das = new List<DefiniteAssignmentBitSet> ();
+
+                       end_reachable_das.Add (fc.DefiniteAssignment);
+               }
+
+               public override void SetEndReachable ()
+               {
+                       end_reachable = true;
+               }
        }
 
-       public class For : Statement
+       public class For : LoopStatement
        {
-               bool infinite, empty;
+               bool infinite, empty, iterator_reachable, end_reachable;
+               List<DefiniteAssignmentBitSet> end_reachability;
                
                public For (Location l)
+                       : base (null)
                {
                        loc = l;
                }
@@ -524,68 +655,68 @@ namespace Mono.CSharp {
                        get; set;
                }
 
-               public Statement Statement {
-                       get; set;
-               }
-
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       bool ok = true;
-
-                       if (Initializer != null) {
-                               if (!Initializer.Resolve (ec))
-                                       ok = false;
-                       }
+                       Initializer.Resolve (bc);
 
                        if (Condition != null) {
-                               Condition = Condition.Resolve (ec);
-                               if (Condition == null)
-                                       ok = false;
-                               else if (Condition is Constant) {
-                                       bool value = !((Constant) Condition).IsDefaultValue;
-
-                                       if (value == false){
-                                               if (!Statement.ResolveUnreachable (ec, true))
-                                                       return false;
-                                               if ((Iterator != null) &&
-                                                       !Iterator.ResolveUnreachable (ec, false))
-                                                       return false;
+                               Condition = Condition.Resolve (bc);
+                               var condition_constant = Condition as Constant;
+                               if (condition_constant != null) {
+                                       if (condition_constant.IsDefaultValue) {
                                                empty = true;
-                                               return true;
+                                       } else {
+                                               infinite = true;
                                        }
-
-                                       infinite = true;
                                }
-                       } else
+                       } else {
                                infinite = true;
+                       }
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
-                       if (!infinite)
-                               ec.CurrentBranching.CreateSibling ();
+                       base.Resolve (bc);
 
-                       bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
+                       Iterator.Resolve (bc);
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
-                       if (!Statement.Resolve (ec))
-                               ok = false;
-                       ec.EndFlowBranching ();
+                       return true;
+               }
 
-                       if (Iterator != null){
-                               if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable) {
-                                       if (!Iterator.ResolveUnreachable (ec, !was_unreachable))
-                                               ok = false;
-                               } else {
-                                       if (!Iterator.Resolve (ec))
-                                               ok = false;
-                               }
-                       }
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Initializer.FlowAnalysis (fc);
 
-                       // There's no direct control flow from the end of the embedded statement to the end of the loop
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
+                       if (Condition != null)
+                               Condition.FlowAnalysis (fc);
 
-                       ec.EndFlowBranching ();
+                       var das = fc.BranchDefiniteAssignment ();
 
-                       return ok;
+                       Statement.FlowAnalysis (fc);
+
+                       Iterator.FlowAnalysis (fc);
+
+                       fc.DefiniteAssignment = das;
+
+                       return infinite && !end_reachable;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       Initializer.MarkReachable (rc);
+
+                       var body_rc = Statement.MarkReachable (rc);
+                       if (!body_rc.IsUnreachable || iterator_reachable) {
+                               Iterator.MarkReachable (rc);
+                       }
+
+                       //
+                       // When infinite for end is unreachable via break anything what follows is unreachable too
+                       //
+                       if (infinite && !end_reachable) {
+                               return Reachability.CreateUnreachable ();
+                       }
+
+                       return rc;
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -658,6 +789,64 @@ namespace Mono.CSharp {
                {
                        return visitor.Visit (this);
                }
+
+               public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+               {
+                       if (!infinite)
+                               return;
+
+                       if (end_reachability == null)
+                               end_reachability = new List<DefiniteAssignmentBitSet> ();
+
+                       end_reachability.Add (fc.DefiniteAssignment);
+               }
+
+               public override void SetEndReachable ()
+               {
+                       end_reachable = true;
+               }
+
+               public override void SetIteratorReachable ()
+               {
+                       iterator_reachable = true;
+               }
+       }
+
+       public abstract class LoopStatement : Statement
+       {
+               protected LoopStatement (Statement statement)
+               {
+                       Statement = statement;
+               }
+
+               public Statement Statement { get; set; }
+
+               public override bool Resolve (BlockContext bc)
+               {
+                       var prev_loop = bc.EnclosingLoop;
+                       var prev_los = bc.EnclosingLoopOrSwitch;
+                       bc.EnclosingLoopOrSwitch = bc.EnclosingLoop = this;
+                       Statement.Resolve (bc);
+                       bc.EnclosingLoopOrSwitch = prev_los;
+                       bc.EnclosingLoop = prev_loop;
+
+                       return true;
+               }
+
+               //
+               // Needed by possibly infinite loops statements (for, while) and switch statment
+               //
+               public virtual void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+               {
+               }
+
+               public virtual void SetEndReachable ()
+               {
+               }
+
+               public virtual void SetIteratorReachable ()
+               {
+               }
        }
        
        public class StatementExpression : Statement
@@ -690,7 +879,20 @@ namespace Mono.CSharp {
                
                protected override void DoEmit (EmitContext ec)
                {
-                       expr.EmitStatement (ec);
+                       expr.EmitStatement (ec);
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+                       return false;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       expr.MarkReachable (rc);
+                       return rc;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -732,6 +934,11 @@ namespace Mono.CSharp {
                        throw new NotSupportedException ();
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return false;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        var t = (StatementErrorExpression) target;
@@ -784,6 +991,25 @@ namespace Mono.CSharp {
                                s.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       foreach (var s in statements)
+                               s.FlowAnalysis (fc);
+
+                       return false;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       Reachability res = rc;
+                       foreach (var s in statements)
+                               res = s.MarkReachable (rc);
+
+                       return res;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        StatementList t = (StatementList) target;
@@ -799,23 +1025,54 @@ namespace Mono.CSharp {
                }
        }
 
-       // A 'return' or a 'yield break'
+       //
+       // For statements which require special handling when inside try or catch block
+       //
        public abstract class ExitStatement : Statement
        {
                protected bool unwind_protect;
-               protected abstract bool DoResolve (BlockContext ec);
 
-               public virtual void Error_FinallyClause (Report Report)
+               protected abstract bool DoResolve (BlockContext bc);
+               protected abstract bool IsLocalExit { get; }
+
+               public override bool Resolve (BlockContext bc)
                {
-                       Report.Error (157, loc, "Control cannot leave the body of a finally clause");
+                       var res = DoResolve (bc);
+
+                       if (!IsLocalExit) {
+                               //
+                               // We are inside finally scope but is it the scope we are exiting
+                               //
+                               if (bc.HasSet (ResolveContext.Options.FinallyScope)) {
+
+                                       for (var b = bc.CurrentBlock; b != null; b = b.Parent) {
+                                               if (b.IsFinallyBlock) {
+                                                       Error_FinallyClauseExit (bc);
+                                                       break;
+                                               }
+
+                                               if (b is ParametersBlock)
+                                                       break;
+                                       }
+                               }
+                       }
+
+                       unwind_protect = bc.HasAny (ResolveContext.Options.TryScope | ResolveContext.Options.CatchScope);
+                       return res;
                }
 
-               public sealed override bool Resolve (BlockContext ec)
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
                {
-                       var res = DoResolve (ec);
-                       unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return res;
+                       if (IsLocalExit)
+                               return true;
+
+                       if (fc.TryFinally != null) {
+                           fc.TryFinally.RegisterOutParametersCheck (new DefiniteAssignmentBitSet (fc.DefiniteAssignment));
+                       } else {
+                           fc.ParametersBlock.CheckOutParametersAssignment (fc);
+                       }
+
+                       return true;
                }
        }
 
@@ -843,12 +1100,20 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override bool IsLocalExit {
+                       get {
+                               return false;
+                       }
+               }
+
                #endregion
 
                protected override bool DoResolve (BlockContext ec)
                {
+                       var block_return_type = ec.ReturnType;
+
                        if (expr == null) {
-                               if (ec.ReturnType.Kind == MemberKind.Void)
+                               if (block_return_type.Kind == MemberKind.Void)
                                        return true;
 
                                //
@@ -878,7 +1143,6 @@ namespace Mono.CSharp {
                        }
 
                        expr = expr.Resolve (ec);
-                       TypeSpec block_return_type = ec.ReturnType;
 
                        AnonymousExpression am = ec.CurrentAnonymousMethod;
                        if (am == null) {
@@ -1007,7 +1271,7 @@ namespace Mono.CSharp {
                                                ec.EmitEpilogue ();
                                        }
 
-                                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, async_body.BodyEnd);
+                                       ec.Emit (OpCodes.Leave, async_body.BodyEnd);
                                        return;
                                }
 
@@ -1026,12 +1290,27 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (expr != null)
+                               expr.FlowAnalysis (fc);
+
+                       base.DoFlowAnalysis (fc);
+                       return true;
+               }
+
                void Error_ReturnFromIterator (ResolveContext rc)
                {
                        rc.Report.Error (1622, loc,
                                "Cannot return a value from iterators. Use the yield return statement to return a value, or yield break to end the iteration");
                }
 
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Reachability.CreateUnreachable ();
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Return target = (Return) t;
@@ -1046,18 +1325,12 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Goto : Statement {
+       public class Goto : ExitStatement
+       {
                string target;
                LabeledStatement label;
-               bool unwind_protect;
+               TryFinally try_finally;
 
-               public override bool Resolve (BlockContext ec)
-               {
-                       unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return true;
-               }
-               
                public Goto (string label, Location l)
                {
                        loc = l;
@@ -1068,10 +1341,67 @@ namespace Mono.CSharp {
                        get { return target; }
                }
 
-               public void SetResolvedTarget (LabeledStatement label)
+               protected override bool IsLocalExit {
+                       get {
+                               return true;
+                       }
+               }
+
+               protected override bool DoResolve (BlockContext bc)
+               {
+                       label = bc.CurrentBlock.LookupLabel (target);
+                       if (label == null) {
+                               Error_UnknownLabel (bc, target, loc);
+                               return false;
+                       }
+
+                       try_finally = bc.CurrentTryBlock as TryFinally;
+
+                       CheckExitBoundaries (bc, label.Block);
+
+                       return true;
+               }
+
+               public static void Error_UnknownLabel (BlockContext bc, string label, Location loc)
+               {
+                       bc.Report.Error (159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
+                               label);
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
                {
-                       this.label = label;
-                       label.AddReference ();
+                       if (fc.LabelStack == null) {
+                               fc.LabelStack = new List<LabeledStatement> ();
+                       } else if (fc.LabelStack.Contains (label)) {
+                               return true;
+                       }
+
+                       fc.LabelStack.Add (label);
+                       label.Block.ScanGotoJump (label, fc);
+                       fc.LabelStack.Remove (label);
+                       return true;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       if (try_finally != null) {
+                               if (try_finally.FinallyBlock.HasReachableClosingBrace) {
+                                       label.AddGotoReference (rc, false);
+                               } else {
+                                       label.AddGotoReference (rc, true);
+                               }
+
+                               try_finally = null;
+                       } else {
+                               label.AddGotoReference (rc, false);
+                       }
+
+                       return Reachability.CreateUnreachable ();
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -1083,6 +1413,7 @@ namespace Mono.CSharp {
                {
                        if (label == null)
                                throw new InternalErrorException ("goto emitted before target resolved");
+
                        Label l = label.LabelTarget (ec);
                        ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
                }
@@ -1097,10 +1428,9 @@ namespace Mono.CSharp {
                string name;
                bool defined;
                bool referenced;
+               bool finalTarget;
                Label label;
                Block block;
-
-               FlowBranching.UsageVector vectors;
                
                public LabeledStatement (string name, Block block, Location l)
                {
@@ -1129,51 +1459,66 @@ namespace Mono.CSharp {
                        get { return name; }
                }
 
-               public bool IsDefined {
-                       get { return defined; }
-               }
-
-               public bool HasBeenReferenced {
-                       get { return referenced; }
-               }
-
-               public FlowBranching.UsageVector JumpOrigins {
-                       get { return vectors; }
-               }
-
-               public void AddUsageVector (FlowBranching.UsageVector vector)
-               {
-                       vector = vector.Clone ();
-                       vector.Next = vectors;
-                       vectors = vector;
-               }
-
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        // nothing to clone
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       // this flow-branching will be terminated when the surrounding block ends
-                       ec.StartFlowBranching (this);
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       if (!HasBeenReferenced)
-                               ec.Report.Warning (164, 2, loc, "This label has not been referenced");
-
                        LabelTarget (ec);
                        ec.MarkLabel (label);
+
+                       if (finalTarget)
+                               ec.Emit (OpCodes.Br_S, label);
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (!referenced) {
+                               fc.Report.Warning (164, 2, loc, "This label has not been referenced");
+                       }
+
+                       return false;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       if (referenced)
+                               rc = new Reachability ();
+
+                       return rc;
                }
 
-               public void AddReference ()
+               public void AddGotoReference (Reachability rc, bool finalTarget)
                {
+                       if (referenced)
+                               return;
+
                        referenced = true;
+
+                       //
+                       // Label is final target when goto jumps out of try block with
+                       // finally clause. In that case we need leave with target but in C#
+                       // terms the label is unreachable. Using finalTarget we emit
+                       // explicit label not just marker
+                       //
+                       if (finalTarget) {
+                               MarkReachable (rc);
+                               this.finalTarget = true;
+                               return;
+                       }
+
+                       block.ScanGotoJump (this);
                }
-               
+
                public override object Accept (StructuralVisitor visitor)
                {
                        return visitor.Visit (this);
@@ -1184,35 +1529,29 @@ namespace Mono.CSharp {
        /// <summary>
        ///   `goto default' statement
        /// </summary>
-       public class GotoDefault : Statement {
-               
+       public class GotoDefault : SwitchGoto
+       {               
                public GotoDefault (Location l)
+                       : base (l)
                {
-                       loc = l;
-               }
-
-               protected override void CloneTo (CloneContext clonectx, Statement target)
-               {
-                       // nothing to clone
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-
-                       if (ec.Switch == null) {
-                               ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+                       if (bc.Switch == null) {
+                               Error_GotoCaseRequiresSwitchBlock (bc);
                                return false;
                        }
 
-                       ec.Switch.RegisterGotoCase (null, null);
+                       bc.Switch.RegisterGotoCase (null, null);
+                       base.Resolve (bc);
 
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.Emit (OpCodes.Br, ec.Switch.DefaultLabel.GetILLabel (ec));
+                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.Switch.DefaultLabel.GetILLabel (ec));
                }
                
                public override object Accept (StructuralVisitor visitor)
@@ -1224,32 +1563,31 @@ namespace Mono.CSharp {
        /// <summary>
        ///   `goto case' statement
        /// </summary>
-       public class GotoCase : Statement {
+       public class GotoCase : SwitchGoto
+       {
                Expression expr;
                
                public GotoCase (Expression e, Location l)
+                       : base (l)
                {
                        expr = e;
-                       loc = l;
                }
 
                public Expression Expr {
                        get {
-                               return this.expr;
+                               return expr;
                        }
                }
 
                public SwitchLabel Label { get; set; }
-               
+
                public override bool Resolve (BlockContext ec)
                {
-                       if (ec.Switch == null){
-                               ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+                       if (ec.Switch == null) {
+                               Error_GotoCaseRequiresSwitchBlock (ec);
                                return false;
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-
                        Constant c = expr.ResolveLabelConstant (ec);
                        if (c == null) {
                                return false;
@@ -1274,12 +1612,14 @@ namespace Mono.CSharp {
                        }
 
                        ec.Switch.RegisterGotoCase (this, res);
+                       base.Resolve (ec);
+
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       ec.Emit (OpCodes.Br, Label.GetILLabel (ec));
+                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, Label.GetILLabel (ec));
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -1294,6 +1634,46 @@ namespace Mono.CSharp {
                        return visitor.Visit (this);
                }
        }
+
+       public abstract class SwitchGoto : Statement
+       {
+               protected bool unwind_protect;
+
+               protected SwitchGoto (Location loc)
+               {
+                       this.loc = loc;
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       // Nothing to clone
+               }
+
+               public override bool Resolve (BlockContext bc)
+               {
+                       CheckExitBoundaries (bc, bc.Switch.Block);
+
+                       unwind_protect = bc.HasAny (ResolveContext.Options.TryScope | ResolveContext.Options.CatchScope);
+
+                       return true;
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return true;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Reachability.CreateUnreachable ();
+               }
+
+               protected void Error_GotoCaseRequiresSwitchBlock (BlockContext bc)
+               {
+                       bc.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+               }
+       }
        
        public class Throw : Statement {
                Expression expr;
@@ -1313,12 +1693,22 @@ namespace Mono.CSharp {
                public override bool Resolve (BlockContext ec)
                {
                        if (expr == null) {
-                               ec.CurrentBranching.CurrentUsageVector.Goto ();
-                               return ec.CurrentBranching.CheckRethrow (loc);
+                               if (!ec.HasSet (ResolveContext.Options.CatchScope)) {
+                                       ec.Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause");
+                               } else if (ec.HasSet (ResolveContext.Options.FinallyScope)) {
+                                       for (var b = ec.CurrentBlock; b != null && !b.IsCatchBlock; b = b.Parent) {
+                                               if (b.IsFinallyBlock) {
+                                                       ec.Report.Error (724, loc,
+                                                               "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause");
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               return true;
                        }
 
                        expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
 
                        if (expr == null)
                                return false;
@@ -1343,6 +1733,20 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (expr != null)
+                               expr.FlowAnalysis (fc);
+
+                       return true;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Reachability.CreateUnreachable ();
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Throw target = (Throw) t;
@@ -1357,20 +1761,16 @@ namespace Mono.CSharp {
                }
        }
 
-       public class Break : Statement {
-               
+       public class Break : LocalExitStatement
+       {               
                public Break (Location l)
+                       : base (l)
                {
-                       loc = l;
                }
-
-               bool unwind_protect;
-
-               public override bool Resolve (BlockContext ec)
+               
+               public override object Accept (StructuralVisitor visitor)
                {
-                       unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return true;
+                       return visitor.Visit (this);
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -1378,46 +1778,99 @@ namespace Mono.CSharp {
                        ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
                }
 
-               protected override void CloneTo (CloneContext clonectx, Statement t)
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
                {
-                       // nothing needed
+                       enclosing_loop.AddEndDefiniteAssignment (fc);
+                       return true;
                }
-               
-               public override object Accept (StructuralVisitor visitor)
+
+               protected override bool DoResolve (BlockContext bc)
                {
-                       return visitor.Visit (this);
+                       enclosing_loop = bc.EnclosingLoopOrSwitch;
+                       return base.DoResolve (bc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       if (!rc.IsUnreachable)
+                               enclosing_loop.SetEndReachable ();
+
+                       return Reachability.CreateUnreachable ();
                }
        }
 
-       public class Continue : Statement {
-               
+       public class Continue : LocalExitStatement
+       {               
                public Continue (Location l)
+                       : base (l)
                {
-                       loc = l;
                }
 
-               bool unwind_protect;
-
-               public override bool Resolve (BlockContext ec)
+               public override object Accept (StructuralVisitor visitor)
                {
-                       unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return true;
+                       return visitor.Visit (this);
                }
 
+
                protected override void DoEmit (EmitContext ec)
                {
                        ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
                }
 
+               protected override bool DoResolve (BlockContext bc)
+               {
+                       enclosing_loop = bc.EnclosingLoop;
+                       return base.DoResolve (bc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       if (!rc.IsUnreachable)
+                               enclosing_loop.SetIteratorReachable ();
+
+                       return Reachability.CreateUnreachable ();
+               }
+       }
+
+       public abstract class LocalExitStatement : ExitStatement
+       {
+               protected LoopStatement enclosing_loop;
+
+               protected LocalExitStatement (Location loc)
+               {
+                       this.loc = loc;
+               }
+
+               protected override bool IsLocalExit {
+                       get {
+                               return true;
+                       }
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        // nothing needed.
                }
-               
-               public override object Accept (StructuralVisitor visitor)
+
+               protected override bool DoResolve (BlockContext bc)
                {
-                       return visitor.Visit (this);
+                       if (enclosing_loop == null) {
+                               bc.Report.Error (139, loc, "No enclosing loop out of which to break or continue");
+                               return false;
+                       }
+
+                       var block = enclosing_loop.Statement as Block;
+
+                       // Don't need to do extra checks for simple statements loops
+                       if (block != null) {
+                               CheckExitBoundaries (bc, block);
+                       }
+
+                       return true;
                }
        }
 
@@ -1679,6 +2132,30 @@ namespace Mono.CSharp {
                        }
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (Initializer != null)
+                               Initializer.FlowAnalysis (fc);
+
+                       if (declarators != null) {
+                               foreach (var d in declarators) {
+                                       if (d.Initializer != null)
+                                               d.Initializer.FlowAnalysis (fc);
+                               }
+                       }
+
+                       return false;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       var init = initializer as ExpressionStatement;
+                       if (init != null)
+                               init.MarkReachable (rc);
+
+                       return base.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        BlockVariable t = (BlockVariable) target;
@@ -1749,7 +2226,7 @@ namespace Mono.CSharp {
        //
        // The information about a user-perceived local variable
        //
-       public class LocalVariable : INamedBlockVariable, ILocalVariable
+       public sealed class LocalVariable : INamedBlockVariable, ILocalVariable
        {
                [Flags]
                public enum Flags
@@ -1762,8 +2239,7 @@ namespace Mono.CSharp {
                        ForeachVariable = 1 << 5,
                        FixedVariable = 1 << 6,
                        UsingVariable = 1 << 7,
-//                     DefinitelyAssigned = 1 << 8,
-                       IsLocked = 1 << 9,
+                       IsLocked = 1 << 8,
 
                        ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable
                }
@@ -2001,23 +2477,20 @@ namespace Mono.CSharp {
                        throw new InternalErrorException ("Variable is not readonly");
                }
 
-               public bool IsThisAssigned (BlockContext ec, Block block)
+               public bool IsThisAssigned (FlowAnalysisContext fc, Block block)
                {
                        if (VariableInfo == null)
                                throw new Exception ();
 
-                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
+                       if (IsAssigned (fc))
                                return true;
 
-                       return VariableInfo.IsFullyInitialized (ec, block.StartLocation);
+                       return VariableInfo.IsFullyInitialized (fc, block.StartLocation);
                }
 
-               public bool IsAssigned (BlockContext ec)
+               public bool IsAssigned (FlowAnalysisContext fc)
                {
-                       if (VariableInfo == null)
-                               throw new Exception ();
-
-                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
+                       return fc.IsDefinitelyAssigned (VariableInfo);
                }
 
                public void PrepareAssignmentAnalysis (BlockContext bc)
@@ -2069,7 +2542,7 @@ namespace Mono.CSharp {
                public enum Flags
                {
                        Unchecked = 1,
-                       HasRet = 8,
+                       ReachableEnd = 8,
                        Unsafe = 16,
                        HasCapturedVariable = 64,
                        HasCapturedThis = 1 << 7,
@@ -2079,7 +2552,10 @@ namespace Mono.CSharp {
                        Resolved = 1 << 11,
                        YieldBlock = 1 << 12,
                        AwaitBlock = 1 << 13,
-                       Iterator = 1 << 14
+                       FinallyBlock = 1 << 14,
+                       CatchBlock = 1 << 15,
+                       Iterator = 1 << 20,
+                       NoFlowAnalysis = 1 << 21
                }
 
                public Block Parent;
@@ -2137,15 +2613,6 @@ namespace Mono.CSharp {
 
                #region Properties
 
-               public bool HasUnreachableClosingBrace {
-                       get {
-                               return (flags & Flags.HasRet) != 0;
-                       }
-                       set {
-                               flags = value ? flags | Flags.HasRet : flags & ~Flags.HasRet;
-                       }
-               }
-
                public Block Original {
                        get {
                                return original;
@@ -2160,6 +2627,19 @@ namespace Mono.CSharp {
                        set { flags = value ? flags | Flags.CompilerGenerated : flags & ~Flags.CompilerGenerated; }
                }
 
+
+               public bool IsCatchBlock {
+                       get {
+                               return (flags & Flags.CatchBlock) != 0;
+                       }
+               }
+
+               public bool IsFinallyBlock {
+                       get {
+                               return (flags & Flags.FinallyBlock) != 0;
+                       }
+               }
+
                public bool Unchecked {
                        get { return (flags & Flags.Unchecked) != 0; }
                        set { flags = value ? flags | Flags.Unchecked : flags & ~Flags.Unchecked; }
@@ -2273,123 +2753,72 @@ namespace Mono.CSharp {
                        return ParametersBlock.TopBlock.GetLabel (name, this);
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       if (scope_initializers != null) {
+                               foreach (var si in scope_initializers)
+                                       si.MarkReachable (rc);
+                       }
+
+                       foreach (var s in statements) {
+                               rc = s.MarkReachable (rc);
+                               if (rc.IsUnreachable) {
+                                       if ((flags & Flags.ReachableEnd) != 0)
+                                               return new Reachability ();
+
+                                       return rc;
+                               }
+                       }
+
+                       flags |= Flags.ReachableEnd;
+
+                       return rc;
+               }
+
+               public override bool Resolve (BlockContext bc)
                {
                        if ((flags & Flags.Resolved) != 0)
                                return true;
 
-                       Block prev_block = ec.CurrentBlock;
-                       bool ok = true;
-                       bool unreachable = ec.IsUnreachable;
-                       bool prev_unreachable = unreachable;
-
-                       ec.CurrentBlock = this;
-                       ec.StartFlowBranching (this);
+                       Block prev_block = bc.CurrentBlock;
+                       bc.CurrentBlock = this;
 
                        //
                        // Compiler generated scope statements
                        //
                        if (scope_initializers != null) {
                                for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) {
-                                       scope_initializers[resolving_init_idx.Value].Resolve (ec);
+                                       scope_initializers[resolving_init_idx.Value].Resolve (bc);
                                }
 
                                resolving_init_idx = null;
                        }
 
-                       //
-                       // This flag is used to notate nested statements as unreachable from the beginning of this block.
-                       // For the purposes of this resolution, it doesn't matter that the whole block is unreachable 
-                       // from the beginning of the function.  The outer Resolve() that detected the unreachability is
-                       // responsible for handling the situation.
-                       //
+                       bool ok = true;
                        int statement_count = statements.Count;
                        for (int ix = 0; ix < statement_count; ix++){
                                Statement s = statements [ix];
 
-                               //
-                               // Warn if we detect unreachable code.
-                               //
-                               if (unreachable) {
-                                       if (s is EmptyStatement)
-                                               continue;
-
-                                       if (!ec.UnreachableReported && !(s is LabeledStatement) && !(s is SwitchLabel)) {
-                                               ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
-                                               ec.UnreachableReported = true;
-                                       }
-                               }
-
-                               //
-                               // Note that we're not using ResolveUnreachable() for unreachable
-                               // statements here.  ResolveUnreachable() creates a temporary
-                               // flow branching and kills it afterwards.  This leads to problems
-                               // if you have two unreachable statements where the first one
-                               // assigns a variable and the second one tries to access it.
-                               //
-
-                               if (!s.Resolve (ec)) {
+                               if (!s.Resolve (bc)) {
                                        ok = false;
-                                       if (!ec.IsInProbingMode)
+                                       if (!bc.IsInProbingMode)
                                                statements [ix] = new EmptyStatement (s.loc);
 
                                        continue;
                                }
-
-                               if (unreachable && !(s is LabeledStatement) && !(s is SwitchLabel) && !(s is Block))
-                                       statements [ix] = new EmptyStatement (s.loc);
-
-                               unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-                               if (unreachable) {
-                                       ec.IsUnreachable = true;
-                               } else if (ec.IsUnreachable)
-                                       ec.IsUnreachable = false;
                        }
 
-                       if (unreachable != prev_unreachable) {
-                               ec.IsUnreachable = prev_unreachable;
-                               ec.UnreachableReported = false;
-                       }
-
-                       while (ec.CurrentBranching is FlowBranchingLabeled)
-                               ec.EndFlowBranching ();
-
-                       bool flow_unreachable = ec.EndFlowBranching ();
-
-                       ec.CurrentBlock = prev_block;
-
-                       if (flow_unreachable)
-                               flags |= Flags.HasRet;
-
-                       // If we're a non-static `struct' constructor which doesn't have an
-                       // initializer, then we must initialize all of the struct's fields.
-                       if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable)
-                               ok = false;
+                       bc.CurrentBlock = prev_block;
 
                        flags |= Flags.Resolved;
                        return ok;
                }
 
-               public override bool ResolveUnreachable (BlockContext ec, bool warn)
-               {
-                       bool unreachable = false;
-                       if (warn && !ec.UnreachableReported) {
-                               ec.UnreachableReported = true;
-                               unreachable = true;
-                               ec.Report.Warning (162, 2, loc, "Unreachable code detected");
-                       }
-
-                       var fb = ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
-                       fb.CurrentUsageVector.IsUnreachable = true;
-                       bool ok = Resolve (ec);
-                       ec.KillFlowBranching ();
-
-                       if (unreachable)
-                               ec.UnreachableReported = false;
-
-                       return ok;
-               }
-               
                protected override void DoEmit (EmitContext ec)
                {
                        for (int ix = 0; ix < statements.Count; ix++){
@@ -2411,6 +2840,103 @@ namespace Mono.CSharp {
                                s.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (scope_initializers != null) {
+                               foreach (var si in scope_initializers)
+                                       si.FlowAnalysis (fc);
+                       }
+
+                       return DoFlowAnalysis (fc, 0);  
+               }
+
+               bool DoFlowAnalysis (FlowAnalysisContext fc, int startIndex)
+               {
+                       bool end_unreachable = !reachable;
+                       for (; startIndex < statements.Count; ++startIndex) {
+                               var s = statements[startIndex];
+
+                               end_unreachable = s.FlowAnalysis (fc);
+                               if (s.IsUnreachable) {
+                                       //
+                                       // This is kind of a hack, switch label is unreachable because we need to mark
+                                       // switch section end but at the same time we need to run Emit on it
+                                       //
+                                       if (s is SwitchLabel)
+                                               continue;
+
+                                       statements[startIndex] = new EmptyStatement (s.loc);
+                                       continue;
+                               }
+
+                               //
+                               // Statement end reachability is needed mostly due to goto support. Consider
+                               //
+                               // if (cond) {
+                               //    goto X;
+                               // } else {
+                               //    goto Y;
+                               // }
+                               // X:
+                               //
+                               // X label is reachable only via goto not as another statement after if. We need
+                               // this for flow-analysis only to carry variable info correctly.
+                               //
+                               if (end_unreachable) { // s is ExitStatement) {
+                                       for (++startIndex; startIndex < statements.Count; ++startIndex) {
+                                               s = statements[startIndex];
+                                               if (s is SwitchLabel) {
+                                                       s.FlowAnalysis (fc);
+                                                       break;
+                                               }
+
+                                               if (s.IsUnreachable) {
+                                                       s.FlowAnalysis (fc);
+                                                       statements[startIndex] = new EmptyStatement (s.loc);
+                                               }
+                                       }
+                               }
+                       }
+
+                       //
+                       // The condition should be true unless there is forward jumping goto
+                       // 
+                       // if (this is ExplicitBlock && end_unreachable != Explicit.HasReachableClosingBrace)
+                       //      Debug.Fail ();
+
+                       return !Explicit.HasReachableClosingBrace;
+               }
+
+               public void ScanGotoJump (Statement label)
+               {
+                       int i;
+                       for (i = 0; i < statements.Count; ++i) {
+                               if (statements[i] == label)
+                                       break;
+                       }
+
+                       var rc = new Reachability ();
+                       for (; i < statements.Count; ++i) {
+                               var s = statements[i];
+                               rc = s.MarkReachable (rc);
+                               if (rc.IsUnreachable)
+                                       return;
+                       }
+
+                       flags |= Flags.ReachableEnd;
+               }
+
+               public void ScanGotoJump (Statement label, FlowAnalysisContext fc)
+               {
+                       int i;
+                       for (i = 0; i < statements.Count; ++i) {
+                               if (statements[i] == label)
+                                       break;
+                       }
+
+                       DoFlowAnalysis (fc, ++i);
+               }
+
 #if DEBUG
                public override string ToString ()
                {
@@ -2497,6 +3023,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public bool HasReachableClosingBrace {
+                   get {
+                       return (flags & Flags.ReachableEnd) != 0;
+                   }
+                       set {
+                               flags = value ? flags | Flags.ReachableEnd : flags & ~Flags.ReachableEnd;
+                       }
+               }
+
                public bool HasYield {
                        get {
                                return (flags & Flags.YieldBlock) != 0;
@@ -2551,7 +3086,8 @@ namespace Mono.CSharp {
                        if (Parent != null)
                                ec.EndScope ();
 
-                       if (ec.EmitAccurateDebugInfo && !HasUnreachableClosingBrace && !IsCompilerGenerated && ec.Mark (EndLocation)) {
+                       if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
+                               !IsCompilerGenerated && ec.Mark (EndLocation)) {
                                ec.Emit (OpCodes.Nop);
                        }
                }
@@ -2744,6 +3280,16 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void SetCatchBlock ()
+               {
+                       flags |= Flags.CatchBlock;
+               }
+
+               public void SetFinallyBlock ()
+               {
+                       flags |= Flags.FinallyBlock;
+               }
+
                public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock)
                {
                        tryBlock.statements = statements;
@@ -2879,12 +3425,11 @@ namespace Mono.CSharp {
 
                protected ParametersCompiled parameters;
                protected ParameterInfo[] parameter_info;
-               bool resolved;
-               protected bool unreachable;
+               protected bool resolved;
                protected ToplevelBlock top_block;
                protected StateMachine state_machine;
 
-               public ParametersBlock (Block parent, ParametersCompiled parameters, Location start)
+               public ParametersBlock (Block parent, ParametersCompiled parameters, Location start, Flags flags = 0)
                        : base (parent, 0, start, start)
                {
                        if (parameters == null)
@@ -2893,7 +3438,7 @@ namespace Mono.CSharp {
                        this.parameters = parameters;
                        ParametersBlock = this;
 
-                       flags |= (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
+                       this.flags |= flags | (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
 
                        this.top_block = parent.ParametersBlock.top_block;
                        ProcessParameters ();
@@ -2920,9 +3465,10 @@ namespace Mono.CSharp {
                        this.scope_initializers = source.scope_initializers;
 
                        this.resolved = true;
-                       this.unreachable = source.unreachable;
+                       this.reachable = source.reachable;
                        this.am_storey = source.am_storey;
                        this.state_machine = source.state_machine;
+                       this.flags = source.flags & Flags.ReachableEnd;
 
                        ParametersBlock = this;
 
@@ -2984,30 +3530,30 @@ namespace Mono.CSharp {
 
                #endregion
 
-               // <summary>
-               //   Check whether all `out' parameters have been assigned.
-               // </summary>
-               public void CheckOutParameters (FlowBranching.UsageVector vector)
+               //
+               // Checks whether all `out' parameters have been assigned.
+               //
+               public void CheckOutParametersAssignment (FlowAnalysisContext fc)
                {
-                       if (vector.IsUnreachable)
-                               return;
-
-                       int n = parameter_info == null ? 0 : parameter_info.Length;
+                       CheckOutParametersAssignment (fc, fc.DefiniteAssignment);
+               }
 
-                       for (int i = 0; i < n; i++) {
-                               VariableInfo var = parameter_info[i].VariableInfo;
+               public void CheckOutParametersAssignment (FlowAnalysisContext fc, DefiniteAssignmentBitSet dat)
+               {
+                       if (parameter_info == null)
+                               return;
 
-                               if (var == null)
+                       foreach (var p in parameter_info) {
+                               if (p.VariableInfo == null)
                                        continue;
 
-                               if (vector.IsAssigned (var, false))
+                               if (p.VariableInfo.IsAssigned (dat))
                                        continue;
 
-                               var p = parameter_info[i].Parameter;
-                               TopBlock.Report.Error (177, p.Location,
+                               fc.Report.Error (177, p.Location,
                                        "The out parameter `{0}' must be assigned to before control leaves the current method",
-                                       p.Name);
-                       }
+                                       p.Parameter.Name);
+                       }                                       
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -3043,6 +3589,16 @@ namespace Mono.CSharp {
                        base.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var res = base.DoFlowAnalysis (fc);
+
+                       if (HasReachableClosingBrace)
+                               CheckOutParametersAssignment (fc);
+
+                       return res;
+               }
+
                public ParameterInfo GetParameterInfo (Parameter p)
                {
                        for (int i = 0; i < parameters.Count; ++i) {
@@ -3082,67 +3638,48 @@ namespace Mono.CSharp {
                        }
                }
 
-               public bool Resolve (FlowBranching parent, BlockContext rc, IMethodData md)
+               public override bool Resolve (BlockContext bc)
                {
+                       // TODO: if ((flags & Flags.Resolved) != 0)
+
                        if (resolved)
                                return true;
 
                        resolved = true;
 
-                       if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
+                       if (bc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
                                flags |= Flags.IsExpressionTree;
 
                        try {
-                               PrepareAssignmentAnalysis (rc);
-
-                               using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) {
-                                       FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent);
+                               PrepareAssignmentAnalysis (bc);
 
-                                       if (!Resolve (rc))
-                                               return false;
+                               if (!base.Resolve (bc))
+                                       return false;
 
-                                       unreachable = top_level.End ();
-                               }
                        } catch (Exception e) {
-                               if (e is CompletionResult || rc.Report.IsDisabled || e is FatalException || rc.Report.Printer is NullReportPrinter)
+                               if (e is CompletionResult || bc.Report.IsDisabled || e is FatalException || bc.Report.Printer is NullReportPrinter)
                                        throw;
 
-                               if (rc.CurrentBlock != null) {
-                                       rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
+                               if (bc.CurrentBlock != null) {
+                                       bc.Report.Error (584, bc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
                                } else {
-                                       rc.Report.Error (587, "Internal compiler error: {0}", e.Message);
+                                       bc.Report.Error (587, "Internal compiler error: {0}", e.Message);
                                }
 
-                               if (rc.Module.Compiler.Settings.DebugFlags > 0)
+                               if (bc.Module.Compiler.Settings.DebugFlags > 0)
                                        throw;
                        }
 
-                       if (rc.ReturnType.Kind != MemberKind.Void && !unreachable) {
-                               if (rc.CurrentAnonymousMethod == null) {
-                                       // FIXME: Missing FlowAnalysis for generated iterator MoveNext method
-                                       if (md is StateMachineMethod) {
-                                               unreachable = true;
-                                       } else {
-                                               rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
-                                               return false;
-                                       }
-                               } else {
-                                       //
-                                       // If an asynchronous body of F is either an expression classified as nothing, or a 
-                                       // statement block where no return statements have expressions, the inferred return type is Task
-                                       //
-                                       if (IsAsync) {
-                                               var am = rc.CurrentAnonymousMethod as AnonymousMethodBody;
-                                               if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) {
-                                                       am.ReturnTypeInference = null;
-                                                       am.ReturnType = rc.Module.PredefinedTypes.Task.TypeSpec;
-                                                       return true;
-                                               }
-                                       }
-
-                                       rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
-                                                         rc.CurrentAnonymousMethod.GetSignatureForError ());
-                                       return false;
+                       //
+                       // If an asynchronous body of F is either an expression classified as nothing, or a 
+                       // statement block where no return statements have expressions, the inferred return type is Task
+                       //
+                       if (IsAsync) {
+                               var am = bc.CurrentAnonymousMethod as AnonymousMethodBody;
+                               if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) {
+                                       am.ReturnTypeInference = null;
+                                       am.ReturnType = bc.Module.PredefinedTypes.Task.TypeSpec;
+                                       return true;
                                }
                        }
 
@@ -3169,9 +3706,8 @@ namespace Mono.CSharp {
                        state_machine = stateMachine;
                        iterator.SetStateMachine (stateMachine);
 
-                       var tlb = new ToplevelBlock (host.Compiler, Parameters, Location.Null);
+                       var tlb = new ToplevelBlock (host.Compiler, Parameters, Location.Null, Flags.CompilerGenerated);
                        tlb.Original = this;
-                       tlb.IsCompilerGenerated = true;
                        tlb.state_machine = stateMachine;
                        tlb.AddStatement (new Return (iterator, iterator.Location));
                        return tlb;
@@ -3216,16 +3752,15 @@ namespace Mono.CSharp {
                        state_machine = stateMachine;
                        initializer.SetStateMachine (stateMachine);
 
+                       const Flags flags = Flags.CompilerGenerated;
+
                        var b = this is ToplevelBlock ?
-                               new ToplevelBlock (host.Compiler, Parameters, Location.Null) :
-                               new ParametersBlock (Parent, parameters, Location.Null) {
-                                       IsAsync = true,
-                               };
+                               new ToplevelBlock (host.Compiler, Parameters, Location.Null, flags) :
+                               new ParametersBlock (Parent, parameters, Location.Null, flags | Flags.HasAsyncModifier);
 
                        b.Original = this;
-                       b.IsCompilerGenerated = true;
                        b.state_machine = stateMachine;
-                       b.AddStatement (new StatementExpression (initializer));
+                       b.AddStatement (new AsyncInitializerStatement (initializer));
                        return b;
                }
        }
@@ -3247,12 +3782,12 @@ namespace Mono.CSharp {
                {
                }
 
-               public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start)
+               public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start, Flags flags = 0)
                        : base (parameters, start)
                {
                        this.compiler = ctx;
+                       this.flags = flags;
                        top_block = this;
-                       flags |= Flags.HasRet;
 
                        ProcessParameters ();
                }
@@ -3268,7 +3803,6 @@ namespace Mono.CSharp {
                {
                        this.compiler = source.TopBlock.compiler;
                        top_block = this;
-                       flags |= Flags.HasRet;
                }
 
                public bool IsIterator {
@@ -3543,8 +4077,11 @@ namespace Mono.CSharp {
                        var label = value as LabeledStatement;
                        Block b = block;
                        if (label != null) {
-                               if (label.Block == b.Original)
-                                       return label;
+                               do {
+                                       if (label.Block == b.Original)
+                                               return label;
+                                       b = b.Parent;
+                               } while (b != null);
                        } else {
                                List<LabeledStatement> list = (List<LabeledStatement>) value;
                                for (int i = 0; i < list.Count; ++i) {
@@ -3574,9 +4111,21 @@ namespace Mono.CSharp {
                        this_variable.PrepareAssignmentAnalysis (bc);
                }
 
-               public bool IsThisAssigned (BlockContext ec)
+               public bool IsThisAssigned (FlowAnalysisContext fc)
                {
-                       return this_variable == null || this_variable.IsThisAssigned (ec, this);
+                       return this_variable == null || this_variable.IsThisAssigned (fc, this);
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var res = base.DoFlowAnalysis (fc);
+
+                       //
+                       // If we're a non-static struct constructor which doesn't have an
+                       // initializer, then we must initialize all of the struct's fields.
+                       //
+                       IsThisAssigned (fc);
+                       return res;
                }
 
                public override void Emit (EmitContext ec)
@@ -3605,7 +4154,7 @@ namespace Mono.CSharp {
                        // As a workaround, we're always creating a return label in
                        // this case.
                        //
-                       if (ec.HasReturnLabel || !unreachable) {
+                       if (ec.HasReturnLabel || HasReachableClosingBrace) {
                                if (ec.HasReturnLabel)
                                        ec.MarkLabel (ec.ReturnLabel);
 
@@ -3622,12 +4171,44 @@ namespace Mono.CSharp {
                                throw new InternalErrorException (e, StartLocation);
                        }
                }
+
+               public bool Resolve (BlockContext bc, IMethodData md)
+               {
+                       if (resolved)
+                               return true;
+
+                       var errors = bc.Report.Errors;
+
+                       base.Resolve (bc);
+
+                       if (bc.Report.Errors > errors)
+                               return false;
+
+                       MarkReachable (new Reachability ());
+
+                       if (HasReachableClosingBrace && bc.ReturnType.Kind != MemberKind.Void) {
+                               // TODO: var md = bc.CurrentMemberDefinition;
+                               bc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+                       }
+
+                       if ((flags & Flags.NoFlowAnalysis) != 0)
+                               return true;
+
+                       var fc = new FlowAnalysisContext (bc.Module.Compiler, this);
+                       try {
+                               FlowAnalysis (fc);
+                       } catch (Exception e) {
+                               throw new InternalErrorException (e, StartLocation);
+                       }
+
+                       return true;
+               }
        }
        
        public class SwitchLabel : Statement
        {
-               Expression label;
                Constant converted;
+               Expression label;
 
                Label? il_label;
 
@@ -3663,7 +4244,7 @@ namespace Mono.CSharp {
                                return converted;
                        }
                        set {
-                               converted = value;
+                               converted = value; 
                        }
                }
 
@@ -3683,21 +4264,34 @@ namespace Mono.CSharp {
                        ec.MarkLabel (GetILLabel (ec));
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (!SectionStart)
+                               return false;
+
+                       if (IsUnreachable) {
+                               fc.DefiniteAssignment = new DefiniteAssignmentBitSet (fc.SwitchInitialDefinitiveAssignment);
+                       } else {
+                               fc.Report.Error (163, Location,
+                                       "Control cannot fall through from one case label `{0}' to another", GetSignatureForError ());
+                       }
+
+                       return false;
+               }
+
                public override bool Resolve (BlockContext bc)
                {
                        if (ResolveAndReduce (bc))
                                bc.Switch.RegisterLabel (bc, this);
 
-                       bc.CurrentBranching.CurrentUsageVector.ResetBarrier ();
-
-                       return base.Resolve (bc);
+                       return true;
                }
 
                //
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
-               bool ResolveAndReduce (ResolveContext rc)
+               bool ResolveAndReduce (BlockContext rc)
                {
                        if (IsDefault)
                                return true;
@@ -3717,14 +4311,8 @@ namespace Mono.CSharp {
 
                public void Error_AlreadyOccurs (ResolveContext ec, SwitchLabel collision_with)
                {
-                       string label;
-                       if (converted == null)
-                               label = "default";
-                       else
-                               label = converted.GetValueAsLiteral ();
-                       
                        ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null);
-                       ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
+                       ec.Report.Error (152, loc, "The label `{0}' already occurs in this switch statement", GetSignatureForError ());
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -3738,9 +4326,20 @@ namespace Mono.CSharp {
                {
                        return visitor.Visit (this);
                }
+
+               string GetSignatureForError ()
+               {
+                       string label;
+                       if (converted == null)
+                               label = "default";
+                       else
+                               label = converted.GetValueAsLiteral ();
+
+                       return string.Format ("case {0}:", label);
+               }
        }
 
-       public class Switch : Statement
+       public class Switch : LoopStatement
        {
                // structure used to hold blocks of keys while calculating table switch
                sealed class LabelsRange : IComparable<LabelsRange>
@@ -3806,6 +4405,11 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               return false;
+                       }
+
                        protected override void DoEmit (EmitContext ec)
                        {
                                body.EmitDispatch (ec);
@@ -3822,6 +4426,7 @@ namespace Mono.CSharp {
                List<SwitchLabel> case_labels;
 
                List<Tuple<GotoCase, Constant>> goto_cases;
+               List<DefiniteAssignmentBitSet> end_reachable_das;
 
                /// <summary>
                ///   The governing switch type
@@ -3838,6 +4443,7 @@ namespace Mono.CSharp {
                ExpressionStatement string_dictionary;
                FieldExpr switch_cache_field;
                ExplicitBlock block;
+               bool end_reachable;
 
                //
                // Nullable Types support
@@ -3845,12 +4451,15 @@ namespace Mono.CSharp {
                Nullable.Unwrap unwrap;
 
                public Switch (Expression e, ExplicitBlock block, Location l)
+                       : base (block)
                {
                        Expr = e;
                        this.block = block;
                        loc = l;
                }
 
+               public SwitchLabel ActiveLabel { get; set; }
+
                public ExplicitBlock Block {
                        get {
                                return block;
@@ -3869,6 +4478,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public List<SwitchLabel> RegisteredLabels {
+                       get {
+                               return case_labels;
+                       }
+               }
+
                //
                // Determines the governing type for a switch.  The returned
                // expression might be the expression from the switch, or an
@@ -3942,7 +4557,7 @@ namespace Mono.CSharp {
                        };
                }
 
-               public void RegisterLabel (ResolveContext rc, SwitchLabel sl)
+               public void RegisterLabel (BlockContext rc, SwitchLabel sl)
                {
                        case_labels.Add (sl);
 
@@ -4128,7 +4743,30 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       return sl;
+                       return sl;
+               }
+
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       Expr.FlowAnalysis (fc);
+
+                       var prev_switch = fc.SwitchInitialDefinitiveAssignment;
+                       var InitialDefinitiveAssignment = fc.DefiniteAssignment;
+                       fc.SwitchInitialDefinitiveAssignment = InitialDefinitiveAssignment;
+
+                       block.FlowAnalysis (fc);
+
+                       fc.SwitchInitialDefinitiveAssignment = prev_switch;
+
+                       if (end_reachable_das != null) {
+                               var sections_das = DefiniteAssignmentBitSet.And (end_reachable_das);
+                               InitialDefinitiveAssignment |= sections_das;
+                               end_reachable_das = null;
+                       }
+
+                       fc.DefiniteAssignment = InitialDefinitiveAssignment;
+
+                       return case_default != null && !end_reachable;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -4199,33 +4837,23 @@ namespace Mono.CSharp {
 
                        Switch old_switch = ec.Switch;
                        ec.Switch = this;
-                       ec.Switch.SwitchType = SwitchType;
-
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
-
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
+                       var parent_los = ec.EnclosingLoopOrSwitch;
+                       ec.EnclosingLoopOrSwitch = this;
 
-                       var ok = block.Resolve (ec);
-
-                       if (case_default == null)
-                               ec.CurrentBranching.CreateSibling (null, FlowBranching.SiblingType.SwitchSection);
-
-                       if (ec.IsUnreachable)
-                               ec.KillFlowBranching ();
-                       else
-                               ec.EndFlowBranching ();
+                       var ok = Statement.Resolve (ec);
 
+                       ec.EnclosingLoopOrSwitch = parent_los;
                        ec.Switch = old_switch;
 
                        //
                        // Check if all goto cases are valid. Needs to be done after switch
-                       // is resolved becuase goto can jump forward in the scope.
+                       // is resolved because goto can jump forward in the scope.
                        //
                        if (goto_cases != null) {
                                foreach (var gc in goto_cases) {
                                        if (gc.Item1 == null) {
                                                if (DefaultLabel == null) {
-                                                       FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report);
+                                                       Goto.Error_UnknownLabel (ec, "default", loc);
                                                }
 
                                                continue;
@@ -4233,17 +4861,13 @@ namespace Mono.CSharp {
 
                                        var sl = FindLabel (gc.Item2);
                                        if (sl == null) {
-                                               FlowBranchingBlock.Error_UnknownLabel (loc, "case " + gc.Item2.GetValueAsLiteral (), ec.Report);
+                                               Goto.Error_UnknownLabel (ec, "case " + gc.Item2.GetValueAsLiteral (), loc);
                                        } else {
                                                gc.Item1.Label = sl;
                                        }
                                }
                        }
 
-                       if (constant != null) {
-                               ResolveUnreachableSections (ec, constant);
-                       }
-
                        if (!ok)
                                return false;
 
@@ -4274,6 +4898,87 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       SwitchLabel constant_label = null;
+                       var constant = new_expr as Constant;
+                       if (constant != null) {
+                               constant_label = FindLabel (constant) ?? case_default;
+                               if (constant_label == null) {
+                                       block.Statements.RemoveAt (0);
+                                       return rc;
+                               }
+                       }
+
+                       var switch_rc = rc;
+                       var section_rc = new Reachability ();
+                       SwitchLabel prev_label = null;
+
+                       for (int i = 0; i < block.Statements.Count; ++i) {
+                               var s = block.Statements[i];
+                               var sl = s as SwitchLabel;
+
+                               if (sl != null) {
+                                       if (!sl.SectionStart) {
+                                               sl.MarkReachable (section_rc);
+                                               continue;
+                                       }
+
+                                       if (prev_label == null) {
+                                               prev_label = sl;
+                                               switch_rc = Reachability.CreateUnreachable ();
+
+                                               if (constant_label != null && sl != constant_label)
+                                                       section_rc = Reachability.CreateUnreachable ();
+
+                                               continue;
+                                       }
+
+                                       //
+                                       // Small trick, using unreachable flag for label means
+                                       // the label section does not fallthrough
+                                       //
+                                       prev_label.MarkReachable (section_rc);
+
+                                       prev_label = sl;
+                                       switch_rc &= section_rc;
+                                       section_rc = new Reachability ();
+
+                                       if (constant_label != null && sl != constant_label)
+                                               section_rc = Reachability.CreateUnreachable ();
+
+                                       continue;
+                               }
+
+                               section_rc = s.MarkReachable (section_rc);
+                       }
+
+                       if (prev_label != null) {
+                               prev_label.MarkReachable (section_rc);
+                               switch_rc &= section_rc;
+                       }
+
+                       //
+                       // Reachability can affect parent only when all possible paths are handled but
+                       // we still need to run reachability check on switch body to check for fall-through
+                       //
+                       if (case_default == null && constant_label == null)
+                               return rc;
+
+                       //
+                       // We have at least one local exit from the switch
+                       //
+                       if (end_reachable)
+                               return rc;
+
+                       return switch_rc;
+               }
+
                public void RegisterGotoCase (GotoCase gotoCase, Constant value)
                {
                        if (goto_cases == null)
@@ -4340,40 +5045,6 @@ namespace Mono.CSharp {
                        string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec));
                }
 
-               void ResolveUnreachableSections (BlockContext bc, Constant value)
-               {
-                       var constant_label = FindLabel (value) ?? case_default;
-
-                       bool found = false;
-                       bool unreachable_reported = false;
-                       for (int i = 0; i < block.Statements.Count; ++i) {
-                               var s = block.Statements[i];
-
-                               if (s is SwitchLabel) {
-                                       if (unreachable_reported) {
-                                               found = unreachable_reported = false;
-                                       }
-
-                                       found |= s == constant_label;
-                                       continue;
-                               }
-
-                               if (found) {
-                                       unreachable_reported = true;
-                                       continue;
-                               }
-
-                               if (!unreachable_reported) {
-                                       unreachable_reported = true;
-                                       if (!bc.IsUnreachable) {
-                                               bc.Report.Warning (162, 2, s.loc, "Unreachable code detected");
-                                       }
-                               }
-
-                               block.Statements[i] = new EmptyStatement (s.loc);
-                       }
-               }
-
                void DoEmitStringSwitch (EmitContext ec)
                {
                        Label l_initialized = ec.DefineLabel ();
@@ -4495,9 +5166,6 @@ namespace Mono.CSharp {
 
                protected override void DoEmit (EmitContext ec)
                {
-                       // Workaround broken flow-analysis
-                       block.HasUnreachableClosingBrace = true;
-
                        //
                        // Setup the codegen context
                        //
@@ -4546,16 +5214,32 @@ namespace Mono.CSharp {
                        Switch target = (Switch) t;
 
                        target.Expr = Expr.Clone (clonectx);
-                       target.block = (ExplicitBlock) block.Clone (clonectx);
+                       target.Statement = target.block = (ExplicitBlock) block.Clone (clonectx);
                }
                
                public override object Accept (StructuralVisitor visitor)
                {
                        return visitor.Visit (this);
                }
+
+               public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+               {
+                       if (case_default == null)
+                               return;
+
+                       if (end_reachable_das == null)
+                               end_reachable_das = new List<DefiniteAssignmentBitSet> ();
+
+                       end_reachable_das.Add (fc.DefiniteAssignment);
+               }
+
+               public override void SetEndReachable ()
+               {
+                       end_reachable = true;
+               }
        }
 
-       // A place where execution can restart in an iterator
+       // A place where execution can restart in a state machine
        public abstract class ResumableStatement : Statement
        {
                bool prepared;
@@ -4715,8 +5399,32 @@ namespace Mono.CSharp {
                        ec.EndExceptionBlock ();
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var res = stmt.FlowAnalysis (fc);
+                       parent = null;
+                       return res;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Statement.MarkReachable (rc);
+               }
+
                public override bool Resolve (BlockContext bc)
                {
+                       bool ok;
+
+                       parent = bc.CurrentTryBlock;
+                       bc.CurrentTryBlock = this;
+
+                       using (bc.Set (ResolveContext.Options.TryScope)) {
+                               ok = stmt.Resolve (bc);
+                       }
+
+                       bc.CurrentTryBlock = parent;
+
                        //
                        // Finally block inside iterator is called from MoveNext and
                        // Dispose methods that means we need to lift the block into
@@ -4730,7 +5438,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       return base.Resolve (bc);
+                       return base.Resolve (bc) && ok;
                }
        }
 
@@ -4739,11 +5447,9 @@ namespace Mono.CSharp {
        //
        public abstract class ExceptionStatement : ResumableStatement
        {
-#if !STATIC
-               bool code_follows;
-#endif
                protected List<ResumableStatement> resume_points;
                protected int first_resume_pc;
+               protected ExceptionStatement parent;
 
                protected ExceptionStatement (Location loc)
                {
@@ -4778,26 +5484,18 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void SomeCodeFollows ()
+               public virtual int AddResumePoint (ResumableStatement stmt, int pc, StateMachineInitializer stateMachine)
                {
-#if !STATIC
-                       code_follows = true;
-#endif
-               }
+                       if (parent != null) {
+                               // TODO: MOVE to virtual TryCatch
+                               var tc = this as TryCatch;
+                               var s = tc != null && tc.IsTryCatchFinally ? stmt : this;
 
-               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;
-               }
+                               pc = parent.AddResumePoint (s, pc, stateMachine);
+                       } else {
+                               pc = stateMachine.AddResumePoint (this);
+                       }
 
-               public void AddResumePoint (ResumableStatement stmt, int pc)
-               {
                        if (resume_points == null) {
                                resume_points = new List<ResumableStatement> ();
                                first_resume_pc = pc;
@@ -4807,8 +5505,8 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("missed an intervening AddResumePoint?");
 
                        resume_points.Add (stmt);
+                       return pc;
                }
-
        }
 
        public class Lock : TryFinallyBlock
@@ -4871,17 +5569,13 @@ namespace Mono.CSharp {
                        }
 
                        using (ec.Set (ResolveContext.Options.LockScope)) {
-                               ec.StartFlowBranching (this);
-                               Statement.Resolve (ec);
-                               ec.EndFlowBranching ();
+                               base.Resolve (ec);
                        }
 
                        if (lv != null) {
                                lv.IsLockedByStatement = locked;
                        }
 
-                       base.Resolve (ec);
-
                        return true;
                }
                
@@ -4992,6 +5686,17 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return Block.FlowAnalysis (fc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Block.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unchecked target = (Unchecked) t;
@@ -5027,6 +5732,17 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return Block.FlowAnalysis (fc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Block.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Checked target = (Checked) t;
@@ -5064,6 +5780,17 @@ namespace Mono.CSharp {
                        Block.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       return Block.FlowAnalysis (fc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+                       return Block.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unsafe target = (Unsafe) t;
@@ -5093,6 +5820,11 @@ namespace Mono.CSharp {
                        }
 
                        public abstract void EmitExit (EmitContext ec);
+
+                       public override void FlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               expr.FlowAnalysis (fc);
+                       }
                }
 
                class ExpressionEmitter : Emitter {
@@ -5306,19 +6038,20 @@ namespace Mono.CSharp {
 
                #endregion
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       using (ec.Set (ResolveContext.Options.FixedInitializerScope)) {
-                               if (!decl.Resolve (ec))
+                       using (bc.Set (ResolveContext.Options.FixedInitializerScope)) {
+                               if (!decl.Resolve (bc))
                                        return false;
                        }
 
-                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
-                       bool ok = statement.Resolve (ec);
-                       bool flow_unreachable = ec.EndFlowBranching ();
-                       has_ret = flow_unreachable;
+                       return statement.Resolve (bc);
+               }
 
-                       return ok;
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       decl.FlowAnalysis (fc);
+                       return statement.FlowAnalysis (fc);
                }
                
                protected override void DoEmit (EmitContext ec)
@@ -5348,6 +6081,19 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       decl.MarkReachable (rc);
+
+                       rc = statement.MarkReachable (rc);
+
+                       // TODO: What if there is local exit?
+                       has_ret = rc.IsUnreachable;
+                       return rc;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Fixed target = (Fixed) t;
@@ -5364,13 +6110,13 @@ namespace Mono.CSharp {
 
        public class Catch : Statement
        {
-               Block block;
+               ExplicitBlock block;
                LocalVariable li;
                FullNamedExpression type_expr;
                CompilerAssign assign;
                TypeSpec type;
                
-               public Catch (Block block, Location loc)
+               public Catch (ExplicitBlock block, Location loc)
                {
                        this.block = block;
                        this.loc = loc;
@@ -5378,7 +6124,7 @@ namespace Mono.CSharp {
 
                #region Properties
 
-               public Block Block {
+               public ExplicitBlock Block {
                        get {
                                return block;
                        }
@@ -5447,7 +6193,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (BlockContext ec)
                {
-                       using (ec.With (ResolveContext.Options.CatchScope, true)) {
+                       using (ec.Set (ResolveContext.Options.CatchScope)) {
                                if (type_expr != null) {
                                        type = type_expr.ResolveAsType (ec);
                                        if (type == null)
@@ -5472,10 +6218,27 @@ namespace Mono.CSharp {
                                        }
                                }
 
+                               Block.SetCatchBlock ();
                                return Block.Resolve (ec);
                        }
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       if (li != null) {
+                               fc.SetVariableAssigned (li.VariableInfo, true);
+                       }
+
+                       return block.FlowAnalysis (fc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       return block.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Catch target = (Catch) t;
@@ -5483,47 +6246,44 @@ namespace Mono.CSharp {
                        if (type_expr != null)
                                target.type_expr = (FullNamedExpression) type_expr.Clone (clonectx);
 
-                       target.block = clonectx.LookupBlock (block);
+                       target.block = (ExplicitBlock) clonectx.LookupBlock (block);
                }
        }
 
        public class TryFinally : TryFinallyBlock
        {
-               Block fini;
+               ExplicitBlock fini;
+               List<DefiniteAssignmentBitSet> try_exit_dat;
 
-               public TryFinally (Statement stmt, Block fini, Location loc)
+               public TryFinally (Statement stmt, ExplicitBlock fini, Location loc)
                         : base (stmt, loc)
                {
                        this.fini = fini;
                }
 
-               public Block Finallyblock {
+               public ExplicitBlock FinallyBlock {
                        get {
                                return fini;
                        }
                }
 
-               public override bool Resolve (BlockContext ec)
+               public void RegisterOutParametersCheck (DefiniteAssignmentBitSet vector)
                {
-                       bool ok = true;
+                       if (try_exit_dat == null)
+                               try_exit_dat = new List<DefiniteAssignmentBitSet> ();
 
-                       ec.StartFlowBranching (this);
-
-                       if (!stmt.Resolve (ec))
-                               ok = false;
+                       try_exit_dat.Add (vector);
+               }
 
-                       if (ok)
-                               ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally);
+               public override bool Resolve (BlockContext bc)
+               {
+                       bool ok = base.Resolve (bc);
 
-                       using (ec.With (ResolveContext.Options.FinallyScope, true)) {
-                               if (!fini.Resolve (ec))
-                                       ok = false;
+                       fini.SetFinallyBlock ();
+                       using (bc.Set (ResolveContext.Options.FinallyScope)) {
+                               ok &= fini.Resolve (bc);
                        }
 
-                       ec.EndFlowBranching ();
-
-                       ok &= base.Resolve (ec);
-
                        return ok;
                }
 
@@ -5537,13 +6297,54 @@ namespace Mono.CSharp {
                        fini.Emit (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var da = fc.BranchDefiniteAssignment ();
+
+                       var tf = fc.TryFinally;
+                       fc.TryFinally = this;
+
+                       var res_stmt = Statement.FlowAnalysis (fc);
+
+                       fc.TryFinally = tf;
+
+                       var try_da = fc.DefiniteAssignment;
+                       fc.DefiniteAssignment = da;
+
+                       var res_fin = fini.FlowAnalysis (fc);
+
+                       if (try_exit_dat != null) {
+                               //
+                               // try block has global exit but we need to run definite assignment check
+                               // for parameter block out parameter after finally block because it's always
+                               // executed before exit
+                               //
+                               foreach (var try_da_part in try_exit_dat)
+                                       fc.ParametersBlock.CheckOutParametersAssignment (fc, fc.DefiniteAssignment | try_da_part);
+
+                               try_exit_dat = null;
+                       }
+
+                       fc.DefiniteAssignment |= try_da;
+                       return res_stmt | res_fin;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       //
+                       // Mark finally block first for any exit statement in try block
+                       // to know whether the code which follows finally is reachable
+                       //
+                       return fini.MarkReachable (rc) | base.MarkReachable (rc);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryFinally target = (TryFinally) t;
 
                        target.stmt = stmt.Clone (clonectx);
                        if (fini != null)
-                               target.fini = clonectx.LookupBlock (fini);
+                               target.fini = (ExplicitBlock) clonectx.LookupBlock (fini);
                }
                
                public override object Accept (StructuralVisitor visitor)
@@ -5578,23 +6379,28 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override bool Resolve (BlockContext ec)
+               public override bool Resolve (BlockContext bc)
                {
-                       bool ok = true;
+                       bool ok;
 
-                       ec.StartFlowBranching (this);
+                       using (bc.Set (ResolveContext.Options.TryScope)) {
+                               parent = bc.CurrentTryBlock;
 
-                       if (!Block.Resolve (ec))
-                               ok = false;
+                               if (IsTryCatchFinally) {
+                                       ok = Block.Resolve (bc);
+                               } else {
+                                       using (bc.Set (ResolveContext.Options.TryWithCatchScope)) {
+                                               bc.CurrentTryBlock = this;
+                                               ok = Block.Resolve (bc);
+                                               bc.CurrentTryBlock = parent;
+                                       }
+                               }
+                       }
 
                        for (int i = 0; i < clauses.Count; ++i) {
                                var c = clauses[i];
-                               ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch);
 
-                               if (!c.Resolve (ec)) {
-                                       ok = false;
-                                       continue;
-                               }
+                               ok &= c.Resolve (bc);
 
                                TypeSpec resolved_type = c.CatchType;
                                for (int ii = 0; ii < clauses.Count; ++ii) {
@@ -5605,13 +6411,13 @@ namespace Mono.CSharp {
                                                if (resolved_type.BuiltinType != BuiltinTypeSpec.Type.Exception)
                                                        continue;
 
-                                               if (!ec.Module.DeclaringAssembly.WrapNonExceptionThrows)
+                                               if (!bc.Module.DeclaringAssembly.WrapNonExceptionThrows)
                                                        continue;
 
-                                               if (!ec.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined)
+                                               if (!bc.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined)
                                                        continue;
 
-                                               ec.Report.Warning (1058, 1, c.loc,
+                                               bc.Report.Warning (1058, 1, c.loc,
                                                        "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
 
                                                continue;
@@ -5625,7 +6431,7 @@ namespace Mono.CSharp {
                                                continue;
 
                                        if (resolved_type == ct || TypeSpec.IsBaseClass (resolved_type, ct, true)) {
-                                               ec.Report.Error (160, c.loc,
+                                               bc.Report.Error (160, c.loc,
                                                        "A previous catch clause already catches all exceptions of this or a super type `{0}'",
                                                        ct.GetSignatureForError ());
                                                ok = false;
@@ -5633,9 +6439,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ec.EndFlowBranching ();
-
-                       return base.Resolve (ec) && ok;
+                       return base.Resolve (bc) && ok;
                }
 
                protected sealed override void DoEmit (EmitContext ec)
@@ -5652,6 +6456,45 @@ namespace Mono.CSharp {
                                ec.EndExceptionBlock ();
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       var start_fc = fc.BranchDefiniteAssignment ();
+                       var res = Block.FlowAnalysis (fc);
+
+                       DefiniteAssignmentBitSet try_fc = res ? null : fc.DefiniteAssignment;
+
+                       foreach (var c in clauses) {
+                               fc.DefiniteAssignment = new DefiniteAssignmentBitSet (start_fc);
+                               if (!c.FlowAnalysis (fc)) {
+                                       if (try_fc == null)
+                                               try_fc = fc.DefiniteAssignment;
+                                       else
+                                               try_fc &= fc.DefiniteAssignment;
+
+                                       res = false;
+                               }
+                       }
+
+                       fc.DefiniteAssignment = try_fc ?? start_fc;
+                       parent = null;
+                       return res;
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       if (rc.IsUnreachable)
+                               return rc;
+
+                       base.MarkReachable (rc);
+
+                       var tc_rc = Block.MarkReachable (rc);
+
+                       foreach (var c in clauses)
+                               tc_rc &= c.MarkReachable (rc);
+
+                       return tc_rc;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryCatch target = (TryCatch) t;
@@ -5881,6 +6724,18 @@ namespace Mono.CSharp {
                        decl.EmitDispose (ec);
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       decl.FlowAnalysis (fc);
+                       return stmt.FlowAnalysis (fc);
+               }
+
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       decl.MarkReachable (rc);
+                       return base.MarkReachable (rc);
+               }
+
                public override bool Resolve (BlockContext ec)
                {
                        VariableReference vr;
@@ -5909,17 +6764,11 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       ec.StartFlowBranching (this);
-
-                       stmt.Resolve (ec);
-
-                       ec.EndFlowBranching ();
+                       base.Resolve (ec);
 
                        if (vr != null)
                                vr.IsLockedByStatement = vr_locked;
 
-                       base.Resolve (ec);
-
                        return true;
                }
 
@@ -5940,7 +6789,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Implementation of the foreach C# statement
        /// </summary>
-       public class Foreach : Statement
+       public class Foreach : LoopStatement
        {
                abstract class IteratorStatement : Statement
                {
@@ -5965,6 +6814,11 @@ namespace Mono.CSharp {
 
                                base.Emit (ec);
                        }
+
+                       protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+                       {
+                               throw new NotImplementedException ();
+                       }
                }
 
                sealed class ArrayForeach : IteratorStatement
@@ -6046,22 +6900,7 @@ namespace Mono.CSharp {
 
                                for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, access, Location.Null), for_each.type.Location));
 
-                               bool ok = true;
-
-                               ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
-                               ec.CurrentBranching.CreateSibling ();
-
-                               ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
-                               if (!for_each.body.Resolve (ec))
-                                       ok = false;
-                               ec.EndFlowBranching ();
-
-                               // There's no direct control flow from the end of the embedded statement to the end of the loop
-                               ec.CurrentBranching.CurrentUsageVector.Goto ();
-
-                               ec.EndFlowBranching ();
-
-                               return ok;
+                               return for_each.body.Resolve (ec);
                        }
 
                        protected override void DoEmit (EmitContext ec)
@@ -6431,15 +7270,14 @@ namespace Mono.CSharp {
                Expression type;
                LocalVariable variable;
                Expression expr;
-               Statement statement;
                Block body;
 
                public Foreach (Expression type, LocalVariable var, Expression expr, Statement stmt, Block body, Location l)
+                       : base (stmt)
                {
                        this.type = type;
                        this.variable = var;
                        this.expr = expr;
-                       this.statement = stmt;
                        this.body = body;
                        loc = l;
                }
@@ -6448,10 +7286,6 @@ namespace Mono.CSharp {
                        get { return expr; }
                }
 
-               public Statement Statement {
-                       get { return statement; }
-               }
-
                public Expression TypeExpression {
                        get { return type; }
                }
@@ -6460,6 +7294,15 @@ namespace Mono.CSharp {
                        get { return variable; }
                }
 
+               public override Reachability MarkReachable (Reachability rc)
+               {
+                       base.MarkReachable (rc);
+
+                       body.MarkReachable (rc);
+
+                       return rc;
+               }
+
                public override bool Resolve (BlockContext ec)
                {
                        expr = expr.Resolve (ec);
@@ -6471,12 +7314,12 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       body.AddStatement (statement);
+                       body.AddStatement (Statement);
 
                        if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.String) {
-                               statement = new ArrayForeach (this, 1);
+                               Statement = new ArrayForeach (this, 1);
                        } else if (expr.Type is ArrayContainer) {
-                               statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank);
+                               Statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank);
                        } else {
                                if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
                                        ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
@@ -6484,10 +7327,11 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               statement = new CollectionForeach (this, variable, expr);
+                               Statement = new CollectionForeach (this, variable, expr);
                        }
 
-                       return statement.Resolve (ec);
+                       base.Resolve (ec);
+                       return true;
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -6496,20 +7340,30 @@ namespace Mono.CSharp {
                        ec.LoopBegin = ec.DefineLabel ();
                        ec.LoopEnd = ec.DefineLabel ();
 
-                       if (!(statement is Block))
+                       if (!(Statement is Block))
                                ec.BeginCompilerScope ();
 
                        variable.CreateBuilder (ec);
 
-                       statement.Emit (ec);
+                       Statement.Emit (ec);
 
-                       if (!(statement is Block))
+                       if (!(Statement is Block))
                                ec.EndScope ();
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
 
+               protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+               {
+                       expr.FlowAnalysis (fc);
+
+                       var da = fc.BranchDefiniteAssignment ();
+                       body.FlowAnalysis (fc);
+                       fc.DefiniteAssignment = da;
+                       return false;
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Foreach target = (Foreach) t;
@@ -6517,7 +7371,7 @@ namespace Mono.CSharp {
                        target.type = type.Clone (clonectx);
                        target.expr = expr.Clone (clonectx);
                        target.body = (Block) body.Clone (clonectx);
-                       target.statement = statement.Clone (clonectx);
+                       target.Statement = Statement.Clone (clonectx);
                }
                
                public override object Accept (StructuralVisitor visitor)
index 68d92317cacf49c25d969ed459d17f2ae6a9d051..51d0b2086fda73f48a672f0c03f5224f8d26104f 100644 (file)
@@ -5,4 +5,3 @@
 # csXXXX.cs IGNORE     : adds test to ignore list
 
 gtest-230.cs
-test-872.cs
index 35ca796e054812cb65e8e784fbb6ac37c38c3486..8b8bd6bf2e8a7290d2d665e6a7dd7722437b2f8b 100644 (file)
@@ -1,3 +1,5 @@
+using System;
+
 class Foo {
        public static int Main ()
        {
@@ -5,9 +7,17 @@ class Foo {
                        f ();
                        return 1;
                } catch {
-                       return 0;
                }
+
+               try {
+                       f2 ();
+                       return 2;
+               } catch (ApplicationException) {
+               }
+
+               return 0;
        }
+
        static void f ()
        {
                try {
@@ -20,4 +30,15 @@ class Foo {
        skip:
                ;
        }
+
+       static void f2 ()
+       {
+               try {
+                       goto FinallyExit;
+               } finally {
+                       throw new ApplicationException ();
+               }
+       FinallyExit:
+               Console.WriteLine ("Too late");
+       }
 }
index 9df2a493acda4d8ed41f70d56e5428c542011269..1f49f63c7650ecb05e0d0e870d1ac32d6b1ffd08 100644 (file)
@@ -3,6 +3,17 @@
 public class TestCase
 {
        public static int Main ()
+       {
+               if (Test1 () != 0)
+                       return 1;
+
+               if (Test2 () != 0)
+                       return 2;
+
+               return 0;
+       }
+
+       static int Test1 ()
        {
                int i = 0;
                {
@@ -21,4 +32,46 @@ public class TestCase
                        
                return 0;
        }
+
+       static int Test2 ()
+       {
+               int i = 0;
+
+               while (true) {
+                       {
+                               goto A;
+                               A:
+                                       i += 3;
+                               break;
+                       }
+               }
+
+               if (i != 3)
+                       return 1;
+
+               return 0;
+       }
+
+       static int Test3 ()
+       {
+               int i = 0;
+
+               do {
+                       {
+                               goto A;
+                               A:
+                                       i += 3;
+                               goto X;
+                               X:
+                               break;
+                       }
+#pragma warning disable 162, 429
+               } while (i > 0);
+#pragma warning restore 162, 429
+               
+               if (i != 3)
+                       return 1;
+
+               return 0;
+       }
 }
diff --git a/mcs/tests/test-874.cs b/mcs/tests/test-874.cs
new file mode 100644 (file)
index 0000000..b8f52f0
--- /dev/null
@@ -0,0 +1,18 @@
+using System;
+
+class X
+{
+       public static void Main ()
+       {
+               int a;
+               goto X;
+       A:
+               Console.WriteLine (a);
+               goto Y;
+       X:
+               a = 1;
+               goto A;
+       Y:
+               return;
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-876.cs b/mcs/tests/test-876.cs
new file mode 100644 (file)
index 0000000..8127d2b
--- /dev/null
@@ -0,0 +1,91 @@
+using System;
+
+class T
+{
+       public static int Main ()
+       {
+               Test1 ();
+               Test2 ();
+               Test3 (0, 1);
+               Test4 ();
+               
+               switch (1) {
+               case 1:
+                       return 0;
+               default:
+                       break;
+               }
+       }
+
+       static void Test1 ()
+       {
+               int g = 9;
+       A:
+               switch (g) {
+               case 4:
+                       return;
+               case 5:
+                       goto A;
+               }
+
+               switch (g) {
+               case 9:
+                       break;
+               }
+
+               return;
+       }
+       
+       static void Test2 ()
+       {
+               int a,b;
+               int g = 9;
+               if (g > 0) {
+                       a = 1;
+                       goto X;
+               } else {
+                       b = 2;
+                       goto Y;
+               }
+
+       X:
+               Console.WriteLine (a);
+               return;
+       Y:
+               Console.WriteLine (b);
+               return;
+       }
+       
+       static uint Test3 (int self, uint data)
+       {
+               uint rid;
+               switch (self) {
+               case 0:
+                       rid = 2;
+                       switch (data & 3) {
+                       case 0:
+                               goto ret;
+                       default:
+                               goto exit;
+                       }
+               default:
+                       goto exit;
+               }
+       ret:
+               return rid;
+       exit:
+               return 0;
+       }
+
+       static void Test4 ()
+       {
+               bool v;
+               try {
+                       throw new NotImplementedException ();
+               } catch (System.Exception) {
+                       v = false;
+               }
+               
+               Console.WriteLine (v);
+       }
+}
index d78064a006a24e8f8f9396f656aee8e1c46caa09..78945bd7cddea1e00b07266358452bf41d3d3c8d 100644 (file)
         <size>10</size>\r
       </method>\r
       <method name="Int32 test40(Int32)" attrs="145">\r
-        <size>27</size>\r
+        <size>20</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
   <test name="test-519.cs">\r
     <type name="Foo">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>25</size>\r
+        <size>52</size>\r
       </method>\r
       <method name="Void f()" attrs="145">\r
-        <size>21</size>\r
+        <size>23</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       </method>\r
+      <method name="Void f2()" attrs="145">\r
+        <size>16</size>\r
+      </method>\r
     </type>\r
   </test>\r
   <test name="test-52.cs">\r
   <test name="test-579.cs">\r
     <type name="TestCase">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>49</size>\r
+        <size>44</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
       </method>\r
+      <method name="Int32 Test1()" attrs="145">\r
+        <size>49</size>\r
+      </method>\r
+      <method name="Int32 Test2()" attrs="145">\r
+        <size>48</size>\r
+      </method>\r
+      <method name="Int32 Test3()" attrs="145">\r
+        <size>47</size>\r
+      </method>\r
     </type>\r
   </test>\r
   <test name="test-58.cs">\r
   <test name="test-634.cs">\r
     <type name="Test">\r
       <method name="Void TestFunc()" attrs="150">\r
-        <size>7</size>\r
+        <size>13</size>\r
       </method>\r
       <method name="Void Main(System.String[])" attrs="150">\r
         <size>7</size>\r
         <size>0</size>\r
       </method>\r
     </type>\r
+    <type name="Test+&lt;TestFunc&gt;c__AnonStorey0">\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
   </test>\r
   <test name="test-635.cs">\r
     <type name="ShortCircuitFold">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-872.cs">\r
+    <type name="X">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>66</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-873.cs">\r
     <type name="Program">\r
       <method name="Int32 Main()" attrs="145">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-874.cs">\r
+    <type name="X">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>30</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-875.cs">\r
     <type name="Test">\r
       <method name="Void Main()" attrs="150">\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-876.cs">\r
+    <type name="T">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>34</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+      <method name="Void Test1()" attrs="145">\r
+        <size>57</size>\r
+      </method>\r
+      <method name="Void Test2()" attrs="145">\r
+        <size>50</size>\r
+      </method>\r
+      <method name="UInt32 Test3(Int32, UInt32)" attrs="145">\r
+        <size>60</size>\r
+      </method>\r
+      <method name="Void Test4()" attrs="145">\r
+        <size>25</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-88.cs">\r
     <type name="X">\r
       <method name="Void f(System.String)" attrs="145">\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>226</size>\r
+        <size>225</size>\r
       </method>\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async2">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>226</size>\r
+        <size>225</size>\r
       </method>\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async3">\r
     </type>\r
     <type name="AsyncTypeInference+&lt;Main&gt;c__async8">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>157</size>\r
+        <size>156</size>\r
       </method>\r
     </type>\r
     <type name="AsyncTypeInference+&lt;Main&gt;c__asyncB">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>38</size>\r
+        <size>37</size>\r
       </method>\r
     </type>\r
     <type name="AsyncTypeInference+&lt;Main&gt;c__async2">\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__async1">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>197</size>\r
+        <size>196</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="C+&lt;Foo&gt;c__async3">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>169</size>\r
+        <size>168</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="C+&lt;Foo&gt;c__async0+&lt;Foo&gt;c__AnonStorey4+&lt;Foo&gt;c__async3">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>185</size>\r
+        <size>184</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="C+&lt;Foo&gt;c__async0+&lt;Foo&gt;c__AnonStorey4+&lt;Foo&gt;c__async3">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>214</size>\r
+        <size>213</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="C+&lt;Test&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>61</size>\r
+        <size>60</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="X+&lt;Foo&gt;c__AnonStorey1+&lt;Foo&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>44</size>\r
+        <size>43</size>\r
       </method>\r
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r