[mono/mono] d12330ed: [mcs] Reachability and flow analysis rewrite to work on resolved statements and expressions

"Marek Safar ([email protected])" <[email protected]> Thu, 21 Nov 2013 13:44:03 +0000
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <000001427ae73b78-a01d333f-51fc-49ca-8e82-5f36fece85ea-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/cc4049bcf262...d12330eda774

   Commit: d12330eda7746321b4611865d11e932e53ac55b8
   Author: Marek Safar <[email protected]> (marek-safar)
     Date: 2013-11-21 13:43:08 GMT
      URL: https://github.com/mono/mono/commit/d12330eda7746321b4611865d11e932e53ac55b8

[mcs] Reachability and flow analysis rewrite to work on resolved statements and expressions

Changed paths:
  M mcs/errors/cs0162-7.cs
  M mcs/errors/cs0163.cs
  M mcs/errors/known-issues-net_4_5
  M mcs/mcs/anonymous.cs
  M mcs/mcs/argument.cs
  M mcs/mcs/assign.cs
  M mcs/mcs/async.cs
  M mcs/mcs/complete.cs
  M mcs/mcs/context.cs
  M mcs/mcs/cs-parser.jay
  M mcs/mcs/delegate.cs
  M mcs/mcs/dynamic.cs
  M mcs/mcs/ecore.cs
  M mcs/mcs/eval.cs
  M mcs/mcs/expression.cs
  M mcs/mcs/flowanalysis.cs
  M mcs/mcs/iterators.cs
  M mcs/mcs/linq.cs
  M mcs/mcs/method.cs
  M mcs/mcs/nullable.cs
  M mcs/mcs/statement.cs
  M mcs/tests/known-issues-net_4_5
  M mcs/tests/test-519.cs
  M mcs/tests/test-579.cs
  M mcs/tests/ver-il-net_4_5.xml
Added paths:
  A mcs/errors/cs0162-20.cs
  A mcs/errors/cs0163-2.cs
  A mcs/errors/cs0165-22.cs
  A mcs/errors/cs0165-23.cs
  A mcs/errors/cs0165-24.cs
  A mcs/errors/cs0201-10.cs
  A mcs/errors/cs0429-4.cs
  A mcs/errors/cs1632-2.cs
  A mcs/errors/cs1632-3.cs
  A mcs/errors/cs1632-4.cs
  A mcs/tests/test-874.cs
  A mcs/tests/test-876.cs
Removed paths:
  D mcs/errors/cs0161-4.cs
  D mcs/errors/cs0162-17.cs
  D mcs/errors/cs0162-19.cs

Removed: mcs/errors/cs0161-4.cs
===================================================================
@@ -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;
-		}
-	}
-}

Renamed: mcs/errors/cs0162-20.cs
===================================================================
@@ -1,12 +1,21 @@
 // CS0162: Unreachable code detected
-// Line: 10
+// Line: 14
 // Compiler options: -warnaserror
 
-public class X
+using System;
+
+class X
 {
+
 	public static void Main ()
 	{
+		goto X;
+	A:
+		bool b = false;
+		if (b) {
+			goto A;
+		}
+	X:
 		return;
-		1+1;
 	}
 }
\ No newline at end of file

Modified: mcs/errors/cs0162-7.cs
===================================================================
@@ -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 ()
 	{

Added: mcs/errors/cs0163-2.cs
===================================================================
@@ -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

Modified: mcs/errors/cs0163.cs
===================================================================
@@ -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
 {

Added: mcs/errors/cs0165-22.cs
===================================================================
@@ -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;
+	}
+}
+

Added: mcs/errors/cs0165-23.cs
===================================================================
@@ -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

Added: mcs/errors/cs0165-24.cs
===================================================================
@@ -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

Added: mcs/errors/cs0201-10.cs
===================================================================
@@ -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

Renamed: mcs/errors/cs0429-4.cs
===================================================================
@@ -1,4 +1,4 @@
-// CS0162: Unreachable code detected
+// CS0429: Unreachable expression code detected
 // Line: 12
 // Compiler options: -warnaserror
 

Added: mcs/errors/cs1632-2.cs
===================================================================
@@ -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;
+			};
+		}
+	}
+}

Added: mcs/errors/cs1632-3.cs
===================================================================
@@ -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;
+		}
+	}
+}

Added: mcs/errors/cs1632-4.cs
===================================================================
@@ -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;
+		}
+	}
+}

Modified: mcs/errors/known-issues-net_4_5
===================================================================
@@ -14,9 +14,6 @@
 # Parser problems
 cs0080.cs 
 
-cs0162-7.cs NO ERROR
-cs0165-3.cs
-
 # Operators
 cs0457-2.cs
 cs0457.cs

Modified: mcs/mcs/anonymous.cs
===================================================================
@@ -214,6 +214,11 @@ protected override void DoEmit (EmitContext ec)
 				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 @@ protected override Expression DoResolve (ResolveContext ec)
 			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 @@ public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae
 			}
 
 			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 @@ public override bool ContainsEmitWithAwait ()
 			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;

Modified: mcs/mcs/argument.cs
===================================================================
@@ -127,6 +127,29 @@ public Argument EmitToField (EmitContext ec, bool cloneResult)
 			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 @@ public bool ResolveMethodGroup (ResolveContext ec)
 
 		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 @@ public virtual Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait)
 			return null;
 		}
 
+		public void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			foreach (var arg in args)
+				arg.FlowAnalysis (fc);
+		}
+
 		public List<Argument>.Enumerator GetEnumerator ()
 		{
 			return args.GetEnumerator ();

Modified: mcs/mcs/assign.cs
===================================================================
@@ -417,6 +417,14 @@ public override void EmitStatement (EmitContext ec)
 			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 @@ protected override Expression DoResolve (ResolveContext ec)
 
 			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 @@ public override void EmitStatement (EmitContext ec)
 			else
 				base.EmitStatement (ec);
 		}
+
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			source.FlowAnalysis (fc);
+		}
 		
 		public bool IsDefaultInitializer {
 			get {
@@ -780,6 +819,12 @@ protected override Expression DoResolve (ResolveContext ec)
 			return base.DoResolve (ec);
 		}
 
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			target.FlowAnalysis (fc);
+			source.FlowAnalysis (fc);
+		}
+
 		protected override Expression ResolveConversions (ResolveContext ec)
 		{
 			//

Modified: mcs/mcs/async.cs
===================================================================
@@ -65,8 +65,19 @@ public override bool ContainsEmitWithAwait ()
 			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 @@ public override void EmitStatement (EmitContext ec)
 			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 @@ public override Expression EmitToField (EmitContext ec)
 		public AwaitStatement (Expression expr, Location loc)
 			: base (expr, loc)
 		{
+			unwind_protect = true;
 		}
 
 		#region Properties
@@ -306,6 +324,10 @@ public override bool Resolve (BlockContext bc)
 				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 @@ public override bool Resolve (BlockContext bc)
 		}
 	}
 
+	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 @@ public AsyncInitializer (ParametersBlock block, TypeDefinition host, TypeSpec re
 
 		#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 @@ public override void EmitStatement (EmitContext ec)
 			storey.EmitInitializer (ec);
 			ec.Emit (OpCodes.Ret);
 		}
+
+		public override void MarkReachable (Reachability rc)
+		{
+			//
+			// Reachability has been done in AsyncInitializerStatement
+			//
+		}
 	}
 
 	class AsyncTaskStorey : StateMachine

Modified: mcs/mcs/complete.cs
===================================================================
@@ -114,32 +114,22 @@ protected override Expression DoResolve (ResolveContext rc)
 			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)

Modified: mcs/mcs/context.cs
===================================================================
@@ -69,8 +69,6 @@ public interface IModuleContext
 	//
 	public class BlockContext : ResolveContext
 	{
-		FlowBranching current_flow_branching;
-
 		readonly TypeSpec return_type;
 
 		//
@@ -112,124 +110,17 @@ public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType
 				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 @@ public enum Options
 
 			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 @@ public void Dispose ()
 
 		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 @@ public ResolveContext (IMemberContext mc, Options options)
 			}
 		}
 
-		public virtual FlowBranching CurrentBranching {
-			get { return null; }
-		}
-
 		//
 		// The current iterator
 		//
@@ -443,10 +314,6 @@ public ResolveContext (IMemberContext mc, Options options)
 			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 @@ public ResolveContext (IMemberContext mc, Options options)
 
 		public bool IsVariableCapturingRequired {
 			get {
-				return !IsInProbingMode && (CurrentBranching == null || !CurrentBranching.CurrentUsageVector.IsUnreachable);
+				return !IsInProbingMode;
 			}
 		}
 
@@ -490,10 +357,6 @@ public ResolveContext (IMemberContext mc, Options options)
 			}
 		}
 
-		public bool OmitStructFlowAnalysis {
-			get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
-		}
-
 		public Report Report {
 			get {
 				return Module.Compiler.Report;
@@ -573,6 +436,65 @@ public FullNamedExpression LookupNamespaceAlias (string name)
 		#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.

Modified: mcs/mcs/cs-parser.jay
===================================================================
@@ -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) {

Modified: mcs/mcs/delegate.cs
===================================================================
@@ -828,6 +828,13 @@ public override Expression CreateExpressionTree (ResolveContext ec)
 			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;

Modified: mcs/mcs/dynamic.cs
===================================================================
@@ -532,6 +532,11 @@ protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments,
 			}
 		}
 
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			arguments.FlowAnalysis (fc);
+		}
+
 		public static MemberAccess GetBinderNamespace (Location loc)
 		{
 			return new MemberAccess (new MemberAccess (
@@ -612,6 +617,11 @@ public override void EmitStatement (EmitContext ec)
 				stmt.Emit (ec);
 			}
 		}
+
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			invoke.FlowAnalysis (fc);
+		}
 	}
 
 	class DynamicConversion : DynamicExpressionStatement, IDynamicBinder

Modified: mcs/mcs/ecore.cs
===================================================================
@@ -923,6 +923,10 @@ protected void Error_PointerInsideExpressionTree (ResolveContext ec)
 			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 @@ public virtual object Accept (StructuralVisitor visitor)
 	/// </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 @@ public override void Emit (EmitContext ec)
 			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 @@ public override void EmitStatement (EmitContext ec)
 			{
 				stm.EmitStatement (ec);
 			}
+
+			public override void FlowAnalysis (FlowAnalysisContext fc)
+			{
+				stm.FlowAnalysis (fc);
+			}
 		}
 
 		readonly Expression expr, orig_expr;
@@ -2244,6 +2262,11 @@ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 			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 @@ public override void Emit (EmitContext ec)
 		{
 			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 @@ public SimpleName GetMethodGroup ()
 
 		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 @@ public static void Error_ProtectedMemberAccess (ResolveContext rc, MemberSpec me
 				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 @@ bool ResolveInstanceExpressionCore (ResolveContext rc, Expression rhs)
 						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,30 +3325,18 @@ bool ResolveInstanceExpressionCore (ResolveContext rc, Expression rhs)
 			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
 			//
 			if (rhs != null) {
@@ -5696,18 +5729,14 @@ Expression DoResolve (ResolveContext ec, Expression rhs)
 					// "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 @@ Expression DoResolve (ResolveContext ec, Expression rhs)
 			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 @@ Expression DoResolve (ResolveContext ec, Expression rhs)
 			//
 			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 @@ public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
 				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 @@ Expression Error_AssignToReadonly (ResolveContext rc, Expression right_side)
 					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 @@ override public Expression DoResolveLValue (ResolveContext ec, Expression right_
 			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 @@ public override void Emit (EmitContext ec)
 				DoEmit (ec);
 			}
 
+			protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+			{
+				return false;
+			}
+
 			protected override void CloneTo (CloneContext clonectx, Statement target)
 			{
 				// Nothing
@@ -6843,10 +6918,6 @@ public override void SetHasAddressTaken ()
 		public override VariableInfo VariableInfo {
 			get { return null; }
 		}
-
-		public override void VerifyDefiniteAssignment (ResolveContext rc)
-		{
-		}
 	}
 
 	/// 

Modified: mcs/mcs/eval.cs
===================================================================
@@ -389,7 +389,7 @@ public string Evaluate (string input, out object result, out bool result_set)
 				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;

Modified: mcs/mcs/expression.cs
===================================================================
@@ -83,6 +83,11 @@ public override void Emit (EmitContext ec)
 			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 @@ public override void EmitSideEffect (EmitContext ec)
 			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 @@ public override void EmitStatement (EmitContext ec)
 			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 @@ protected override Expression DoResolve (ResolveContext ec)
 			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 @@ void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expressi
 			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 @@ public override void Emit (EmitContext ec)
 			}
 		}
 
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			arguments.FlowAnalysis (fc);
+		}
+
 		public override SLE.Expression MakeExpression (BuilderContext ctx)
 		{
 			if (arguments.Count != 2)
@@ -5259,32 +5298,8 @@ public override Expression CreateExpressionTree (ResolveContext ec)
 		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 @@ protected override Expression DoResolve (ResolveContext ec)
 						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 @@ public override void Emit (EmitContext ec)
 			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 @@ public abstract class VariableReference : Expression, IAssignMethod, IMemoryLoca
 		#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 @@ public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 
 		#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 @@ protected override Expression DoResolve (ResolveContext ec)
 		{
 			local_info.SetIsUsed ();
 
-			VerifyDefiniteAssignment (ec);
-
 			DoResolveBase (ec);
 			return this;
 		}
@@ -5721,8 +5742,6 @@ public override Expression DoResolveLValue (ResolveContext ec, Expression rhs)
 					}
 					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 @@ public override void SetHasAddressTaken ()
 			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 @@ protected override Expression DoResolve (ResolveContext ec)
 			if (!DoResolveBase (ec))
 				return null;
 
-			VerifyDefiniteAssignment (ec);
 			return this;
 		}
 
@@ -5925,21 +5934,23 @@ public override Expression DoResolveLValue (ResolveContext ec, Expression right_
 			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 @@ protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
 			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 @@ public override void EmitStatement (EmitContext ec)
 				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 @@ public override void Emit (EmitContext ec)
 		{
 			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 @@ protected override void Error_NegativeArrayIndex (ResolveContext ec, Location lo
 			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 @@ public This (Location loc)
 
 		#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 @@ public void CheckStructThisDefiniteAssignment (ResolveContext rc)
 			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 @@ protected virtual void Error_ThisNotAvailable (ResolveContext ec)
 			}
 		}
 
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			CheckStructThisDefiniteAssignment (fc);
+		}
+
 		public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 		{
 			if (ae == null)
@@ -7781,9 +7824,6 @@ public virtual void ResolveBase (ResolveContext ec)
 		protected override Expression DoResolve (ResolveContext ec)
 		{
 			ResolveBase (ec);
-
-			CheckStructThisDefiniteAssignment (ec);
-
 			return this;
 		}
 
@@ -7792,9 +7832,6 @@ public override Expression DoResolveLValue (ResolveContext ec, Expression right_
 			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 @@ public override void SetHasAddressTaken ()
 		{
 			// Nothing
 		}
-
-		public override void VerifyDefiniteAssignment (ResolveContext rc)
-		{
-		}
 		
 		public override object Accept (StructuralVisitor visitor)
 		{
@@ -8616,50 +8649,25 @@ public MemberAccess (Expression expr, string identifier, int arity, Location loc
 
 		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 @@ public override Expression LookupNameExpression (ResolveContext rc, MemberLookup
 			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 @@ public override Expression LookupNameExpression (ResolveContext rc, MemberLookup
 				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 @@ public override Expression LookupNameExpression (ResolveContext rc, MemberLookup
 								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 @@ public override Expression LookupNameExpression (ResolveContext rc, MemberLookup
 				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 @@ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 				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 @@ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 				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 @@ public static void Error_NamedArgument (NamedArgument na, Report Report)
 			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 @@ protected override void Error_NegativeArrayIndex (ResolveContext ec, Location lo
 			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 @@ public override void EmitAssign (EmitContext ec, Expression source, bool leave_c
 			}
 		}
 
+		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 @@ public override void Emit (EmitContext ec)
 			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 @@ public override void EmitStatement (EmitContext ec)
 				e.EmitStatement (ec);
 			}
 		}
+
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			foreach (var initializer in initializers)
+				initializer.FlowAnalysis (fc);
+		}
 	}
 	
 	//
@@ -10995,6 +11002,12 @@ protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode
 			return instance;
 		}
 
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			base.FlowAnalysis (fc);
+			initializers.FlowAnalysis (fc);
+		}
+
 		public override object Accept (StructuralVisitor visitor)
 		{
 			return visitor.Visit (this);

Modified: mcs/mcs/flowanalysis.cs
===================================================================
@@ -18,1055 +18,6 @@
 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.
 	//
 	//   The flow code uses a BitVector to keep track of whether a variable has been assigned
@@ -1178,23 +129,22 @@ public static TypeInfo GetTypeInfo (TypeSpec type)
 		//   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 @@ public static VariableInfo Create (BlockContext bc, Parameter parameter)
 			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 @@ public bool IsAssigned (MyBitVector vector)
 					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 @@ public bool IsStructFieldAssigned (MyBitVector vector, string field_name)
 			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 @@ public void SetStructFieldAssigned (MyBitVector vector, string field_name)
 
 			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 @@ public void SetStructFieldAssigned (MyBitVector vector, string field_name)
 			// 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 @@ public VariableInfo GetStructFieldInfo (string fieldName)
 
 		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;
 		}
 	}
 }

Modified: mcs/mcs/iterators.cs
===================================================================
@@ -29,6 +29,7 @@ public abstract class YieldStatement<T> : ResumableStatement where T : StateMach
 		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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ public override bool Resolve (BlockContext bc)
 				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 @@ public Yield (Expression expr, Location loc)
 		{
 		}
 
-		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 @@ public override bool Resolve (BlockContext bc)
 			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 @@ public YieldBreak (Location l)
 			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 @@ protected override void CloneTo (CloneContext clonectx, Statement target)
 			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 @@ public override bool Resolve (BlockContext ec)
 					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 @@ protected override void DoEmit (EmitContext ec)
 					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 @@ public static GetEnumeratorMethod Create (IteratorStorey host, FullNamedExpressi
 				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 @@ protected override void DoEmit (EmitContext ec)
 					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 @@ void Define_Current (bool is_generic)
 
 			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 @@ void Define_Reset ()
 				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 @@ public class StateMachineMethod : Method
 	{
 		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 @@ public override void Emit (EmitContext ec)
 				// 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 @@ public override Expression CreateExpressionTree (ResolveContext ec)
 			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 @@ protected override void CloneTo (CloneContext clonectx, Statement target)
 				throw new NotSupportedException ();
 			}
 
+			protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+			{
+				throw new NotSupportedException ();
+			}
+
 			protected override void DoEmit (EmitContext ec)
 			{
 				//
@@ -985,8 +1057,8 @@ public Method CreateFinallyHost (TryFinallyBlock block)
 				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 @@ public override void InjectYield (EmitContext ec, Expression expr, int resume_pc
 			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;

Modified: mcs/mcs/linq.cs
===================================================================
@@ -811,9 +811,8 @@ public static void Reset ()
 		}
 
 		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)

Modified: mcs/mcs/method.cs
===================================================================
@@ -1498,6 +1498,12 @@ public override void EmitStatement (EmitContext ec)
 		{
 			Emit (ec);
 		}
+
+		public override void FlowAnalysis (FlowAnalysisContext fc)
+		{
+			if (argument_list != null)
+				argument_list.FlowAnalysis (fc);
+		}
 	}
 
 	public class ConstructorBaseInitializer : ConstructorInitializer {
@@ -1742,7 +1748,7 @@ public override void Emit ()
 					}
 				}
 
-				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 @@ public void Emit (TypeDefinition parent)
 			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);
 

Modified: mcs/mcs/nullable.cs
===================================================================
@@ -201,6 +201,11 @@ public override bool Equals (object obj)
 			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 @@ public override void Emit (EmitContext ec)
 			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 @@ void EmitEquality (EmitContext ec)
 			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 @@ public override void Emit (EmitContext ec)
 			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;

Modified: mcs/mcs/statement.cs
===================================================================
@@ -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
@@ -35,44 +42,6 @@ public virtual bool Resolve (BlockContext bc)
 		}
 
 		/// <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>
 		protected abstract void DoEmit (EmitContext ec);
@@ -110,6 +79,64 @@ public virtual object Accept (StructuralVisitor visitor)
 		{
 			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 @@ public EmptyStatement (Location loc)
 		{
 			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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ public override object Accept (StructuralVisitor visitor)
 			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 @@ public If (Expression bool_expr, Statement true_statement, Location l)
 		
 		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 @@ protected override void DoEmit (EmitContext ec)
 				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 @@ protected override void DoEmit (EmitContext ec)
 			}
 		}
 
+		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 @@ public override object Accept (StructuralVisitor visitor)
 		}
 	}
 
-	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 @@ public Do (Statement statement, BooleanExpression bool_expr, Location doLocation
 			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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ public override object Accept (StructuralVisitor visitor)
 		{
 			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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ public override object Accept (StructuralVisitor visitor)
 		{
 			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 @@ public For (Location l)
 			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 @@ public override object Accept (StructuralVisitor visitor)
 		{
 			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 @@ protected override void CloneTo (CloneContext clonectx, Statement t)
 		
 		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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ protected override void DoEmit (EmitContext ec)
 				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 @@ public override object Accept (StructuralVisitor visitor)
 		}
 	}
 
-	// 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 @@ public Return (Expression expr, Location l)
 			}
 		}
 
+		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 @@ protected override bool DoResolve (BlockContext ec)
 			}
 
 			expr = expr.Resolve (ec);
-			TypeSpec block_return_type = ec.ReturnType;
 
 			AnonymousExpression am = ec.CurrentAnonymousMethod;
 			if (am == null) {
@@ -1007,7 +1271,7 @@ protected override void DoEmit (EmitContext ec)
 						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 @@ protected override void DoEmit (EmitContext ec)
 			}
 		}
 
+		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 @@ public override object Accept (StructuralVisitor visitor)
 		}
 	}
 
-	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 @@ public Goto (string label, Location l)
 			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 @@ protected override void DoEmit (EmitContext ec)
 		{
 			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 @@ public class LabeledStatement : Statement {
 		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 @@ public Label LabelTarget (EmitContext ec)
 			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 @@ public override object Accept (StructuralVisitor visitor)
 	/// <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 @@ public override object Accept (StructuralVisitor visitor)
 	/// <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 @@ public override bool Resolve (BlockContext ec)
 			}
 
 			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 @@ public override object Accept (StructuralVisitor visitor)
 			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 @@ public Throw (Expression expr, Location l)
 		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 @@ protected override void DoEmit (EmitContext ec)
 			}
 		}
 
+		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 @@ public override object Accept (StructuralVisitor visitor)
 		}
 	}
 
-	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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ protected override void DoEmit (EmitContext ec)
 			}
 		}
 
+		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 @@ public override object Accept (StructuralVisitor visitor)
 	//
 	// 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 @@ public enum Flags
 			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 @@ public string GetReadOnlyContext ()
 			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 @@ public class Block : Statement {
 		public enum Flags
 		{
 			Unchecked = 1,
-			HasRet = 8,
+			ReachableEnd = 8,
 			Unsafe = 16,
 			HasCapturedVariable = 64,
 			HasCapturedThis = 1 << 7,
@@ -2079,7 +2552,10 @@ public enum Flags
 			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 @@ public Block (Block parent, Flags flags, Location start, Location end)
 
 		#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 @@ public Block (Block parent, Flags flags, Location start, Location end)
 			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 @@ public LabeledStatement LookupLabel (string name)
 			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 @@ protected void EmitScopeInitializers (EmitContext ec)
 				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 @@ public ExplicitBlock (Block parent, Flags flags, Location start, Location end)
 			}
 		}
 
+		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 @@ public override void Emit (EmitContext ec)
 			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 @@ public void RegisterIteratorYield ()
 			}
 		}
 
+		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 @@ public override void Emit (EmitContext ec)
 
 		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 @@ public ParametersBlock (Block parent, ParametersCompiled parameters, Location st
 			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 @@ protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters
 			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 @@ protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters
 
 		#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 @@ public void EmitEmbedded (EmitContext ec)
 			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 @@ protected void ProcessParameters ()
 			}
 		}
 
-		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 @@ public ToplevelBlock ConvertToIterator (IMethodData method, TypeDefinition host,
 			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 @@ public ParametersBlock ConvertToAsyncTask (IMemberContext context, TypeDefinitio
 			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 @@ public ToplevelBlock (CompilerContext ctx, Location loc)
 		{
 		}
 
-		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 @@ public ToplevelBlock (ParametersBlock source, ParametersCompiled parameters)
 		{
 			this.compiler = source.TopBlock.compiler;
 			top_block = this;
-			flags |= Flags.HasRet;
 		}
 
 		public bool IsIterator {
@@ -3543,8 +4077,11 @@ public LabeledStatement GetLabel (string name, Block block)
 			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 @@ public void AddThisVariable (BlockContext bc)
 			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 @@ public override void Emit (EmitContext ec)
 			// 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 @@ public override void Emit (EmitContext ec)
 				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 @@ public SwitchLabel (Expression expr, Location l)
 				return converted;
 			}
 			set {
-				converted = value;
+				converted = value; 
 			}
 		}
 
@@ -3683,21 +4264,34 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ bool ResolveAndReduce (ResolveContext rc)
 
 		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 @@ public override object Accept (StructuralVisitor visitor)
 		{
 			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 @@ protected override void CloneTo (CloneContext clonectx, Statement target)
 				throw new NotImplementedException ();
 			}
 
+			protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+			{
+				return false;
+			}
+
 			protected override void DoEmit (EmitContext ec)
 			{
 				body.EmitDispatch (ec);
@@ -3822,6 +4426,7 @@ protected override void DoEmit (EmitContext ec)
 		List<SwitchLabel> case_labels;
 
 		List<Tuple<GotoCase, Constant>> goto_cases;
+		List<DefiniteAssignmentBitSet> end_reachable_das;
 
 		/// <summary>
 		///   The governing switch type
@@ -3838,6 +4443,7 @@ protected override void DoEmit (EmitContext ec)
 		ExpressionStatement string_dictionary;
 		FieldExpr switch_cache_field;
 		ExplicitBlock block;
+		bool end_reachable;
 
 		//
 		// Nullable Types support
@@ -3845,12 +4451,15 @@ protected override void DoEmit (EmitContext ec)
 		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 @@ public Switch (Expression e, ExplicitBlock block, Location l)
 			}
 		}
 
+		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 @@ public static TypeSpec[] CreateSwitchUserTypes (BuiltinTypes types)
 			};
 		}
 
-		public void RegisterLabel (ResolveContext rc, SwitchLabel sl)
+		public void RegisterLabel (BlockContext rc, SwitchLabel sl)
 		{
 			case_labels.Add (sl);
 
@@ -4128,7 +4743,30 @@ SwitchLabel FindLabel (Constant value)
 				}
 			}
 
-			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 @@ public override bool Resolve (BlockContext ec)
 
 			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 @@ public override bool Resolve (BlockContext ec)
 
 					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 @@ bool HasOnlyDefaultSection ()
 			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 @@ void ResolveStringSwitchMap (ResolveContext ec)
 			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 @@ void EmitDispatch (EmitContext ec)
 
 		protected override void DoEmit (EmitContext ec)
 		{
-			// Workaround broken flow-analysis
-			block.HasUnreachableClosingBrace = true;
-
 			//
 			// Setup the codegen context
 			//
@@ -4546,16 +5214,32 @@ protected override void CloneTo (CloneContext clonectx, Statement t)
 			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 @@ public override void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end,
 			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 @@ public override bool Resolve (BlockContext bc)
 				}
 			}
 
-			return base.Resolve (bc);
+			return base.Resolve (bc) && ok;
 		}
 	}
 
@@ -4739,11 +5447,9 @@ public override bool Resolve (BlockContext bc)
 	//
 	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 @@ protected virtual void EmitTryBodyPrepare (EmitContext ec)
 			}
 		}
 
-		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 @@ public void AddResumePoint (ResumableStatement stmt, int pc)
 				throw new InternalErrorException ("missed an intervening AddResumePoint?");
 
 			resume_points.Add (stmt);
+			return pc;
 		}
-
 	}
 
 	public class Lock : TryFinallyBlock
@@ -4871,17 +5569,13 @@ public override bool Resolve (BlockContext ec)
 			}
 
 			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 @@ protected override void DoEmit (EmitContext ec)
 				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 @@ protected override void DoEmit (EmitContext ec)
 				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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ protected Emitter (Expression expr, LocalVariable li)
 			}
 
 			public abstract void EmitExit (EmitContext ec);
+
+			public override void FlowAnalysis (FlowAnalysisContext fc)
+			{
+				expr.FlowAnalysis (fc);
+			}
 		}
 
 		class ExpressionEmitter : Emitter {
@@ -5306,19 +6038,20 @@ public Fixed (VariableDeclaration decl, Statement stmt, Location l)
 
 		#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 @@ protected override void DoEmit (EmitContext ec)
 			}
 		}
 
+		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 @@ public override object Accept (StructuralVisitor visitor)
 
 	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 @@ public Catch (Block block, Location loc)
 
 		#region Properties
 
-		public Block Block {
+		public ExplicitBlock Block {
 			get {
 				return block;
 			}
@@ -5447,7 +6193,7 @@ protected override void DoEmit (EmitContext ec)
 
 		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 @@ public override bool Resolve (BlockContext ec)
 					}
 				}
 
+				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 @@ protected override void CloneTo (CloneContext clonectx, Statement t)
 			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 @@ public override void EmitFinallyBody (EmitContext ec)
 			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 @@ public TryCatch (Block block, List<Catch> catch_clauses, Location l, bool inside
 			}
 		}
 
-		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 @@ public override bool Resolve (BlockContext ec)
 						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 @@ public override bool Resolve (BlockContext ec)
 						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 @@ public override bool Resolve (BlockContext ec)
 				}
 			}
 
-			ec.EndFlowBranching ();
-
-			return base.Resolve (ec) && ok;
+			return base.Resolve (bc) && ok;
 		}
 
 		protected sealed override void DoEmit (EmitContext ec)
@@ -5652,6 +6456,45 @@ protected sealed override void DoEmit (EmitContext ec)
 				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 @@ public override void EmitFinallyBody (EmitContext ec)
 			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 @@ public override bool Resolve (BlockContext ec)
 				}
 			}
 
-			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 @@ public override object Accept (StructuralVisitor visitor)
 	/// <summary>
 	///   Implementation of the foreach C# statement
 	/// </summary>
-	public class Foreach : Statement
+	public class Foreach : LoopStatement
 	{
 		abstract class IteratorStatement : Statement
 		{
@@ -5965,6 +6814,11 @@ public override void Emit (EmitContext ec)
 
 				base.Emit (ec);
 			}
+
+			protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+			{
+				throw new NotImplementedException ();
+			}
 		}
 
 		sealed class ArrayForeach : IteratorStatement
@@ -6046,22 +6900,7 @@ public override bool Resolve (BlockContext ec)
 
 				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 @@ bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, Memb
 		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 @@ public Foreach (Expression type, LocalVariable var, Expression expr, Statement s
 			get { return expr; }
 		}
 
-		public Statement Statement {
-			get { return statement; }
-		}
-
 		public Expression TypeExpression {
 			get { return type; }
 		}
@@ -6460,6 +7294,15 @@ public Foreach (Expression type, LocalVariable var, Expression expr, Statement s
 			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 @@ public override bool Resolve (BlockContext ec)
 				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 @@ public override bool Resolve (BlockContext ec)
 					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 @@ protected override void DoEmit (EmitContext ec)
 			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 @@ protected override void CloneTo (CloneContext clonectx, Statement t)
 			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)

Modified: mcs/tests/known-issues-net_4_5
===================================================================
@@ -5,4 +5,3 @@
 # csXXXX.cs IGNORE 	: adds test to ignore list
 
 gtest-230.cs
-test-872.cs

Modified: mcs/tests/test-519.cs
===================================================================
@@ -1,3 +1,5 @@
+using System;
+
 class Foo {
 	public static int Main ()
 	{
@@ -5,9 +7,17 @@ public static int Main ()
 			f ();
 			return 1;
 		} catch {
-			return 0;
 		}
+
+		try {
+			f2 ();
+			return 2;
+		} catch (ApplicationException) {
+		}
+
+		return 0;
 	}
+
 	static void f ()
 	{
 		try {
@@ -20,4 +30,15 @@ static void f ()
 	skip:
 		;
 	}
+
+	static void f2 ()
+	{
+		try {
+			goto FinallyExit;
+		} finally {
+			throw new ApplicationException ();
+		}
+	FinallyExit:
+		Console.WriteLine ("Too late");
+	}
 }

Modified: mcs/tests/test-579.cs
===================================================================
@@ -4,6 +4,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;
 		{
 			goto A;
@@ -21,4 +32,46 @@ public static int Main ()
 			
 		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;
+	}
 }

Added: mcs/tests/test-874.cs
===================================================================
@@ -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

Added: mcs/tests/test-876.cs
===================================================================
@@ -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);
+	}
+}

Modified: mcs/tests/ver-il-net_4_5.xml
===================================================================
@@ -31086,7 +31086,7 @@
         <size>10</size>
       </method>
       <method name="Int32 test40(Int32)" attrs="145">
-        <size>27</size>
+        <size>20</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
@@ -40380,14 +40380,17 @@
   <test name="test-519.cs">
     <type name="Foo">
       <method name="Int32 Main()" attrs="150">
-        <size>25</size>
+        <size>52</size>
       </method>
       <method name="Void f()" attrs="145">
-        <size>21</size>
+        <size>23</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Void f2()" attrs="145">
+        <size>16</size>
+      </method>
     </type>
   </test>
   <test name="test-52.cs">
@@ -41722,11 +41725,20 @@
   <test name="test-579.cs">
     <type name="TestCase">
       <method name="Int32 Main()" attrs="150">
-        <size>49</size>
+        <size>44</size>
       </method>
       <method name="Void .ctor()" attrs="6278">
         <size>7</size>
       </method>
+      <method name="Int32 Test1()" attrs="145">
+        <size>49</size>
+      </method>
+      <method name="Int32 Test2()" attrs="145">
+        <size>48</size>
+      </method>
+      <method name="Int32 Test3()" attrs="145">
+        <size>47</size>
+      </method>
     </type>
   </test>
   <test name="test-58.cs">
@@ -43076,7 +43088,7 @@
   <test name="test-634.cs">
     <type name="Test">
       <method name="Void TestFunc()" attrs="150">
-        <size>7</size>
+        <size>13</size>
       </method>
       <method name="Void Main(System.String[])" attrs="150">
         <size>7</size>
@@ -43099,6 +43111,11 @@
         <size>0</size>
       </method>
     </type>
+    <type name="Test+&lt;TestFunc&gt;c__AnonStorey0">
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
   </test>
   <test name="test-635.cs">
     <type name="ShortCircuitFold">
@@ -48329,6 +48346,16 @@
       </method>
     </type>
   </test>
+  <test name="test-872.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="150">
+        <size>66</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-873.cs">
     <type name="Program">
       <method name="Int32 Main()" attrs="145">
@@ -48339,6 +48366,16 @@
       </method>
     </type>
   </test>
+  <test name="test-874.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="150">
+        <size>30</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-875.cs">
     <type name="Test">
       <method name="Void Main()" attrs="150">
@@ -48349,6 +48386,28 @@
       </method>
     </type>
   </test>
+  <test name="test-876.cs">
+    <type name="T">
+      <method name="Int32 Main()" attrs="150">
+        <size>34</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+      <method name="Void Test1()" attrs="145">
+        <size>57</size>
+      </method>
+      <method name="Void Test2()" attrs="145">
+        <size>50</size>
+      </method>
+      <method name="UInt32 Test3(Int32, UInt32)" attrs="145">
+        <size>60</size>
+      </method>
+      <method name="Void Test4()" attrs="145">
+        <size>25</size>
+      </method>
+    </type>
+  </test>
   <test name="test-88.cs">
     <type name="X">
       <method name="Void f(System.String)" attrs="145">
@@ -56284,12 +56343,12 @@
     </type>
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async0">
       <method name="Void MoveNext()" attrs="486">
-        <size>226</size>
+        <size>225</size>
       </method>
     </type>
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async2">
       <method name="Void MoveNext()" attrs="486">
-        <size>226</size>
+        <size>225</size>
       </method>
     </type>
     <type name="Program+&lt;Main&gt;c__AnonStorey1+&lt;Main&gt;c__async3">
@@ -56488,12 +56547,12 @@
     </type>
     <type name="AsyncTypeInference+&lt;Main&gt;c__async8">
       <method name="Void MoveNext()" attrs="486">
-        <size>157</size>
+        <size>156</size>
       </method>
     </type>
     <type name="AsyncTypeInference+&lt;Main&gt;c__asyncB">
       <method name="Void MoveNext()" attrs="486">
-        <size>38</size>
+        <size>37</size>
       </method>
     </type>
     <type name="AsyncTypeInference+&lt;Main&gt;c__async2">
@@ -59741,7 +59800,7 @@
     </type>
     <type name="Program+&lt;Main&gt;c__async1">
       <method name="Void MoveNext()" attrs="486">
-        <size>197</size>
+        <size>196</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>
@@ -59836,7 +59895,7 @@
     </type>
     <type name="C+&lt;Foo&gt;c__async3">
       <method name="Void MoveNext()" attrs="486">
-        <size>169</size>
+        <size>168</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>
@@ -59887,7 +59946,7 @@
     </type>
     <type name="C+&lt;Foo&gt;c__async0+&lt;Foo&gt;c__AnonStorey4+&lt;Foo&gt;c__async3">
       <method name="Void MoveNext()" attrs="486">
-        <size>185</size>
+        <size>184</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>
@@ -59941,7 +60000,7 @@
     </type>
     <type name="C+&lt;Foo&gt;c__async0+&lt;Foo&gt;c__AnonStorey4+&lt;Foo&gt;c__async3">
       <method name="Void MoveNext()" attrs="486">
-        <size>214</size>
+        <size>213</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>
@@ -60032,7 +60091,7 @@
     </type>
     <type name="C+&lt;Test&gt;c__async0">
       <method name="Void MoveNext()" attrs="486">
-        <size>61</size>
+        <size>60</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>
@@ -60290,7 +60349,7 @@
     </type>
     <type name="X+&lt;Foo&gt;c__AnonStorey1+&lt;Foo&gt;c__async0">
       <method name="Void MoveNext()" attrs="486">
-        <size>44</size>
+        <size>43</size>
       </method>
       <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">
         <size>13</size>



_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches