2004-05-24 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / statement.cs
index e83fa00b754cb7aa2686f1b49b8578c374d1032a..203e61d58bf9c0fc51f3aeecf25aaeace77b483e 100755 (executable)
@@ -5,7 +5,7 @@
 //   Miguel de Icaza (miguel@ximian.com)
 //   Martin Baulig (martin@gnome.org)
 //
-// (C) 2001, 2002 Ximian, Inc.
+// (C) 2001, 2002, 2003 Ximian, Inc.
 //
 
 using System;
@@ -21,111 +21,86 @@ namespace Mono.CSharp {
        public abstract class Statement {
                public Location loc;
                
-               ///
-               /// Resolves the statement, true means that all sub-statements
-               /// did resolve ok.
-               //
+               /// <summary>
+               ///   Resolves the statement, true means that all sub-statements
+               ///   did resolve ok.
+               //  </summary>
                public virtual bool Resolve (EmitContext ec)
                {
                        return true;
                }
-               
-               /// <summary>
-               ///   Return value indicates whether all code paths emitted return.
-               /// </summary>
-               protected abstract bool DoEmit (EmitContext ec);
 
                /// <summary>
-               ///   Return value indicates whether all code paths emitted return.
+               ///   We already know that the statement is unreachable, but we still
+               ///   need to resolve it to catch errors.
                /// </summary>
-               public virtual bool Emit (EmitContext ec)
+               public virtual bool ResolveUnreachable (EmitContext ec, bool warn)
                {
-                       ec.Mark (loc);
-                       Report.Debug (8, "MARK", this, loc);
-                       return DoEmit (ec);
-               }
-               
-               public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
-               {
-                       e = e.Resolve (ec);
-                       if (e == null)
-                               return null;
-                       
-                       if (e.Type != TypeManager.bool_type){
-                               e = Expression.ConvertImplicit (ec, e, TypeManager.bool_type,
-                                                               new Location (-1));
-                       }
+                       //
+                       // 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.
+                       //
 
-                       if (e == null){
-                               Report.Error (
-                                       31, loc, "Can not convert the expression to a boolean");
-                       }
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
+                       bool ok = Resolve (ec);
+                       ec.KillFlowBranching ();
 
-                       ec.Mark (loc);
+                       if (!ok)
+                               return false;
 
-                       return e;
+                       if (warn)
+                               Report.Warning (162, loc, "Unreachable code detected");
+                       return true;
                }
                
-               /// <remarks>
-               ///    Encapsulates the emission of a boolean test and jumping to a
-               ///    destination.
-               ///
-               ///    This will emit the bool expression in `bool_expr' and if
-               ///    `target_is_for_true' is true, then the code will generate a 
-               ///    brtrue to the target.   Otherwise a brfalse. 
-               /// </remarks>
-               public static void EmitBoolExpression (EmitContext ec, Expression bool_expr,
-                                                      Label target, bool target_is_for_true)
-               {
-                       ILGenerator ig = ec.ig;
-                       
-                       bool invert = false;
-                       if (bool_expr is Unary){
-                               Unary u = (Unary) bool_expr;
-                               
-                               if (u.Oper == Unary.Operator.LogicalNot){
-                                       invert = true;
-
-                                       u.EmitLogicalNot (ec);
-                               }
-                       } else if (bool_expr is Binary){
-                               Binary b = (Binary) bool_expr;
-
-                               if (b.EmitBranchable (ec, target, target_is_for_true))
-                                       return;
-                       }
-
-                       if (!invert)
-                               bool_expr.Emit (ec);
+               /// <summary>
+               ///   Return value indicates whether all code paths emitted return.
+               /// </summary>
+               protected abstract void DoEmit (EmitContext ec);
 
-                       if (target_is_for_true){
-                               if (invert)
-                                       ig.Emit (OpCodes.Brfalse, target);
-                               else
-                                       ig.Emit (OpCodes.Brtrue, target);
-                       } else {
-                               if (invert)
-                                       ig.Emit (OpCodes.Brtrue, target);
-                               else
-                                       ig.Emit (OpCodes.Brfalse, target);
-                       }
+               /// <summary>
+               ///   Utility wrapper routine for Error, just to beautify the code
+               /// </summary>
+               public void Error (int error, string format, params object[] args)
+               {
+                       Error (error, String.Format (format, args));
                }
 
-               public static void Warning_DeadCodeFound (Location loc)
+               public void Error (int error, string s)
                {
-                       Report.Warning (162, loc, "Unreachable code detected");
+                       if (!Location.IsNull (loc))
+                               Report.Error (error, loc, s);
+                       else
+                               Report.Error (error, s);
                }
+
+               /// <summary>
+               ///   Return value indicates whether all code paths emitted return.
+               /// </summary>
+               public virtual void Emit (EmitContext ec)
+               {
+                       ec.Mark (loc, true);
+                       DoEmit (ec);
+               }               
        }
 
-       public class EmptyStatement : Statement {
+       public sealed class EmptyStatement : Statement {
+               
+               private EmptyStatement () {}
+               
+               public static readonly EmptyStatement Value = new EmptyStatement ();
+               
                public override bool Resolve (EmitContext ec)
                {
                        return true;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
-                       return false;
                }
        }
        
@@ -133,6 +108,8 @@ namespace Mono.CSharp {
                Expression expr;
                public Statement TrueStatement;
                public Statement FalseStatement;
+
+               bool is_true_ret;
                
                public If (Expression expr, Statement trueStatement, Location l)
                {
@@ -156,61 +133,80 @@ namespace Mono.CSharp {
                {
                        Report.Debug (1, "START IF BLOCK", loc);
 
-                       expr = ResolveBoolean (ec, expr, loc);
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
                        if (expr == null){
                                return false;
                        }
+
+                       //
+                       // Dead code elimination
+                       //
+                       if (expr is BoolConstant){
+                               bool take = ((BoolConstant) expr).Value;
+
+                               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 (FlowBranchingType.BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
                        
-                       if (!TrueStatement.Resolve (ec)) {
-                               ec.KillFlowBranching ();
-                               return false;
-                       }
+                       bool ok = TrueStatement.Resolve (ec);
+
+                       is_true_ret = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
 
                        ec.CurrentBranching.CreateSibling ();
 
-                       if ((FalseStatement != null) && !FalseStatement.Resolve (ec)) {
-                               ec.KillFlowBranching ();
-                               return false;
-                       }
+                       if ((FalseStatement != null) && !FalseStatement.Resolve (ec))
+                               ok = false;
                                        
                        ec.EndFlowBranching ();
 
                        Report.Debug (1, "END IF BLOCK", loc);
 
-                       return true;
+                       return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        Label false_target = ig.DefineLabel ();
                        Label end;
-                       bool is_true_ret, is_false_ret;
 
                        //
-                       // Dead code elimination
+                       // If we're a boolean expression, Resolve() already
+                       // eliminated dead code for us.
                        //
                        if (expr is BoolConstant){
                                bool take = ((BoolConstant) expr).Value;
 
-                               if (take){
-                                       if (FalseStatement != null){
-                                               Warning_DeadCodeFound (FalseStatement.loc);
-                                       }
-                                       return TrueStatement.Emit (ec);
-                               } else {
-                                       Warning_DeadCodeFound (TrueStatement.loc);
-                                       if (FalseStatement != null)
-                                               return FalseStatement.Emit (ec);
-                               }
+                               if (take)
+                                       TrueStatement.Emit (ec);
+                               else if (FalseStatement != null)
+                                       FalseStatement.Emit (ec);
+
+                               return;
                        }
                        
-                       EmitBoolExpression (ec, expr, false_target, false);
-
-                       is_true_ret = TrueStatement.Emit (ec);
-                       is_false_ret = is_true_ret;
+                       expr.EmitBranchable (ec, false_target, false);
+                       
+                       TrueStatement.Emit (ec);
 
                        if (FalseStatement != null){
                                bool branch_emitted = false;
@@ -222,23 +218,20 @@ namespace Mono.CSharp {
                                }
 
                                ig.MarkLabel (false_target);
-                               is_false_ret = FalseStatement.Emit (ec);
+                               FalseStatement.Emit (ec);
 
                                if (branch_emitted)
                                        ig.MarkLabel (end);
                        } else {
                                ig.MarkLabel (false_target);
-                               is_false_ret = false;
                        }
-
-                       return is_true_ret && is_false_ret;
                }
        }
 
        public class Do : Statement {
                public Expression expr;
                public readonly Statement  EmbeddedStatement;
-               bool infinite, may_return;
+               bool infinite;
                
                public Do (Statement statement, Expression boolExpr, Location l)
                {
@@ -251,12 +244,12 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
 
                        if (!EmbeddedStatement.Resolve (ec))
                                ok = false;
 
-                       expr = ResolveBoolean (ec, expr, loc);
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
                        if (expr == null)
                                ok = false;
                        else if (expr is BoolConstant){
@@ -267,25 +260,20 @@ namespace Mono.CSharp {
                        }
 
                        ec.CurrentBranching.Infinite = infinite;
-                       FlowReturns returns = ec.EndFlowBranching ();
-                       may_return = returns != FlowReturns.NEVER;
+                       ec.EndFlowBranching ();
 
                        return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
                        Label loop = ig.DefineLabel ();
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool  old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
                                
                        ig.MarkLabel (loop);
                        EmbeddedStatement.Emit (ec);
@@ -300,26 +288,19 @@ namespace Mono.CSharp {
                                if (res)
                                        ec.ig.Emit (OpCodes.Br, loop); 
                        } else
-                               EmitBoolExpression (ec, expr, loop, true);
+                               expr.EmitBranchable (ec, loop, true);
                        
                        ig.MarkLabel (ec.LoopEnd);
 
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-
-                       if (infinite)
-                               return may_return == false;
-                       else
-                               return false;
                }
        }
 
        public class While : Statement {
                public Expression expr;
                public readonly Statement Statement;
-               bool may_return, empty, infinite;
+               bool infinite, empty;
                
                public While (Expression boolExpr, Statement statement, Location l)
                {
@@ -332,12 +313,10 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       expr = ResolveBoolean (ec, expr, loc);
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
                        if (expr == null)
                                return false;
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
-
                        //
                        // Inform whether we are infinite or not
                        //
@@ -345,54 +324,41 @@ namespace Mono.CSharp {
                                BoolConstant bc = (BoolConstant) expr;
 
                                if (bc.Value == false){
-                                       Warning_DeadCodeFound (Statement.loc);
+                                       if (!Statement.ResolveUnreachable (ec, true))
+                                               return false;
                                        empty = true;
+                                       return true;
                                } else
                                        infinite = true;
-                       } else {
-                               //
-                               // We are not infinite, so the loop may or may not be executed.
-                               //
-                               ec.CurrentBranching.CreateSibling ();
                        }
 
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
+
                        if (!Statement.Resolve (ec))
                                ok = false;
 
-                       if (empty)
-                               ec.KillFlowBranching ();
-                       else {
-                               ec.CurrentBranching.Infinite = infinite;
-                               FlowReturns returns = ec.EndFlowBranching ();
-                               may_return = returns != FlowReturns.NEVER;
-                       }
+                       ec.CurrentBranching.Infinite = infinite;
+                       ec.EndFlowBranching ();
 
                        return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        if (empty)
-                               return false;
+                               return;
 
                        ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
-                       bool ret;
                        
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
 
                        //
                        // Inform whether we are infinite or not
                        //
                        if (expr is BoolConstant){
-                               BoolConstant bc = (BoolConstant) expr;
-
                                ig.MarkLabel (ec.LoopBegin);
                                Statement.Emit (ec);
                                ig.Emit (OpCodes.Br, ec.LoopBegin);
@@ -401,7 +367,6 @@ namespace Mono.CSharp {
                                // Inform that we are infinite (ie, `we return'), only
                                // if we do not `break' inside the code.
                                //
-                               ret = may_return == false;
                                ig.MarkLabel (ec.LoopEnd);
                        } else {
                                Label while_loop = ig.DefineLabel ();
@@ -413,18 +378,13 @@ namespace Mono.CSharp {
                        
                                ig.MarkLabel (ec.LoopBegin);
 
-                               EmitBoolExpression (ec, expr, while_loop, true);
+                               expr.EmitBranchable (ec, while_loop, true);
+                               
                                ig.MarkLabel (ec.LoopEnd);
-
-                               ret = false;
                        }       
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
-
-                       return ret;
                }
        }
 
@@ -433,7 +393,7 @@ namespace Mono.CSharp {
                readonly Statement InitStatement;
                readonly Statement Increment;
                readonly Statement Statement;
-               bool may_return, infinite, empty;
+               bool infinite, empty;
                
                public For (Statement initStatement,
                            Expression test,
@@ -458,72 +418,67 @@ namespace Mono.CSharp {
                        }
 
                        if (Test != null){
-                               Test = ResolveBoolean (ec, Test, loc);
+                               Test = Expression.ResolveBoolean (ec, Test, loc);
                                if (Test == null)
                                        ok = false;
                                else if (Test is BoolConstant){
                                        BoolConstant bc = (BoolConstant) Test;
 
                                        if (bc.Value == false){
-                                               Warning_DeadCodeFound (Statement.loc);
+                                               if (!Statement.ResolveUnreachable (ec, true))
+                                                       return false;
+                                               if ((Increment != null) &&
+                                                   !Increment.ResolveUnreachable (ec, false))
+                                                       return false;
                                                empty = true;
+                                               return true;
                                        } else
                                                infinite = true;
                                }
                        } else
                                infinite = true;
 
-                       if (Increment != null){
-                               if (!Increment.Resolve (ec))
-                                       ok = false;
-                       }
-
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                        if (!infinite)
                                ec.CurrentBranching.CreateSibling ();
 
                        if (!Statement.Resolve (ec))
                                ok = false;
 
-                       if (empty)
-                               ec.KillFlowBranching ();
-                       else {
-                               ec.CurrentBranching.Infinite = infinite;
-                               FlowReturns returns = ec.EndFlowBranching ();
-                               may_return = returns != FlowReturns.NEVER;
+                       if (Increment != null){
+                               if (!Increment.Resolve (ec))
+                                       ok = false;
                        }
 
+                       ec.CurrentBranching.Infinite = infinite;
+                       ec.EndFlowBranching ();
+
                        return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        if (empty)
-                               return false;
+                               return;
 
                        ILGenerator ig = ec.ig;
                        Label old_begin = ec.LoopBegin;
                        Label old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        Label loop = ig.DefineLabel ();
                        Label test = ig.DefineLabel ();
                        
-                       if (InitStatement != null)
-                               if (! (InitStatement is EmptyStatement))
-                                       InitStatement.Emit (ec);
+                       if (InitStatement != null && InitStatement != EmptyStatement.Value)
+                               InitStatement.Emit (ec);
 
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
 
                        ig.Emit (OpCodes.Br, test);
                        ig.MarkLabel (loop);
                        Statement.Emit (ec);
 
                        ig.MarkLabel (ec.LoopBegin);
-                       if (!(Increment is EmptyStatement))
+                       if (Increment != EmptyStatement.Value)
                                Increment.Emit (ec);
 
                        ig.MarkLabel (test);
@@ -533,40 +488,26 @@ namespace Mono.CSharp {
                        //
                        if (Test != null){
                                //
-                               // The Resolve code already catches the case for Test == BoolConstant (false)
-                               // so we know that this is true
+                               // The Resolve code already catches the case for
+                               // Test == BoolConstant (false) so we know that
+                               // this is true
                                //
                                if (Test is BoolConstant)
                                        ig.Emit (OpCodes.Br, loop);
                                else
-                                       EmitBoolExpression (ec, Test, loop, true);
+                                       Test.EmitBranchable (ec, loop, true);
+                               
                        } else
                                ig.Emit (OpCodes.Br, loop);
                        ig.MarkLabel (ec.LoopEnd);
 
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
-                       
-                       //
-                       // Inform whether we are infinite or not
-                       //
-                       if (Test != null){
-                               if (Test is BoolConstant){
-                                       BoolConstant bc = (BoolConstant) Test;
-
-                                       if (bc.Value)
-                                               return may_return == false;
-                               }
-                               return false;
-                       } else
-                               return may_return == false;
                }
        }
        
        public class StatementExpression : Statement {
-               Expression expr;
+               ExpressionStatement expr;
                
                public StatementExpression (ExpressionStatement expr, Location l)
                {
@@ -576,22 +517,13 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       expr = (Expression) expr.Resolve (ec);
+                       expr = expr.ResolveStatement (ec);
                        return expr != null;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
-                       
-                       if (expr is ExpressionStatement)
-                               ((ExpressionStatement) expr).EmitStatement (ec);
-                       else {
-                               expr.Emit (ec);
-                               ig.Emit (OpCodes.Pop);
-                       }
-
-                       return false;
+                       expr.EmitStatement (ec);
                }
 
                public override string ToString ()
@@ -612,69 +544,70 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool in_exc;
+
                public override bool Resolve (EmitContext ec)
                {
-                       if (Expr != null){
+                       if (ec.ReturnType == null){
+                               if (Expr != null){
+                                       Error (127, "Return with a value not allowed here");
+                                       return false;
+                               }
+                       } else {
+                               if (Expr == null){
+                                       Error (126, "An object of type `{0}' is expected " +
+                                              "for the return statement",
+                                              TypeManager.CSharpName (ec.ReturnType));
+                                       return false;
+                               }
+
                                Expr = Expr.Resolve (ec);
                                if (Expr == null)
                                        return false;
+
+                               if (Expr.Type != ec.ReturnType) {
+                                       Expr = Convert.ImplicitConversionRequired (
+                                               ec, Expr, ec.ReturnType, loc);
+                                       if (Expr == null)
+                                               return false;
+                               }
                        }
 
+                       if (ec.InIterator){
+                               Error (-206, "Return statement not allowed inside iterators");
+                               return false;
+                       }
+                               
                        FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
 
-                       if (ec.CurrentBranching.InTryBlock ())
+                       if (ec.CurrentBranching.InTryOrCatch (true)) {
                                ec.CurrentBranching.AddFinallyVector (vector);
-                       else
+                               in_exc = true;
+                       } else if (ec.CurrentBranching.InFinally (true)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else
                                vector.CheckOutParameters (ec.CurrentBranching);
 
-                       vector.Returns = FlowReturns.ALWAYS;
-                       vector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Return ();
                        return true;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
-                       if (ec.InFinally){
-                               Report.Error (157,loc,"Control can not leave the body of the finally block");
-                               return false;
-                       }
-                       
-                       if (ec.ReturnType == null){
-                               if (Expr != null){
-                                       Report.Error (127, loc, "Return with a value not allowed here");
-                                       return true;
-                               }
-                       } else {
-                               if (Expr == null){
-                                       Report.Error (126, loc, "An object of type `" +
-                                                     TypeManager.CSharpName (ec.ReturnType) + "' is " +
-                                                     "expected for the return statement");
-                                       return true;
-                               }
-
-                               if (Expr.Type != ec.ReturnType)
-                                       Expr = Expression.ConvertImplicitRequired (
-                                               ec, Expr, ec.ReturnType, loc);
-
-                               if (Expr == null)
-                                       return true;
-
+                       if (Expr != null) {
                                Expr.Emit (ec);
 
-                               if (ec.InTry || ec.InCatch)
+                               if (in_exc)
                                        ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
                        }
 
-                       if (ec.InTry || ec.InCatch) {
-                               if (!ec.HasReturnLabel) {
-                                       ec.ReturnLabel = ec.ig.DefineLabel ();
-                                       ec.HasReturnLabel = true;
-                               }
+                       if (in_exc) {
+                               ec.NeedReturnLabel ();
                                ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
-                       } else
+                       } else {
                                ec.ig.Emit (OpCodes.Ret);
-
-                       return true; 
+                       }
                }
        }
 
@@ -685,20 +618,15 @@ namespace Mono.CSharp {
                
                public override bool Resolve (EmitContext ec)
                {
-                       label = block.LookupLabel (target);
-                       if (label == null){
-                               Report.Error (
-                                       159, loc,
-                                       "No such label `" + target + "' in this scope");
+                       label = ec.CurrentBranching.LookupLabel (target, loc);
+                       if (label == null)
                                return false;
-                       }
 
                        // If this is a forward goto.
                        if (!label.IsDefined)
                                label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
 
                        return true;
                }
@@ -716,27 +644,23 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        Label l = label.LabelTarget (ec);
                        ec.ig.Emit (OpCodes.Br, l);
-                       
-                       return false;
                }
        }
 
        public class LabeledStatement : Statement {
                public readonly Location Location;
-               string label_name;
                bool defined;
                bool referenced;
                Label label;
 
-               ArrayList vectors;
+               FlowBranching.UsageVector vectors;
                
                public LabeledStatement (string label_name, Location l)
                {
-                       this.label_name = label_name;
                        this.Location = l;
                }
 
@@ -764,32 +688,24 @@ namespace Mono.CSharp {
 
                public void AddUsageVector (FlowBranching.UsageVector vector)
                {
-                       if (vectors == null)
-                               vectors = new ArrayList ();
-
-                       vectors.Add (vector.Clone ());
+                       vector = vector.Clone ();
+                       vector.Next = vectors;
+                       vectors = vector;
                }
 
                public override bool Resolve (EmitContext ec)
                {
-                       if (vectors != null)
-                               ec.CurrentBranching.CurrentUsageVector.MergeJumpOrigins (vectors);
-                       else {
-                               ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.NEVER;
-                               ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.NEVER;
-                       }
+                       ec.CurrentBranching.Label (vectors);
 
                        referenced = true;
 
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        LabelTarget (ec);
                        ec.ig.MarkLabel (label);
-
-                       return false;
                }
        }
        
@@ -806,24 +722,22 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        if (ec.Switch == null){
                                Report.Error (153, loc, "goto default is only valid in a switch statement");
-                               return false;
+                               return;
                        }
 
                        if (!ec.Switch.GotDefault){
                                Report.Error (159, loc, "No default target on switch statement");
-                               return false;
+                               return;
                        }
                        ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
-                       return false;
                }
        }
 
@@ -868,19 +782,18 @@ namespace Mono.CSharp {
                                Report.Error (
                                        159, loc,
                                        "No such label 'case " + val + "': for the goto case");
+                               return false;
                        }
 
                        label = sl.ILLabelCode;
 
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.UNREACHABLE;
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ec.ig.Emit (OpCodes.Br, label);
-                       return true;
                }
        }
        
@@ -895,6 +808,9 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
+                       bool in_catch = ec.CurrentBranching.InCatch ();
+                       ec.CurrentBranching.CurrentUsageVector.Throw ();
+
                        if (expr != null){
                                expr = expr.Resolve (ec);
                                if (expr == null)
@@ -904,7 +820,7 @@ namespace Mono.CSharp {
 
                                if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
                                      eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) {
-                                       expr.Error118 ("value, variable, property or indexer access ");
+                                       expr.Error_UnexpectedKind ("value, variable, property or indexer access ");
                                        return false;
                                }
 
@@ -913,37 +829,30 @@ namespace Mono.CSharp {
                                if ((t != TypeManager.exception_type) &&
                                    !t.IsSubclassOf (TypeManager.exception_type) &&
                                    !(expr is NullLiteral)) {
-                                       Report.Error (155, loc,
-                                                     "The type caught or thrown must be derived " +
-                                                     "from System.Exception");
+                                       Error (155,
+                                              "The type caught or thrown must be derived " +
+                                              "from System.Exception");
                                        return false;
                                }
+                       } else if (!in_catch) {
+                               Error (156,
+                                      "A throw statement with no argument is only " +
+                                      "allowed in a catch clause");
+                               return false;
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.EXCEPTION;
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.EXCEPTION;
                        return true;
                }
                        
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
-                       if (expr == null){
-                               if (ec.InCatch)
-                                       ec.ig.Emit (OpCodes.Rethrow);
-                               else {
-                                       Report.Error (
-                                               156, loc,
-                                               "A throw statement with no argument is only " +
-                                               "allowed in a catch clause");
-                               }
-                               return false;
-                       }
-
-                       expr.Emit (ec);
-
-                       ec.ig.Emit (OpCodes.Throw);
+                       if (expr == null)
+                               ec.ig.Emit (OpCodes.Rethrow);
+                       else {
+                               expr.Emit (ec);
 
-                       return true;
+                               ec.ig.Emit (OpCodes.Throw);
+                       }
                }
        }
 
@@ -954,28 +863,39 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool crossing_exc;
+
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.MayLeaveLoop = true;
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+                               Error (139, "No enclosing loop or switch to continue to");
+                               return false;
+                       } else if (ec.CurrentBranching.InFinally (false)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else if (ec.CurrentBranching.InTryOrCatch (false))
+                               ec.CurrentBranching.AddFinallyVector (
+                                       ec.CurrentBranching.CurrentUsageVector);
+                       else if (ec.CurrentBranching.InLoop ())
+                               ec.CurrentBranching.AddBreakVector (
+                                       ec.CurrentBranching.CurrentUsageVector);
+
+                       crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
+                       ec.CurrentBranching.CurrentUsageVector.Break ();
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
 
-                       if (ec.InLoop == false && ec.Switch == null){
-                               Report.Error (139, loc, "No enclosing loop or switch to continue to");
-                               return false;
-                       }
-
-                       if (ec.InTry || ec.InCatch)
+                       if (crossing_exc)
                                ig.Emit (OpCodes.Leave, ec.LoopEnd);
-                       else
+                       else {
+                               ec.NeedReturnLabel ();
                                ig.Emit (OpCodes.Br, ec.LoopEnd);
-
-                       return false;
+                       }
                }
        }
 
@@ -986,1529 +906,111 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               bool crossing_exc;
+
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       if (!ec.CurrentBranching.InLoop () && !ec.CurrentBranching.InSwitch ()){
+                               Error (139, "No enclosing loop to continue to");
+                               return false;
+                       } else if (ec.CurrentBranching.InFinally (false)) {
+                               Error (157, "Control can not leave the body of the finally block");
+                               return false;
+                       } else if (ec.CurrentBranching.InTryOrCatch (false))
+                               ec.CurrentBranching.AddFinallyVector (ec.CurrentBranching.CurrentUsageVector);
+
+                       crossing_exc = ec.CurrentBranching.BreakCrossesTryCatchBoundary ();
+
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        Label begin = ec.LoopBegin;
                        
-                       if (!ec.InLoop){
-                               Report.Error (139, loc, "No enclosing loop to continue to");
-                               return false;
-                       } 
-
-                       //
-                       // UGH: Non trivial.  This Br might cross a try/catch boundary
-                       // How can we tell?
-                       //
-                       // while () {
-                       //   try { ... } catch { continue; }
-                       // }
-                       //
-                       // From:
-                       // try {} catch { while () { continue; }}
-                       //
-                       if (ec.TryCatchLevel > ec.LoopBeginTryCatchLevel)
+                       if (crossing_exc)
                                ec.ig.Emit (OpCodes.Leave, begin);
-                       else if (ec.TryCatchLevel < ec.LoopBeginTryCatchLevel)
-                               throw new Exception ("Should never happen");
                        else
                                ec.ig.Emit (OpCodes.Br, begin);
-                       return false;
-               }
-       }
-
-       // <summary>
-       //   This is used in the control flow analysis code to specify whether the
-       //   current code block may return to its enclosing block before reaching
-       //   its end.
-       // </summary>
-       public enum FlowReturns {
-               // It can never return.
-               NEVER,
-
-               // This means that the block contains a conditional return statement
-               // somewhere.
-               SOMETIMES,
-
-               // The code always returns, ie. there's an unconditional return / break
-               // statement in it.
-               ALWAYS,
-
-               // The code always throws an exception.
-               EXCEPTION,
-
-               // The current code block is unreachable.  This happens if it's immediately
-               // following a FlowReturns.ALWAYS block.
-               UNREACHABLE
-       }
-
-       // <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 readonly MyBitVector InheritsFrom;
-
-               bool is_dirty;
-               BitArray vector;
-
-               public MyBitVector (int Count)
-                       : this (null, Count)
-               { }
-
-               public MyBitVector (MyBitVector InheritsFrom, int Count)
-               {
-                       this.InheritsFrom = InheritsFrom;
-                       this.Count = Count;
-               }
-
-               // <summary>
-               //   Checks whether this bit vector has been modified.  After setting this to true,
-               //   we won't use the inherited vector anymore, but our own copy of it.
-               // </summary>
-               public bool IsDirty {
-                       get {
-                               return is_dirty;
-                       }
-
-                       set {
-                               if (!is_dirty)
-                                       initialize_vector ();
-                       }
-               }
-
-               // <summary>
-               //   Get/set bit `index' in the bit vector.
-               // </summary>
-               public bool this [int index]
-               {
-                       get {
-                               if (index > Count)
-                                       throw new ArgumentOutOfRangeException ();
-
-                               // We're doing a "copy-on-write" strategy here; as long
-                               // as nobody writes to the array, we can use our parent's
-                               // copy instead of duplicating the vector.
-
-                               if (vector != null)
-                                       return vector [index];
-                               else if (InheritsFrom != null) {
-                                       BitArray inherited = InheritsFrom.Vector;
-
-                                       if (index < inherited.Count)
-                                               return inherited [index];
-                                       else
-                                               return false;
-                               } else
-                                       return false;
-                       }
-
-                       set {
-                               if (index > Count)
-                                       throw new ArgumentOutOfRangeException ();
-
-                               // Only copy the vector if we're actually modifying it.
-
-                               if (this [index] != value) {
-                                       initialize_vector ();
-
-                                       vector [index] = value;
-                               }
-                       }
-               }
-
-               // <summary>
-               //   If you explicitly convert the MyBitVector to a BitArray, you will get a deep
-               //   copy of the bit vector.
-               // </summary>
-               public static explicit operator BitArray (MyBitVector vector)
-               {
-                       vector.initialize_vector ();
-                       return vector.Vector;
-               }
-
-               // <summary>
-               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
-               //   different size than the current one.
-               // </summary>
-               public void Or (MyBitVector new_vector)
-               {
-                       BitArray new_array = new_vector.Vector;
-
-                       initialize_vector ();
-
-                       int upper;
-                       if (vector.Count < new_array.Count)
-                               upper = vector.Count;
-                       else
-                               upper = new_array.Count;
-
-                       for (int i = 0; i < upper; i++)
-                               vector [i] = vector [i] | new_array [i];
-               }
-
-               // <summary>
-               //   Perfonrms an `and' operation on the bit vector.  The `new_vector' may have
-               //   a different size than the current one.
-               // </summary>
-               public void And (MyBitVector new_vector)
-               {
-                       BitArray new_array = new_vector.Vector;
-
-                       initialize_vector ();
-
-                       int lower, upper;
-                       if (vector.Count < new_array.Count)
-                               lower = upper = vector.Count;
-                       else {
-                               lower = new_array.Count;
-                               upper = vector.Count;
-                       }
-
-                       for (int i = 0; i < lower; i++)
-                               vector [i] = vector [i] & new_array [i];
-
-                       for (int i = lower; i < upper; i++)
-                               vector [i] = false;
-               }
-
-               // <summary>
-               //   This does a deep copy of the bit vector.
-               // </summary>
-               public MyBitVector Clone ()
-               {
-                       MyBitVector retval = new MyBitVector (Count);
-
-                       retval.Vector = Vector;
-
-                       return retval;
-               }
-
-               BitArray Vector {
-                       get {
-                               if (vector != null)
-                                       return vector;
-                               else if (!is_dirty && (InheritsFrom != null))
-                                       return InheritsFrom.Vector;
-
-                               initialize_vector ();
-
-                               return vector;
-                       }
-
-                       set {
-                               initialize_vector ();
-
-                               for (int i = 0; i < Math.Min (vector.Count, value.Count); i++)
-                                       vector [i] = value [i];
-                       }
-               }
-
-               void initialize_vector ()
-               {
-                       if (vector != null)
-                               return;
-
-                       vector = new BitArray (Count, false);
-                       if (InheritsFrom != null)
-                               Vector = InheritsFrom.Vector;
-
-                       is_dirty = true;
-               }
-
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ("MyBitVector (");
-
-                       BitArray vector = Vector;
-                       sb.Append (Count);
-                       sb.Append (",");
-                       if (!IsDirty)
-                               sb.Append ("INHERITED - ");
-                       for (int i = 0; i < vector.Count; i++) {
-                               if (i > 0)
-                                       sb.Append (",");
-                               sb.Append (vector [i]);
-                       }
-                       
-                       sb.Append (")");
-                       return sb.ToString ();
                }
        }
-
-       // <summary>
-       //   The type of a FlowBranching.
-       // </summary>
-       public enum FlowBranchingType {
-               // Normal (conditional or toplevel) block.
-               BLOCK,
-
-               // A loop block.
-               LOOP_BLOCK,
-
-               // Try/Catch block.
-               EXCEPTION,
-
-               // Switch block.
-               SWITCH,
-
-               // Switch section.
-               SWITCH_SECTION
-       }
-
-       // <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 class FlowBranching {
-               // <summary>
-               //   The type of this flow branching.
-               // </summary>
-               public readonly FlowBranchingType 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;
-
-               // <summary>
-               //   A list of UsageVectors.  A new vector is added each time control flow may
-               //   take a different path.
-               // </summary>
-               public UsageVector[] Siblings;
-
-               // <summary>
-               //   If this is an infinite loop.
-               // </summary>
-               public bool Infinite;
-
-               // <summary>
-               //   If we may leave the current loop.
-               // </summary>
-               public bool MayLeaveLoop;
-
-               //
-               // Private
-               //
-               InternalParameters param_info;
-               int[] param_map;
-               MyStructInfo[] struct_params;
-               int num_params;
-               ArrayList finally_vectors;
-
-               static int next_id = 0;
-               int id;
-
-               // <summary>
-               //   Performs an `And' operation on the FlowReturns status
-               //   (for instance, a block only returns ALWAYS if all its siblings
-               //   always return).
-               // </summary>
-               public static FlowReturns AndFlowReturns (FlowReturns a, FlowReturns b)
-               {
-                       if (b == FlowReturns.UNREACHABLE)
-                               return a;
-
-                       switch (a) {
-                       case FlowReturns.NEVER:
-                               if (b == FlowReturns.NEVER)
-                                       return FlowReturns.NEVER;
-                               else
-                                       return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.SOMETIMES:
-                               return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.ALWAYS:
-                               if ((b == FlowReturns.ALWAYS) || (b == FlowReturns.EXCEPTION))
-                                       return FlowReturns.ALWAYS;
-                               else
-                                       return FlowReturns.SOMETIMES;
-
-                       case FlowReturns.EXCEPTION:
-                               if (b == FlowReturns.EXCEPTION)
-                                       return FlowReturns.EXCEPTION;
-                               else if (b == FlowReturns.ALWAYS)
-                                       return FlowReturns.ALWAYS;
-                               else
-                                       return FlowReturns.SOMETIMES;
-                       }
-
-                       return b;
-               }
-
-               // <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>
-                       //   If this is true, then the usage vector has been modified and must be
-                       //   merged when we're done with this branching.
-                       // </summary>
-                       public bool IsDirty;
-
-                       // <summary>
-                       //   The number of parameters in this block.
-                       // </summary>
-                       public readonly int CountParameters;
-
-                       // <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;
-
-                       //
-                       // Private.
-                       //
-                       MyBitVector locals, parameters;
-                       FlowReturns real_returns, real_breaks;
-                       bool is_finally;
-
-                       static int next_id = 0;
-                       int id;
-
-                       //
-                       // Normally, you should not use any of these constructors.
-                       //
-                       public UsageVector (UsageVector parent, int num_params, int num_locals)
-                       {
-                               this.InheritsFrom = parent;
-                               this.CountParameters = num_params;
-                               this.CountLocals = num_locals;
-                               this.real_returns = FlowReturns.NEVER;
-                               this.real_breaks = FlowReturns.NEVER;
-
-                               if (parent != null) {
-                                       locals = new MyBitVector (parent.locals, CountLocals);
-                                       if (num_params > 0)
-                                               parameters = new MyBitVector (parent.parameters, num_params);
-                                       real_returns = parent.Returns;
-                                       real_breaks = parent.Breaks;
-                               } else {
-                                       locals = new MyBitVector (null, CountLocals);
-                                       if (num_params > 0)
-                                               parameters = new MyBitVector (null, num_params);
-                               }
-
-                               id = ++next_id;
-                       }
-
-                       public UsageVector (UsageVector parent)
-                               : this (parent, parent.CountParameters, parent.CountLocals)
-                       { }
-
-                       // <summary>
-                       //   This does a deep copy of the usage vector.
-                       // </summary>
-                       public UsageVector Clone ()
-                       {
-                               UsageVector retval = new UsageVector (null, CountParameters, CountLocals);
-
-                               retval.locals = locals.Clone ();
-                               if (parameters != null)
-                                       retval.parameters = parameters.Clone ();
-                               retval.real_returns = real_returns;
-                               retval.real_breaks = real_breaks;
-
-                               return retval;
-                       }
-
-                       // 
-                       // State of parameter `number'.
-                       //
-                       public bool this [int number]
-                       {
-                               get {
-                                       if (number == -1)
-                                               return true;
-                                       else if (number == 0)
-                                               throw new ArgumentException ();
-
-                                       return parameters [number - 1];
-                               }
-
-                               set {
-                                       if (number == -1)
-                                               return;
-                                       else if (number == 0)
-                                               throw new ArgumentException ();
-
-                                       parameters [number - 1] = value;
-                               }
-                       }
-
-                       //
-                       // State of the local variable `vi'.
-                       // If the local variable is a struct, use a non-zero `field_idx'
-                       // to check an individual field in it.
-                       //
-                       public bool this [VariableInfo vi, int field_idx]
-                       {
-                               get {
-                                       if (vi.Number == -1)
-                                               return true;
-                                       else if (vi.Number == 0)
-                                               throw new ArgumentException ();
-
-                                       return locals [vi.Number + field_idx - 1];
-                               }
-
-                               set {
-                                       if (vi.Number == -1)
-                                               return;
-                                       else if (vi.Number == 0)
-                                               throw new ArgumentException ();
-
-                                       locals [vi.Number + field_idx - 1] = value;
-                               }
-                       }
-
-                       // <summary>
-                       //   Specifies when the current block returns.
-                       //   If this is FlowReturns.UNREACHABLE, then control can never reach the
-                       //   end of the method (so that we don't need to emit a return statement).
-                       //   The same applies for FlowReturns.EXCEPTION, but in this case the return
-                       //   value will never be used.
-                       // </summary>
-                       public FlowReturns Returns {
-                               get {
-                                       return real_returns;
-                               }
-
-                               set {
-                                       real_returns = value;
-                               }
-                       }
-
-                       // <summary>
-                       //   Specifies whether control may return to our containing block
-                       //   before reaching the end of this block.  This happens if there
-                       //   is a break/continue/goto/return in it.
-                       //   This can also be used to find out whether the statement immediately
-                       //   following the current block may be reached or not.
-                       // </summary>
-                       public FlowReturns Breaks {
-                               get {
-                                       return real_breaks;
-                               }
-
-                               set {
-                                       real_breaks = value;
-                               }
-                       }
-
-                       public bool AlwaysBreaks {
-                               get {
-                                       return (Breaks == FlowReturns.ALWAYS) ||
-                                               (Breaks == FlowReturns.EXCEPTION) ||
-                                               (Breaks == FlowReturns.UNREACHABLE);
-                               }
-                       }
-
-                       public bool MayBreak {
-                               get {
-                                       return Breaks != FlowReturns.NEVER;
-                               }
-                       }
-
-                       public bool AlwaysReturns {
-                               get {
-                                       return (Returns == FlowReturns.ALWAYS) ||
-                                               (Returns == FlowReturns.EXCEPTION);
-                               }
-                       }
-
-                       public bool MayReturn {
-                               get {
-                                       return (Returns == FlowReturns.SOMETIMES) ||
-                                               (Returns == FlowReturns.ALWAYS);
-                               }
-                       }
-
-                       // <summary>
-                       //   Merge a child branching.
-                       // </summary>
-                       public FlowReturns MergeChildren (FlowBranching branching, UsageVector[] children)
-                       {
-                               MyBitVector new_locals = null;
-                               MyBitVector new_params = null;
-
-                               FlowReturns new_returns = FlowReturns.NEVER;
-                               FlowReturns new_breaks = FlowReturns.NEVER;
-                               bool new_returns_set = false, new_breaks_set = false;
-
-                               Report.Debug (2, "MERGING CHILDREN", branching, branching.Type,
-                                             this, children.Length);
-
-                               foreach (UsageVector child in children) {
-                                       Report.Debug (2, "  MERGING CHILD", child, child.is_finally);
-                                       
-                                       if (!child.is_finally) {
-                                               if (child.Breaks != FlowReturns.UNREACHABLE) {
-                                                       // If Returns is already set, perform an
-                                                       // `And' operation on it, otherwise just set just.
-                                                       if (!new_returns_set) {
-                                                               new_returns = child.Returns;
-                                                               new_returns_set = true;
-                                                       } else
-                                                               new_returns = AndFlowReturns (
-                                                                       new_returns, child.Returns);
-                                               }
-
-                                               // If Breaks is already set, perform an
-                                               // `And' operation on it, otherwise just set just.
-                                               if (!new_breaks_set) {
-                                                       new_breaks = child.Breaks;
-                                                       new_breaks_set = true;
-                                               } else
-                                                       new_breaks = AndFlowReturns (
-                                                               new_breaks, child.Breaks);
-                                       }
-
-                                       // Ignore unreachable children.
-                                       if (child.Returns == FlowReturns.UNREACHABLE)
-                                               continue;
-
-                                       // A local variable is initialized after a flow branching if it
-                                       // has been initialized in all its branches which do neither
-                                       // always return or always throw an exception.
-                                       //
-                                       // If a branch may return, but does not always return, then we
-                                       // can treat it like a never-returning branch here: control will
-                                       // only reach the code position after the branching if we did not
-                                       // return here.
-                                       //
-                                       // It's important to distinguish between always and sometimes
-                                       // returning branches here:
-                                       //
-                                       //    1   int a;
-                                       //    2   if (something) {
-                                       //    3      return;
-                                       //    4      a = 5;
-                                       //    5   }
-                                       //    6   Console.WriteLine (a);
-                                       //
-                                       // The if block in lines 3-4 always returns, so we must not look
-                                       // at the initialization of `a' in line 4 - thus it'll still be
-                                       // uninitialized in line 6.
-                                       //
-                                       // On the other hand, the following is allowed:
-                                       //
-                                       //    1   int a;
-                                       //    2   if (something)
-                                       //    3      a = 5;
-                                       //    4   else
-                                       //    5      return;
-                                       //    6   Console.WriteLine (a);
-                                       //
-                                       // Here, `a' is initialized in line 3 and we must not look at
-                                       // line 5 since it always returns.
-                                       // 
-                                       if (child.is_finally) {
-                                               if (new_locals == null)
-                                                       new_locals = locals.Clone ();
-                                               new_locals.Or (child.locals);
-
-                                               if (parameters != null) {
-                                                       if (new_params == null)
-                                                               new_params = parameters.Clone ();
-                                                       new_params.Or (child.parameters);
-                                               }
-
-                                       } else {
-                                               if (!child.AlwaysReturns && !child.AlwaysBreaks) {
-                                                       if (new_locals != null)
-                                                               new_locals.And (child.locals);
-                                                       else {
-                                                               new_locals = locals.Clone ();
-                                                               new_locals.Or (child.locals);
-                                                       }
-                                               } else if (children.Length == 1) {
-                                                       new_locals = locals.Clone ();
-                                                       new_locals.Or (child.locals);
-                                               }
-
-                                               // An `out' parameter must be assigned in all branches which do
-                                               // not always throw an exception.
-                                               if (parameters != null) {
-                                                       if (child.Breaks != FlowReturns.EXCEPTION) {
-                                                               if (new_params != null)
-                                                                       new_params.And (child.parameters);
-                                                               else {
-                                                                       new_params = parameters.Clone ();
-                                                                       new_params.Or (child.parameters);
-                                                               }
-                                                       } else if (children.Length == 1) {
-                                                               new_params = parameters.Clone ();
-                                                               new_params.Or (child.parameters);
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               Returns = new_returns;
-                               if ((branching.Type == FlowBranchingType.BLOCK) ||
-                                   (branching.Type == FlowBranchingType.EXCEPTION) ||
-                                   (new_breaks == FlowReturns.UNREACHABLE) ||
-                                   (new_breaks == FlowReturns.EXCEPTION))
-                                       Breaks = new_breaks;
-                               else if (branching.Type == FlowBranchingType.SWITCH_SECTION)
-                                       Breaks = new_returns;
-                               else if (branching.Type == FlowBranchingType.SWITCH){
-                                       if (new_breaks == FlowReturns.ALWAYS)
-                                               Breaks = FlowReturns.ALWAYS;
-                               }
-
-                               //
-                               // 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 (((new_breaks != FlowReturns.ALWAYS) &&
-                                    (new_breaks != FlowReturns.EXCEPTION) &&
-                                    (new_breaks != FlowReturns.UNREACHABLE)) ||
-                                   (children.Length == 1)) {
-                                       if (new_locals != null)
-                                               locals.Or (new_locals);
-
-                                       if (new_params != null)
-                                               parameters.Or (new_params);
-                               }
-
-                               Report.Debug (2, "MERGING CHILDREN DONE", branching.Type,
-                                             new_params, new_locals, new_returns, new_breaks,
-                                             branching.Infinite, branching.MayLeaveLoop, this);
-
-                               if (branching.Type == FlowBranchingType.SWITCH_SECTION) {
-                                       if ((new_breaks != FlowReturns.ALWAYS) &&
-                                           (new_breaks != FlowReturns.EXCEPTION) &&
-                                           (new_breaks != FlowReturns.UNREACHABLE))
-                                               Report.Error (163, branching.Location,
-                                                             "Control cannot fall through from one " +
-                                                             "case label to another");
-                               }
-
-                               if (branching.Infinite && !branching.MayLeaveLoop) {
-                                       Report.Debug (1, "INFINITE", new_returns, new_breaks,
-                                                     Returns, Breaks, this);
-
-                                       // We're actually infinite.
-                                       if (new_returns == FlowReturns.NEVER) {
-                                               Breaks = FlowReturns.UNREACHABLE;
-                                               return FlowReturns.UNREACHABLE;
-                                       }
-
-                                       // If we're an infinite loop and do not break, the code after
-                                       // the loop can never be reached.  However, if we may return
-                                       // from the loop, then we do always return (or stay in the loop
-                                       // forever).
-                                       if ((new_returns == FlowReturns.SOMETIMES) ||
-                                           (new_returns == FlowReturns.ALWAYS)) {
-                                               Returns = FlowReturns.ALWAYS;
-                                               return FlowReturns.ALWAYS;
-                                       }
-                               }
-
-                               return new_returns;
-                       }
-
-                       // <summary>
-                       //   Tells control flow analysis that the current code position may be reached with
-                       //   a forward jump from any of the origins listed in `origin_vectors' which is a
-                       //   list of UsageVectors.
-                       //
-                       //   This is used when resolving forward gotos - in the following example, the
-                       //   variable `a' is uninitialized in line 8 becase this line may be reached via
-                       //   the goto in line 4:
-                       //
-                       //      1     int a;
-                       //
-                       //      3     if (something)
-                       //      4        goto World;
-                       //
-                       //      6     a = 5;
-                       //
-                       //      7  World:
-                       //      8     Console.WriteLine (a);
-                       //
-                       // </summary>
-                       public void MergeJumpOrigins (ICollection origin_vectors)
-                       {
-                               Report.Debug (1, "MERGING JUMP ORIGIN", this);
-
-                               real_breaks = FlowReturns.NEVER;
-                               real_returns = FlowReturns.NEVER;
-
-                               foreach (UsageVector vector in origin_vectors) {
-                                       Report.Debug (1, "  MERGING JUMP ORIGIN", vector);
-
-                                       locals.And (vector.locals);
-                                       if (parameters != null)
-                                               parameters.And (vector.parameters);
-                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
-                                       Returns = AndFlowReturns (Returns, vector.Returns);
-                               }
-
-                               Report.Debug (1, "MERGING JUMP ORIGIN DONE", this);
-                       }
-
-                       // <summary>
-                       //   This is used at the beginning of a finally block if there were
-                       //   any return statements in the try block or one of the catch blocks.
-                       // </summary>
-                       public void MergeFinallyOrigins (ICollection finally_vectors)
-                       {
-                               Report.Debug (1, "MERGING FINALLY ORIGIN", this);
-
-                               real_breaks = FlowReturns.NEVER;
-
-                               foreach (UsageVector vector in finally_vectors) {
-                                       Report.Debug (1, "  MERGING FINALLY ORIGIN", vector);
-
-                                       if (parameters != null)
-                                               parameters.And (vector.parameters);
-                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
-                               }
-
-                               is_finally = true;
-
-                               Report.Debug (1, "MERGING FINALLY ORIGIN DONE", this);
-                       }
-
-                       public void CheckOutParameters (FlowBranching branching)
-                       {
-                               if (parameters != null)
-                                       branching.CheckOutParameters (parameters, branching.Location);
-                       }
-
-                       // <summary>
-                       //   Performs an `or' operation on the locals and the parameters.
-                       // </summary>
-                       public void Or (UsageVector new_vector)
-                       {
-                               locals.Or (new_vector.locals);
-                               if (parameters != null)
-                                       parameters.Or (new_vector.parameters);
-                       }
-
-                       // <summary>
-                       //   Performs an `and' operation on the locals.
-                       // </summary>
-                       public void AndLocals (UsageVector new_vector)
-                       {
-                               locals.And (new_vector.locals);
-                       }
-
-                       // <summary>
-                       //   Returns a deep copy of the parameters.
-                       // </summary>
-                       public MyBitVector Parameters {
-                               get {
-                                       if (parameters != null)
-                                               return parameters.Clone ();
-                                       else
-                                               return null;
-                               }
-                       }
-
-                       // <summary>
-                       //   Returns a deep copy of the locals.
-                       // </summary>
-                       public MyBitVector Locals {
-                               get {
-                                       return locals.Clone ();
-                               }
-                       }
-
-                       //
-                       // Debugging stuff.
-                       //
-
-                       public override string ToString ()
-                       {
-                               StringBuilder sb = new StringBuilder ();
-
-                               sb.Append ("Vector (");
-                               sb.Append (id);
-                               sb.Append (",");
-                               sb.Append (Returns);
-                               sb.Append (",");
-                               sb.Append (Breaks);
-                               if (parameters != null) {
-                                       sb.Append (" - ");
-                                       sb.Append (parameters);
-                               }
-                               sb.Append (" - ");
-                               sb.Append (locals);
-                               sb.Append (")");
-
-                               return sb.ToString ();
-                       }
-               }
-
-               FlowBranching (FlowBranchingType type, Location loc)
-               {
-                       this.Block = null;
-                       this.Location = loc;
-                       this.Type = type;
-                       id = ++next_id;
-               }
-
-               // <summary>
-               //   Creates a new flow branching for `block'.
-               //   This is used from Block.Resolve to create the top-level branching of
-               //   the block.
-               // </summary>
-               public FlowBranching (Block block, InternalParameters ip, Location loc)
-                       : this (FlowBranchingType.BLOCK, loc)
-               {
-                       Block = block;
-                       Parent = null;
-
-                       int count = (ip != null) ? ip.Count : 0;
-
-                       param_info = ip;
-                       param_map = new int [count];
-                       struct_params = new MyStructInfo [count];
-                       num_params = 0;
-
-                       for (int i = 0; i < count; i++) {
-                               Parameter.Modifier mod = param_info.ParameterModifier (i);
-
-                               if ((mod & Parameter.Modifier.OUT) == 0)
-                                       continue;
-
-                               param_map [i] = ++num_params;
-
-                               Type param_type = param_info.ParameterType (i);
-
-                               struct_params [i] = MyStructInfo.GetStructInfo (param_type);
-                               if (struct_params [i] != null)
-                                       num_params += struct_params [i].Count;
-                       }
-
-                       AddSibling (new UsageVector (null, num_params, block.CountVariables));
-               }
-
-               // <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>
-               public FlowBranching (FlowBranching parent, FlowBranchingType type,
-                                     Block block, Location loc)
-                       : this (type, loc)
-               {
-                       Parent = parent;
-                       Block = block;
-
-                       if (parent != null) {
-                               param_info = parent.param_info;
-                               param_map = parent.param_map;
-                               struct_params = parent.struct_params;
-                               num_params = parent.num_params;
-                       }
-
-                       UsageVector vector;
-                       if (Block != null)
-                               vector = new UsageVector (parent.CurrentUsageVector, num_params,
-                                                         Block.CountVariables);
-                       else
-                               vector = new UsageVector (Parent.CurrentUsageVector);
-
-                       AddSibling (vector);
-
-                       switch (Type) {
-                       case FlowBranchingType.EXCEPTION:
-                               finally_vectors = new ArrayList ();
-                               break;
-
-                       default:
-                               break;
-                       }
-               }
-
-               void AddSibling (UsageVector uv)
-               {
-                       if (Siblings != null) {
-                               UsageVector[] ns = new UsageVector [Siblings.Length + 1];
-                               for (int i = 0; i < Siblings.Length; ++i)
-                                       ns [i] = Siblings [i];
-                               Siblings = ns;
-                       } else {
-                               Siblings = new UsageVector [1];
-                       }
-                       Siblings [Siblings.Length - 1] = uv;
-               }
-
-               // <summary>
-               //   Returns the branching's current usage vector.
-               // </summary>
-               public UsageVector CurrentUsageVector
-               {
-                       get {
-                               return Siblings [Siblings.Length - 1];
-                       }
-               }
-
-               // <summary>
-               //   Creates a sibling of the current usage vector.
-               // </summary>
-               public void CreateSibling ()
-               {
-                       AddSibling (new UsageVector (Parent.CurrentUsageVector));
-
-                       Report.Debug (1, "CREATED SIBLING", CurrentUsageVector);
-               }
-
-               // <summary>
-               //   Creates a sibling for a `finally' block.
-               // </summary>
-               public void CreateSiblingForFinally ()
-               {
-                       if (Type != FlowBranchingType.EXCEPTION)
-                               throw new NotSupportedException ();
-
-                       CreateSibling ();
-
-                       CurrentUsageVector.MergeFinallyOrigins (finally_vectors);
-               }
-
-               // <summary>
-               //   Check whether all `out' parameters have been assigned.
-               // </summary>
-               public void CheckOutParameters (MyBitVector parameters, Location loc)
-               {
-                       if (InTryBlock ())
-                               return;
-
-                       for (int i = 0; i < param_map.Length; i++) {
-                               int index = param_map [i];
-
-                               if (index == 0)
-                                       continue;
-
-                               if (parameters [index - 1])
-                                       continue;
-
-                               // If it's a struct, we must ensure that all its fields have
-                               // been assigned.  If the struct has any non-public fields, this
-                               // can only be done by assigning the whole struct.
-
-                               MyStructInfo struct_info = struct_params [i];
-                               if ((struct_info == null) || struct_info.HasNonPublicFields) {
-                                       Report.Error (
-                                               177, loc, "The out parameter `" +
-                                               param_info.ParameterName (i) + "' must be " +
-                                               "assigned before control leave the current method.");
-                                       param_map [i] = 0;
-                                       continue;
-                               }
-
-
-                               for (int j = 0; j < struct_info.Count; j++) {
-                                       if (!parameters [index + j]) {
-                                               Report.Error (
-                                                       177, loc, "The out parameter `" +
-                                                       param_info.ParameterName (i) + "' must be " +
-                                                       "assigned before control leaves the current method.");
-                                               param_map [i] = 0;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               // <summary>
-               //   Merge a child branching.
-               // </summary>
-               public FlowReturns MergeChild (FlowBranching child)
-               {
-                       FlowReturns returns = CurrentUsageVector.MergeChildren (child, child.Siblings);
-
-                       if ((child.Type != FlowBranchingType.LOOP_BLOCK) &&
-                           (child.Type != FlowBranchingType.SWITCH_SECTION))
-                               MayLeaveLoop |= child.MayLeaveLoop;
-                       else
-                               MayLeaveLoop = false;
-
-                       return returns;
-               }
-               // <summary>
-               //   Does the toplevel merging.
-               // </summary>
-               public FlowReturns MergeTopBlock ()
-               {
-                       if ((Type != FlowBranchingType.BLOCK) || (Block == null))
-                               throw new NotSupportedException ();
-
-                       UsageVector vector = new UsageVector (null, num_params, Block.CountVariables);
-
-                       Report.Debug (1, "MERGING TOP BLOCK", Location, vector);
-
-                       vector.MergeChildren (this, Siblings);
-
-                       if (Siblings.Length == 1)
-                               Siblings [0] = vector;
-                       else {
-                               Siblings = null;
-                               AddSibling (vector);
-                       }
-
-                       Report.Debug (1, "MERGING TOP BLOCK DONE", Location, vector);
-
-                       if (vector.Breaks != FlowReturns.EXCEPTION) {
-                               if (!vector.AlwaysBreaks)
-                                       CheckOutParameters (CurrentUsageVector.Parameters, Location);
-                               return vector.AlwaysBreaks ? FlowReturns.ALWAYS : vector.Returns;
-                       } else
-                               return FlowReturns.EXCEPTION;
-               }
-
-               public bool InTryBlock ()
-               {
-                       if (finally_vectors != null)
-                               return true;
-                       else if (Parent != null)
-                               return Parent.InTryBlock ();
-                       else
-                               return false;
-               }
-
-               public void AddFinallyVector (UsageVector vector)
-               {
-                       if (finally_vectors != null) {
-                               finally_vectors.Add (vector.Clone ());
-                               return;
-                       }
-
-                       if (Parent != null)
-                               Parent.AddFinallyVector (vector);
-                       else
-                               throw new NotSupportedException ();
-               }
-
-               public bool IsVariableAssigned (VariableInfo vi)
-               {
-                       if (CurrentUsageVector.AlwaysBreaks)
-                               return true;
-                       else
-                               return CurrentUsageVector [vi, 0];
-               }
-
-               public bool IsVariableAssigned (VariableInfo vi, int field_idx)
-               {
-                       if (CurrentUsageVector.AlwaysBreaks)
-                               return true;
-                       else
-                               return CurrentUsageVector [vi, field_idx];
-               }
-
-               public void SetVariableAssigned (VariableInfo vi)
-               {
-                       if (CurrentUsageVector.AlwaysBreaks)
-                               return;
-
-                       CurrentUsageVector [vi, 0] = true;
-               }
-
-               public void SetVariableAssigned (VariableInfo vi, int field_idx)
-               {
-                       if (CurrentUsageVector.AlwaysBreaks)
-                               return;
-
-                       CurrentUsageVector [vi, field_idx] = true;
-               }
-
-               public bool IsParameterAssigned (int number)
-               {
-                       int index = param_map [number];
-
-                       if (index == 0)
-                               return true;
-
-                       if (CurrentUsageVector [index])
-                               return true;
-
-                       // Parameter is not assigned, so check whether it's a struct.
-                       // If it's either not a struct or a struct which non-public
-                       // fields, return false.
-                       MyStructInfo struct_info = struct_params [number];
-                       if ((struct_info == null) || struct_info.HasNonPublicFields)
-                               return false;
-
-                       // Ok, so each field must be assigned.
-                       for (int i = 0; i < struct_info.Count; i++)
-                               if (!CurrentUsageVector [index + i])
-                                       return false;
-
-                       return true;
-               }
-
-               public bool IsParameterAssigned (int number, string field_name)
-               {
-                       int index = param_map [number];
-
-                       if (index == 0)
-                               return true;
-
-                       MyStructInfo info = (MyStructInfo) struct_params [number];
-                       if (info == null)
-                               return true;
-
-                       int field_idx = info [field_name];
-
-                       return CurrentUsageVector [index + field_idx];
-               }
-
-               public void SetParameterAssigned (int number)
-               {
-                       if (param_map [number] == 0)
-                               return;
-
-                       if (!CurrentUsageVector.AlwaysBreaks)
-                               CurrentUsageVector [param_map [number]] = true;
-               }
-
-               public void SetParameterAssigned (int number, string field_name)
-               {
-                       int index = param_map [number];
-
-                       if (index == 0)
-                               return;
-
-                       MyStructInfo info = (MyStructInfo) struct_params [number];
-                       if (info == null)
-                               return;
-
-                       int field_idx = info [field_name];
-
-                       if (!CurrentUsageVector.AlwaysBreaks)
-                               CurrentUsageVector [index + field_idx] = true;
-               }
-
-               public bool IsReachable ()
-               {
-                       bool reachable;
-
-                       switch (Type) {
-                       case FlowBranchingType.SWITCH_SECTION:
-                               // The code following a switch block is reachable unless the switch
-                               // block always returns.
-                               reachable = !CurrentUsageVector.AlwaysReturns;
-                               break;
-
-                       case FlowBranchingType.LOOP_BLOCK:
-                               // The code following a loop is reachable unless the loop always
-                               // returns or it's an infinite loop without any `break's in it.
-                               reachable = !CurrentUsageVector.AlwaysReturns &&
-                                       (CurrentUsageVector.Breaks != FlowReturns.UNREACHABLE);
-                               break;
-
-                       default:
-                               // The code following a block or exception is reachable unless the
-                               // block either always returns or always breaks.
-                               reachable = !CurrentUsageVector.AlwaysBreaks &&
-                                       !CurrentUsageVector.AlwaysReturns;
-                               break;
-                       }
-
-                       Report.Debug (1, "REACHABLE", Type, CurrentUsageVector.Returns,
-                                     CurrentUsageVector.Breaks, CurrentUsageVector, reachable);
-
-                       return reachable;
-               }
-
-               public override string ToString ()
-               {
-                       StringBuilder sb = new StringBuilder ("FlowBranching (");
-
-                       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 ();
-               }
-       }
-
-       public class MyStructInfo {
-               public readonly Type Type;
-               public readonly FieldInfo[] Fields;
-               public readonly FieldInfo[] NonPublicFields;
-               public readonly int Count;
-               public readonly int CountNonPublic;
-               public readonly bool HasNonPublicFields;
-
-               private static Hashtable field_type_hash = new Hashtable ();
-               private Hashtable field_hash;
-
-               // Private constructor.  To save memory usage, we only need to create one instance
-               // of this class per struct type.
-               private MyStructInfo (Type type)
-               {
-                       this.Type = type;
-
-                       if (type is TypeBuilder) {
-                               TypeContainer tc = TypeManager.LookupTypeContainer (type);
-
-                               Field [] fields = tc.Fields;
-                               if (fields != null) {
-                                       foreach (Field field in fields) {
-                                               if ((field.ModFlags & Modifiers.STATIC) != 0)
-                                                       continue;
-                                               if ((field.ModFlags & Modifiers.PUBLIC) != 0)
-                                                       ++Count;
-                                               else
-                                                       ++CountNonPublic;
-                                       }
-                               }
-
-                               Fields = new FieldInfo [Count];
-                               NonPublicFields = new FieldInfo [CountNonPublic];
-
-                               Count = CountNonPublic = 0;
-                               if (fields != null) {
-                                       foreach (Field field in fields) {
-                                               if ((field.ModFlags & Modifiers.STATIC) != 0)
-                                                       continue;
-                                               if ((field.ModFlags & Modifiers.PUBLIC) != 0)
-                                                       Fields [Count++] = field.FieldBuilder;
-                                               else
-                                                       NonPublicFields [CountNonPublic++] =
-                                                               field.FieldBuilder;
-                                       }
-                               }
-                               
-                       } else {
-                               Fields = type.GetFields (BindingFlags.Instance|BindingFlags.Public);
-                               Count = Fields.Length;
-
-                               NonPublicFields = type.GetFields (BindingFlags.Instance|BindingFlags.NonPublic);
-                               CountNonPublic = NonPublicFields.Length;
-                       }
-
-                       Count += NonPublicFields.Length;
-
-                       int number = 0;
-                       field_hash = new Hashtable ();
-                       foreach (FieldInfo field in Fields)
-                               field_hash.Add (field.Name, ++number);
-
-                       if (NonPublicFields.Length != 0)
-                               HasNonPublicFields = true;
-
-                       foreach (FieldInfo field in NonPublicFields)
-                               field_hash.Add (field.Name, ++number);
-               }
-
-               public int this [string name] {
-                       get {
-                               if (field_hash.Contains (name))
-                                       return (int) field_hash [name];
-                               else
-                                       return 0;
-                       }
-               }
-
-               public FieldInfo this [int index] {
-                       get {
-                               if (index >= Fields.Length)
-                                       return NonPublicFields [index - Fields.Length];
-                               else
-                                       return Fields [index];
-                       }
-               }                      
-
-               public static MyStructInfo GetStructInfo (Type type)
-               {
-                       if (!TypeManager.IsValueType (type) || TypeManager.IsEnumType (type))
-                               return null;
-
-                       if (!(type is TypeBuilder) && TypeManager.IsBuiltinType (type))
-                               return null;
-
-                       MyStructInfo info = (MyStructInfo) field_type_hash [type];
-                       if (info != null)
-                               return info;
-
-                       info = new MyStructInfo (type);
-                       field_type_hash.Add (type, info);
-                       return info;
-               }
-
-               public static MyStructInfo GetStructInfo (TypeContainer tc)
-               {
-                       MyStructInfo info = (MyStructInfo) field_type_hash [tc.TypeBuilder];
-                       if (info != null)
-                               return info;
-
-                       info = new MyStructInfo (tc.TypeBuilder);
-                       field_type_hash.Add (tc.TypeBuilder, info);
-                       return info;
-               }
-       }
-       
-       public class VariableInfo : IVariable {
+
+       public class LocalInfo {
                public Expression Type;
+
+               //
+               // Most of the time a variable will be stored in a LocalBuilder
+               //
+               // But sometimes, it will be stored in a field.  The context of the field will
+               // be stored in the EmitContext
+               //
+               //
                public LocalBuilder LocalBuilder;
+               public FieldBuilder FieldBuilder;
+
                public Type VariableType;
                public readonly string Name;
                public readonly Location Location;
-               public readonly int Block;
+               public readonly Block Block;
 
-               public int Number;
-               
-               public bool Used;
-               public bool Assigned;
-               public bool ReadOnly;
+               public VariableInfo VariableInfo;
+
+               enum Flags : byte {
+                       Used = 1,
+                       ReadOnly = 2,
+                       Fixed = 4
+               }
+
+               Flags flags;
                
-               public VariableInfo (Expression type, string name, int block, Location l)
+               public LocalInfo (Expression type, string name, Block block, Location l)
                {
                        Type = type;
                        Name = name;
                        Block = block;
-                       LocalBuilder = null;
                        Location = l;
                }
 
-               public VariableInfo (TypeContainer tc, int block, Location l)
+               public LocalInfo (TypeContainer tc, Block block, Location l)
                {
                        VariableType = tc.TypeBuilder;
-                       struct_info = MyStructInfo.GetStructInfo (tc);
                        Block = block;
-                       LocalBuilder = null;
                        Location = l;
                }
 
-               MyStructInfo struct_info;
-               public MyStructInfo StructInfo {
-                       get {
-                               return struct_info;
-                       }
-               }
-
-               public bool IsAssigned (EmitContext ec, Location loc)
-               {
-                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsVariableAssigned (this))
-                               return true;
-
-                       MyStructInfo struct_info = StructInfo;
-                       if ((struct_info == null) || (struct_info.HasNonPublicFields && (Name != null))) {
-                               Report.Error (165, loc, "Use of unassigned local variable `" + Name + "'");
-                               ec.CurrentBranching.SetVariableAssigned (this);
-                               return false;
-                       }
-
-                       int count = struct_info.Count;
-
-                       for (int i = 0; i < count; i++) {
-                               if (!ec.CurrentBranching.IsVariableAssigned (this, i+1)) {
-                                       if (Name != null) {
-                                               Report.Error (165, loc,
-                                                             "Use of unassigned local variable `" +
-                                                             Name + "'");
-                                               ec.CurrentBranching.SetVariableAssigned (this);
-                                               return false;
-                                       }
-
-                                       FieldInfo field = struct_info [i];
-                                       Report.Error (171, loc,
-                                                     "Field `" + TypeManager.CSharpName (VariableType) +
-                                                     "." + field.Name + "' must be fully initialized " +
-                                                     "before control leaves the constructor");
-                                       return false;
-                               }
-                       }
-
-                       return true;
-               }
-
-               public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
+               public bool IsThisAssigned (EmitContext ec, Location loc)
                {
-                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsVariableAssigned (this) ||
-                           (struct_info == null))
-                               return true;
+                       if (VariableInfo == null)
+                               throw new Exception ();
 
-                       int field_idx = StructInfo [name];
-                       if (field_idx == 0)
+                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
                                return true;
 
-                       if (!ec.CurrentBranching.IsVariableAssigned (this, field_idx)) {
-                               Report.Error (170, loc,
-                                             "Use of possibly unassigned field `" + name + "'");
-                               ec.CurrentBranching.SetVariableAssigned (this, field_idx);
-                               return false;
-                       }
-
-                       return true;
+                       return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, loc);
                }
 
-               public void SetAssigned (EmitContext ec)
+               public bool IsAssigned (EmitContext ec)
                {
-                       if (ec.DoFlowAnalysis)
-                               ec.CurrentBranching.SetVariableAssigned (this);
-               }
+                       if (VariableInfo == null)
+                               throw new Exception ();
 
-               public void SetFieldAssigned (EmitContext ec, string name)
-               {
-                       if (ec.DoFlowAnalysis && (struct_info != null))
-                               ec.CurrentBranching.SetVariableAssigned (this, StructInfo [name]);
+                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
                }
 
                public bool Resolve (DeclSpace decl)
                {
-                       if (struct_info != null)
-                               return true;
-
                        if (VariableType == null)
                                VariableType = decl.ResolveType (Type, false, Location);
 
-                       if (VariableType == null)
+                       if (VariableType == TypeManager.void_type) {
+                               Report.Error (1547, Location,
+                                             "Keyword 'void' cannot be used in this context");
                                return false;
+                       }
 
-                       struct_info = MyStructInfo.GetStructInfo (VariableType);
+                       if (VariableType == null)
+                               return false;
 
                        return true;
                }
@@ -2516,12 +1018,44 @@ namespace Mono.CSharp {
                public void MakePinned ()
                {
                        TypeManager.MakePinned (LocalBuilder);
+                       flags |= Flags.Fixed;
+               }
+
+               public bool IsFixed {
+                       get {
+                               if (((flags & Flags.Fixed) != 0) || TypeManager.IsValueType (VariableType))
+                                       return true;
+
+                               return false;
+                       }
                }
 
                public override string ToString ()
                {
-                       return "VariableInfo (" + Number + "," + Type + "," + Location + ")";
+                       return String.Format ("LocalInfo ({0},{1},{2},{3})",
+                                             Name, Type, VariableInfo, Location);
+               }
+
+               public bool Used {
+                       get {
+                               return (flags & Flags.Used) != 0;
+                       }
+                       set {
+                               flags = value ? (flags | Flags.Used) : (flags & ~Flags.Used);
+                       }
+               }
+
+               public bool ReadOnly {
+                       get {
+                               return (flags & Flags.ReadOnly) != 0;
+                       }
+                       set {
+                               flags = value ? (flags | Flags.ReadOnly) : (flags & ~Flags.ReadOnly);
+                       }
                }
+
+               
+               
        }
                
        /// <summary>
@@ -2534,17 +1068,46 @@ namespace Mono.CSharp {
        ///
        ///   Implicit blocks are used as labels or to introduce variable
        ///   declarations.
+       ///
+       ///   Top-level blocks derive from Block, and they are called ToplevelBlock
+       ///   they contain extra information that is not necessary on normal blocks.
        /// </remarks>
        public class Block : Statement {
                public readonly Block     Parent;
-               public readonly bool      Implicit;
                public readonly Location  StartLocation;
                public Location           EndLocation = Location.Null;
 
+               [Flags]
+               public enum Flags : byte {
+                       Implicit  = 1,
+                       Unchecked = 2,
+                       BlockUsed = 4,
+                       VariablesInitialized = 8,
+                       HasRet = 16,
+                       IsDestructor = 32       
+               }
+               Flags flags;
+
+               public bool Implicit {
+                       get {
+                               return (flags & Flags.Implicit) != 0;
+                       }
+               }
+
+               public bool Unchecked {
+                       get {
+                               return (flags & Flags.Unchecked) != 0;
+                       }
+                       set {
+                               flags |= Flags.Unchecked;
+                       }
+               }
+
                //
                // The statements in this block
                //
                ArrayList statements;
+               int num_statements;
 
                //
                // An array of Blocks.  We keep track of children just
@@ -2570,55 +1133,67 @@ namespace Mono.CSharp {
                Hashtable constants;
 
                //
-               // Maps variable names to ILGenerator.LocalBuilders
+               // If this is a switch section, the enclosing switch block.
                //
-               Hashtable local_builders;
-
-               bool used = false;
+               Block switch_block;
 
                static int id;
 
                int this_id;
                
                public Block (Block parent)
-                       : this (parent, false, Location.Null, Location.Null)
+                       : this (parent, (Flags) 0, Location.Null, Location.Null)
                { }
 
-               public Block (Block parent, bool implicit_block)
-                       : this (parent, implicit_block, Location.Null, Location.Null)
+               public Block (Block parent, Flags flags)
+                       : this (parent, flags, Location.Null, Location.Null)
                { }
 
-               public Block (Block parent, bool implicit_block, Parameters parameters)
-                       : this (parent, implicit_block, parameters, Location.Null, Location.Null)
+               public Block (Block parent, Flags flags, Parameters parameters)
+                       : this (parent, flags, parameters, Location.Null, Location.Null)
                { }
 
                public Block (Block parent, Location start, Location end)
-                       : this (parent, false, start, end)
+                       : this (parent, (Flags) 0, start, end)
                { }
 
                public Block (Block parent, Parameters parameters, Location start, Location end)
-                       : this (parent, false, parameters, start, end)
+                       : this (parent, (Flags) 0, parameters, start, end)
                { }
 
-               public Block (Block parent, bool implicit_block, Location start, Location end)
-                       : this (parent, implicit_block, Parameters.EmptyReadOnlyParameters,
-                               start, end)
+               public Block (Block parent, Flags flags, Location start, Location end)
+                       : this (parent, flags, Parameters.EmptyReadOnlyParameters, start, end)
                { }
 
-               public Block (Block parent, bool implicit_block, Parameters parameters,
+               public Block (Block parent, Flags flags, Parameters parameters,
                              Location start, Location end)
                {
                        if (parent != null)
                                parent.AddChild (this);
                        
                        this.Parent = parent;
-                       this.Implicit = implicit_block;
+                       this.flags = flags;
                        this.parameters = parameters;
                        this.StartLocation = start;
                        this.EndLocation = end;
                        this.loc = start;
                        this_id = id++;
                        statements = new ArrayList ();
+
+                       if (parent != null && Implicit) {
+                               if (parent.child_variable_names == null)
+                                       parent.child_variable_names = new Hashtable();
+                               // share with parent
+                               child_variable_names = parent.child_variable_names;
+                       }
+                               
+               }
+
+               public Block CreateSwitchBlock (Location start)
+               {
+                       Block new_block = new Block (this, start, start);
+                       new_block.switch_block = this;
+                       return new_block;
                }
 
                public int ID {
@@ -2649,37 +1224,103 @@ namespace Mono.CSharp {
                ///   otherwise.
                /// </returns>
                ///
-               public bool AddLabel (string name, LabeledStatement target)
+               public bool AddLabel (string name, LabeledStatement target, Location loc)
                {
+                       if (switch_block != null)
+                               return switch_block.AddLabel (name, target, loc);
+
+                       Block cur = this;
+                       while (cur != null) {
+                               if (cur.DoLookupLabel (name) != null) {
+                                       Report.Error (
+                                               140, loc, "The label '{0}' is a duplicate",
+                                               name);
+                                       return false;
+                               }
+
+                               if (!Implicit)
+                                       break;
+
+                               cur = cur.Parent;
+                       }
+
+                       while (cur != null) {
+                               if (cur.DoLookupLabel (name) != null) {
+                                       Report.Error (
+                                               158, loc,
+                                               "The label '{0}' shadows another label " +
+                                               "by the same name in a containing scope.",
+                                               name);
+                                       return false;
+                               }
+
+                               if (children != null) {
+                                       foreach (Block b in children) {
+                                               LabeledStatement s = b.DoLookupLabel (name);
+                                               if (s == null)
+                                                       continue;
+
+                                               Report.Error (
+                                                       158, s.Location,
+                                                       "The label '{0}' shadows another " +
+                                                       "label by the same name in a " +
+                                                       "containing scope.",
+                                                       name);
+                                               return false;
+                                       }
+                               }
+
+
+                               cur = cur.Parent;
+                       }
+
                        if (labels == null)
                                labels = new Hashtable ();
-                       if (labels.Contains (name))
-                               return false;
-                       
+
                        labels.Add (name, target);
                        return true;
                }
 
                public LabeledStatement LookupLabel (string name)
                {
-                       if (labels != null){
-                               if (labels.Contains (name))
-                                       return ((LabeledStatement) labels [name]);
+                       LabeledStatement s = DoLookupLabel (name);
+                       if (s != null)
+                               return s;
+
+                       if (children == null)
+                               return null;
+
+                       foreach (Block child in children) {
+                               if (!child.Implicit)
+                                       continue;
+
+                               s = child.LookupLabel (name);
+                               if (s != null)
+                                       return s;
                        }
 
-                       if (Parent != null)
-                               return Parent.LookupLabel (name);
+                       return null;
+               }
+
+               LabeledStatement DoLookupLabel (string name)
+               {
+                       if (switch_block != null)
+                               return switch_block.LookupLabel (name);
+
+                       if (labels != null)
+                               if (labels.Contains (name))
+                                       return ((LabeledStatement) labels [name]);
 
                        return null;
                }
 
-               VariableInfo this_variable = null;
+               LocalInfo this_variable = null;
 
                // <summary>
                //   Returns the "this" instance variable of this block.
                //   See AddThisVariable() for more information.
                // </summary>
-               public VariableInfo ThisVariable {
+               public LocalInfo ThisVariable {
                        get {
                                if (this_variable != null)
                                        return this_variable;
@@ -2706,25 +1347,6 @@ namespace Mono.CSharp {
                                child_variable_names.Add (name, true);
                }
 
-               // <summary>
-               //   Marks all variables from block @block and all its children as being
-               //   used in a child block.
-               // </summary>
-               public void AddChildVariableNames (Block block)
-               {
-                       if (block.Variables != null) {
-                               foreach (string name in block.Variables.Keys)
-                                       AddChildVariableName (name);
-                       }
-
-                       foreach (Block child in block.children) {
-                               if (child.Variables != null) {
-                                       foreach (string name in child.Variables.Keys)
-                                               AddChildVariableName (name);
-                               }
-                       }
-               }
-
                // <summary>
                //   Checks whether a variable name has already been used in a child block.
                // </summary>
@@ -2743,28 +1365,30 @@ namespace Mono.CSharp {
                //   analysis code to ensure that it's been fully initialized before control
                //   leaves the constructor.
                // </summary>
-               public VariableInfo AddThisVariable (TypeContainer tc, Location l)
+               public LocalInfo AddThisVariable (TypeContainer tc, Location l)
                {
                        if (this_variable != null)
                                return this_variable;
 
-                       this_variable = new VariableInfo (tc, ID, l);
-
                        if (variables == null)
                                variables = new Hashtable ();
+
+                       this_variable = new LocalInfo (tc, this, l);
+                       this_variable.Used = true;
+
                        variables.Add ("this", this_variable);
 
                        return this_variable;
                }
 
-               public VariableInfo AddVariable (Expression type, string name, Parameters pars, Location l)
+               public LocalInfo AddVariable (Expression type, string name, Parameters pars, Location l)
                {
                        if (variables == null)
                                variables = new Hashtable ();
 
-                       VariableInfo vi = GetVariableInfo (name);
+                       LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
-                               if (vi.Block != ID)
+                               if (vi.Block != this)
                                        Report.Error (136, l, "A local variable named `" + name + "' " +
                                                      "cannot be declared in this scope since it would " +
                                                      "give a different meaning to `" + name + "', which " +
@@ -2786,7 +1410,7 @@ namespace Mono.CSharp {
                        }
 
                        if (pars != null) {
-                               int idx = 0;
+                               int idx;
                                Parameter p = pars.GetParameterByName (name, out idx);
                                if (p != null) {
                                        Report.Error (136, l, "A local variable named `" + name + "' " +
@@ -2797,12 +1421,20 @@ namespace Mono.CSharp {
                                        return null;
                                }
                        }
-                       
-                       vi = new VariableInfo (type, name, ID, l);
+
+                       vi = new LocalInfo (type, name, this, l);
 
                        variables.Add (name, vi);
 
-                       if (variables_initialized)
+                       // Mark 'name' as "used by a child block" in every surrounding block
+                       Block cur = this;
+                       while (cur != null && cur.Implicit) 
+                               cur = cur.Parent;
+                       if (cur != null)
+                               for (Block par = cur.Parent; par != null; par = par.Parent)
+                                       par.AddChildVariableName (name);
+
+                       if ((flags & Flags.VariablesInitialized) != 0)
                                throw new Exception ();
 
                        // Console.WriteLine ("Adding {0} to {1}", name, ID);
@@ -2827,26 +1459,21 @@ namespace Mono.CSharp {
                        }
                }
 
-               public VariableInfo GetVariableInfo (string name)
+               public LocalInfo GetLocalInfo (string name)
                {
-                       if (variables != null) {
-                               object temp;
-                               temp = variables [name];
-
-                               if (temp != null){
-                                       return (VariableInfo) temp;
+                       for (Block b = this; b != null; b = b.Parent) {
+                               if (b.variables != null) {
+                                       LocalInfo ret = b.variables [name] as LocalInfo;
+                                       if (ret != null)
+                                               return ret;
                                }
                        }
-
-                       if (Parent != null)
-                               return Parent.GetVariableInfo (name);
-
                        return null;
                }
-               
+
                public Expression GetVariableType (string name)
                {
-                       VariableInfo vi = GetVariableInfo (name);
+                       LocalInfo vi = GetLocalInfo (name);
 
                        if (vi != null)
                                return vi.Type;
@@ -2856,17 +1483,13 @@ namespace Mono.CSharp {
 
                public Expression GetConstantExpression (string name)
                {
-                       if (constants != null) {
-                               object temp;
-                               temp = constants [name];
-                               
-                               if (temp != null)
-                                       return (Expression) temp;
+                       for (Block b = this; b != null; b = b.Parent) {
+                               if (b.constants != null) {
+                                       Expression ret = b.constants [name] as Expression;
+                                       if (ret != null)
+                                               return ret;
+                               }
                        }
-                       
-                       if (Parent != null)
-                               return Parent.GetConstantExpression (name);
-
                        return null;
                }
                
@@ -2882,22 +1505,13 @@ namespace Mono.CSharp {
                        return e != null;
                }
                
-               /// <summary>
-               ///   Use to fetch the statement associated with this label
-               /// </summary>
-               public Statement this [string name] {
-                       get {
-                               return (Statement) labels [name];
-                       }
-               }
-
                Parameters parameters = null;
                public Parameters Parameters {
                        get {
-                               if (Parent != null)
-                                       return Parent.Parameters;
-
-                               return parameters;
+                               Block b = this;
+                               while (b.Parent != null)
+                                       b = b.Parent;
+                               return b.parameters;
                        }
                }
 
@@ -2913,98 +1527,130 @@ namespace Mono.CSharp {
                public void AddStatement (Statement s)
                {
                        statements.Add (s);
-                       used = true;
+                       flags |= Flags.BlockUsed;
                }
 
                public bool Used {
                        get {
-                               return used;
+                               return (flags & Flags.BlockUsed) != 0;
                        }
                }
 
                public void Use ()
                {
-                       used = true;
+                       flags |= Flags.BlockUsed;
                }
 
-               bool variables_initialized = false;
-               int count_variables = 0, first_variable = 0;
-
-               void UpdateVariableInfo (EmitContext ec)
-               {
-                       DeclSpace ds = ec.DeclSpace;
+               public bool HasRet {
+                       get {
+                               return (flags & Flags.HasRet) != 0;
+                       }
+               }
 
-                       first_variable = 0;
+               public bool IsDestructor {
+                       get {
+                               return (flags & Flags.IsDestructor) != 0;
+                       }
+               }
 
-                       if (Parent != null)
-                               first_variable += Parent.CountVariables;
+               public void SetDestructor ()
+               {
+                       flags |= Flags.IsDestructor;
+               }
 
-                       count_variables = first_variable;
-                       if (variables != null) {
-                               foreach (VariableInfo vi in variables.Values) {
-                                       if (!vi.Resolve (ds)) {
-                                               vi.Number = -1;
-                                               continue;
-                                       }
+               VariableMap param_map, local_map;
 
-                                       vi.Number = ++count_variables;
+               public VariableMap ParameterMap {
+                       get {
+                               if ((flags & Flags.VariablesInitialized) == 0)
+                                       throw new Exception ();
 
-                                       if (vi.StructInfo != null)
-                                               count_variables += vi.StructInfo.Count;
-                               }
+                               return param_map;
                        }
-
-                       variables_initialized = true;
                }
 
-               //
-               // <returns>
-               //   The number of local variables in this block
-               // </returns>
-               public int CountVariables
-               {
+               public VariableMap LocalMap {
                        get {
-                               if (!variables_initialized)
+                               if ((flags & Flags.VariablesInitialized) == 0)
                                        throw new Exception ();
 
-                               return count_variables;
+                               return local_map;
                        }
                }
 
+               public bool LiftVariable (LocalInfo local_info)
+               {
+                       return false;
+               }
+               
                /// <summary>
                ///   Emits the variable declarations and labels.
                /// </summary>
                /// <remarks>
                ///   tc: is our typecontainer (to resolve type references)
                ///   ig: is the code generator:
-               ///   toplevel: the toplevel block.  This is used for checking 
-               ///             that no two labels with the same name are used.
                /// </remarks>
-               public void EmitMeta (EmitContext ec, Block toplevel)
+               public void EmitMeta (EmitContext ec, InternalParameters ip)
                {
-                       DeclSpace ds = ec.DeclSpace;
                        ILGenerator ig = ec.ig;
 
-                       if (!variables_initialized)
-                               UpdateVariableInfo (ec);
+                       //
+                       // Compute the VariableMap's.
+                       //
+                       // Unfortunately, we don't know the type when adding variables with
+                       // AddVariable(), so we need to compute this info here.
+                       //
+
+                       LocalInfo[] locals;
+                       if (variables != null) {
+                               foreach (LocalInfo li in variables.Values)
+                                       li.Resolve (ec.DeclSpace);
+
+                               locals = new LocalInfo [variables.Count];
+                               variables.Values.CopyTo (locals, 0);
+                       } else
+                               locals = new LocalInfo [0];
+
+                       if (Parent != null)
+                               local_map = new VariableMap (Parent.LocalMap, locals);
+                       else
+                               local_map = new VariableMap (locals);
+
+                       param_map = new VariableMap (ip);
+                       flags |= Flags.VariablesInitialized;
 
+                       bool old_check_state = ec.ConstantCheckState;
+                       ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
+                       bool remap_locals = ec.RemapToProxy;
+                               
                        //
                        // Process this block variables
                        //
                        if (variables != null){
-                               local_builders = new Hashtable ();
-                               
                                foreach (DictionaryEntry de in variables){
                                        string name = (string) de.Key;
-                                       VariableInfo vi = (VariableInfo) de.Value;
-
+                                       LocalInfo vi = (LocalInfo) de.Value;
+                                       
                                        if (vi.VariableType == null)
                                                continue;
 
-                                       vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+                                       Type variable_type = vi.VariableType;
 
-                                       if (CodeGen.SymbolWriter != null)
-                                               vi.LocalBuilder.SetLocalSymInfo (name);
+                                       if (variable_type.IsPointer){
+                                               //
+                                               // Am not really convinced that this test is required (Microsoft does it)
+                                               // but the fact is that you would not be able to use the pointer variable
+                                               // *anyways*
+                                               //
+                                               if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
+                                                                                  vi.Location))
+                                                       continue;
+                                       }
+
+                                       if (remap_locals)
+                                               vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
+                                       else
+                                               vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
 
                                        if (constants == null)
                                                continue;
@@ -3013,45 +1659,54 @@ namespace Mono.CSharp {
                                        if (cv == null)
                                                continue;
 
+                                       ec.CurrentBlock = this;
                                        Expression e = cv.Resolve (ec);
                                        if (e == null)
                                                continue;
 
-                                       if (!(e is Constant)){
+                                       Constant ce = e as Constant;
+                                       if (ce == null){
                                                Report.Error (133, vi.Location,
                                                              "The expression being assigned to `" +
                                                              name + "' must be constant (" + e + ")");
                                                continue;
                                        }
 
+                                       if (e.Type != variable_type){
+                                               e = Const.ChangeType (vi.Location, ce, variable_type);
+                                               if (e == null)
+                                                       continue;
+                                       }
+
                                        constants.Remove (name);
                                        constants.Add (name, e);
                                }
                        }
+                       ec.ConstantCheckState = old_check_state;
 
                        //
                        // Now, handle the children
                        //
                        if (children != null){
                                foreach (Block b in children)
-                                       b.EmitMeta (ec, toplevel);
+                                       b.EmitMeta (ec, ip);
                        }
                }
 
-               public void UsageWarning ()
+               void UsageWarning (FlowBranching.UsageVector vector)
                {
                        string name;
-                       
+
                        if (variables != null){
                                foreach (DictionaryEntry de in variables){
-                                       VariableInfo vi = (VariableInfo) de.Value;
+                                       LocalInfo vi = (LocalInfo) de.Value;
                                        
                                        if (vi.Used)
                                                continue;
                                        
                                        name = (string) de.Key;
-                                               
-                                       if (vi.Assigned){
+
+                                       if (vector.IsAssigned (vi.VariableInfo)){
                                                Report.Warning (
                                                        219, vi.Location, "The variable `" + name +
                                                        "' is assigned but its value is never used");
@@ -3063,64 +1718,69 @@ namespace Mono.CSharp {
                                        } 
                                }
                        }
-
-                       if (children != null)
-                               foreach (Block b in children)
-                                       b.UsageWarning ();
                }
 
-               bool has_ret = false;
-
                public override bool Resolve (EmitContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
                        bool ok = true;
 
+                       int errors = Report.Errors;
+
                        ec.CurrentBlock = this;
                        ec.StartFlowBranching (this);
 
-                       Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+                       Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
 
-                       if (!variables_initialized)
-                               UpdateVariableInfo (ec);
-
-                       ArrayList new_statements = new ArrayList ();
                        bool unreachable = false, warning_shown = false;
 
-                       foreach (Statement s in statements){
+                       int statement_count = statements.Count;
+                       for (int ix = 0; ix < statement_count; ix++){
+                               Statement s = (Statement) statements [ix];
+
                                if (unreachable && !(s is LabeledStatement)) {
-                                       if (!warning_shown && !(s is EmptyStatement)) {
+                                       if (s == EmptyStatement.Value)
+                                               s.loc = EndLocation;
+
+                                       if (!s.ResolveUnreachable (ec, !warning_shown))
+                                               ok = false;
+
+                                       if (s != EmptyStatement.Value)
                                                warning_shown = true;
-                                               Warning_DeadCodeFound (s.loc);
-                                       }
+                                       else
+                                               s.loc = Location.Null;
 
+                                       statements [ix] = EmptyStatement.Value;
                                        continue;
                                }
 
                                if (s.Resolve (ec) == false) {
                                        ok = false;
+                                       statements [ix] = EmptyStatement.Value;
                                        continue;
                                }
 
+                               num_statements = ix + 1;
+
                                if (s is LabeledStatement)
                                        unreachable = false;
                                else
-                                       unreachable = ! ec.CurrentBranching.IsReachable ();
-
-                               new_statements.Add (s);
+                                       unreachable = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;
                        }
 
-                       statements = new_statements;
+                       Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
+                                     ec.CurrentBranching, statement_count, num_statements);
 
-                       Report.Debug (1, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching);
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       FlowBranching.UsageVector vector = ec.DoEndFlowBranching ();
+
                        ec.CurrentBlock = prev_block;
 
                        // 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_variable != null) && (returns != FlowReturns.EXCEPTION) &&
-                           !this_variable.IsAssigned (ec, loc))
+                       if ((this_variable != null) &&
+                           (vector.Reachability.Throws != FlowBranching.FlowReturns.Always) &&
+                           !this_variable.IsThisAssigned (ec, loc))
                                ok = false;
 
                        if ((labels != null) && (RootContext.WarningLevel >= 2)) {
@@ -3130,30 +1790,89 @@ namespace Mono.CSharp {
                                                                "This label has not been referenced");
                        }
 
-                       if ((returns == FlowReturns.ALWAYS) ||
-                           (returns == FlowReturns.EXCEPTION) ||
-                           (returns == FlowReturns.UNREACHABLE))
-                               has_ret = true;
+                       Report.Debug (4, "RESOLVE BLOCK DONE #2", StartLocation, vector);
+
+                       if ((vector.Reachability.Returns == FlowBranching.FlowReturns.Always) ||
+                           (vector.Reachability.Throws == FlowBranching.FlowReturns.Always) ||
+                           (vector.Reachability.Reachable == FlowBranching.FlowReturns.Never))
+                               flags |= Flags.HasRet;
+
+                       if (ok && (errors == Report.Errors)) {
+                               if (RootContext.WarningLevel >= 3)
+                                       UsageWarning (vector);
+                       }
 
                        return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
+               {
+                       for (int ix = 0; ix < num_statements; ix++){
+                               Statement s = (Statement) statements [ix];
+
+                               // Check whether we are the last statement in a
+                               // top-level block.
+
+                               if ((Parent == null) && (ix+1 == num_statements))
+                                       ec.IsLastStatement = true;
+                               else
+                                       ec.IsLastStatement = false;
+
+                               s.Emit (ec);
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
 
                        ec.CurrentBlock = this;
 
-                       ec.Mark (StartLocation);
-                       foreach (Statement s in statements)
-                               s.Emit (ec);
-                       ec.Mark (EndLocation); 
-                       
+                       bool emit_debug_info = (CodeGen.SymbolWriter != null);
+                       bool is_lexical_block = !Implicit && (Parent != null);
+
+                       if (emit_debug_info) {
+                               if (is_lexical_block)
+                                       ec.ig.BeginScope ();
+
+                               if (variables != null) {
+                                       foreach (DictionaryEntry de in variables) {
+                                               string name = (string) de.Key;
+                                               LocalInfo vi = (LocalInfo) de.Value;
+
+                                               if (vi.LocalBuilder == null)
+                                                       continue;
+
+                                               vi.LocalBuilder.SetLocalSymInfo (name);
+                                       }
+                               }
+                       }
+
+                       ec.Mark (StartLocation, true);
+                       DoEmit (ec);
+                       ec.Mark (EndLocation, true); 
+
+                       if (emit_debug_info && is_lexical_block)
+                               ec.ig.EndScope ();
+
                        ec.CurrentBlock = prev_block;
-                       return has_ret;
                }
        }
 
+       //
+       // 
+       public class ToplevelBlock : Block {
+               public ToplevelBlock (Parameters parameters, Location start) :
+                       base (null, parameters, start, Location.Null)
+               {
+               }
+
+               public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
+                       base (null, flags, parameters, start, Location.Null)
+               {
+               }
+       }
+       
        public class SwitchLabel {
                Expression label;
                object converted;
@@ -3326,7 +2045,7 @@ namespace Mono.CSharp {
                        foreach (Type tt in allowed_types){
                                Expression e;
                                
-                               e = Expression.ImplicitUserConversion (ec, Expr, tt, loc);
+                               e = Convert.ImplicitUserConversion (ec, Expr, tt, loc);
                                if (e == null)
                                        continue;
 
@@ -3492,7 +2211,7 @@ namespace Mono.CSharp {
                        }
                        if (error)
                                return false;
-                       
+
                        return true;
                }
 
@@ -3553,6 +2272,8 @@ namespace Mono.CSharp {
                        public long nFirst;
                        public long nLast;
                        public ArrayList rgKeys = null;
+                       // how many items are in the bucket
+                       public int Size = 1;
                        public int Length
                        {
                                get { return (int) (nLast - nFirst + 1); }
@@ -3582,7 +2303,7 @@ namespace Mono.CSharp {
                /// <param name="ec"></param>
                /// <param name="val"></param>
                /// <returns></returns>
-               bool TableSwitchEmit (EmitContext ec, LocalBuilder val)
+               void TableSwitchEmit (EmitContext ec, LocalBuilder val)
                {
                        int cElements = Elements.Count;
                        object [] rgKeys = new object [cElements];
@@ -3592,7 +2313,7 @@ namespace Mono.CSharp {
                        // initialize the block list with one element per key
                        ArrayList rgKeyBlocks = new ArrayList ();
                        foreach (object key in rgKeys)
-                               rgKeyBlocks.Add (new KeyBlock (Convert.ToInt64 (key)));
+                               rgKeyBlocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));
 
                        KeyBlock kbCurr;
                        // iteratively merge the blocks while they are at least half full
@@ -3604,10 +2325,11 @@ namespace Mono.CSharp {
                                for (int ikb = 1; ikb < rgKeyBlocks.Count; ikb++)
                                {
                                        KeyBlock kb = (KeyBlock) rgKeyBlocks [ikb];
-                                       if ((kbCurr.Length + kb.Length) * 2 >=  KeyBlock.TotalLength (kbCurr, kb))
+                                       if ((kbCurr.Size + kb.Size) * 2 >=  KeyBlock.TotalLength (kbCurr, kb))
                                        {
                                                // merge blocks
                                                kbCurr.nLast = kb.nLast;
+                                               kbCurr.Size += kb.Size;
                                        }
                                        else
                                        {
@@ -3632,7 +2354,8 @@ namespace Mono.CSharp {
                                kbCurr = (KeyBlock) rgKeyBlocks [0];
                                foreach (object key in rgKeys)
                                {
-                                       bool fNextBlock = (key is UInt64) ? (ulong) key > (ulong) kbCurr.nLast : Convert.ToInt64 (key) > kbCurr.nLast;
+                                       bool fNextBlock = (key is UInt64) ? (ulong) key > (ulong) kbCurr.nLast :
+                                               System.Convert.ToInt64 (key) > kbCurr.nLast;
                                        if (fNextBlock)
                                                kbCurr = (KeyBlock) rgKeyBlocks [++iBlockCurr];
                                        kbCurr.rgKeys.Add (key);
@@ -3651,6 +2374,13 @@ namespace Mono.CSharp {
                        if (rgKeys.Length > 0)
                                typeKeys = rgKeys [0].GetType ();       // used for conversions
 
+                       Type compare_type;
+                       
+                       if (TypeManager.IsEnumType (SwitchType))
+                               compare_type = TypeManager.EnumToUnderlying (SwitchType);
+                       else
+                               compare_type = SwitchType;
+                       
                        for (int iBlock = rgKeyBlocks.Count - 1; iBlock >= 0; --iBlock)
                        {
                                KeyBlock kb = ((KeyBlock) rgKeyBlocks [iBlock]);
@@ -3669,24 +2399,24 @@ namespace Mono.CSharp {
                                {
                                        // TODO: if all the keys in the block are the same and there are
                                        //       no gaps/defaults then just use a range-check.
-                                       if (SwitchType == TypeManager.int64_type ||
-                                               SwitchType == TypeManager.uint64_type)
+                                       if (compare_type == TypeManager.int64_type ||
+                                               compare_type == TypeManager.uint64_type)
                                        {
                                                // TODO: optimize constant/I4 cases
 
                                                // check block range (could be > 2^31)
                                                ig.Emit (OpCodes.Ldloc, val);
-                                               EmitObjectInteger (ig, Convert.ChangeType (kb.nFirst, typeKeys));
+                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
                                                ig.Emit (OpCodes.Blt, lblDefault);
                                                ig.Emit (OpCodes.Ldloc, val);
-                                               EmitObjectInteger (ig, Convert.ChangeType (kb.nFirst, typeKeys));
+                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.nLast, typeKeys));
                                                ig.Emit (OpCodes.Bgt, lblDefault);
 
                                                // normalize range
                                                ig.Emit (OpCodes.Ldloc, val);
                                                if (kb.nFirst != 0)
                                                {
-                                                       EmitObjectInteger (ig, Convert.ChangeType (kb.nFirst, typeKeys));
+                                                       EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
                                                        ig.Emit (OpCodes.Sub);
                                                }
                                                ig.Emit (OpCodes.Conv_I4);      // assumes < 2^31 labels!
@@ -3715,7 +2445,7 @@ namespace Mono.CSharp {
                                        for (int iJump = 0; iJump < cJumps; iJump++)
                                        {
                                                object key = kb.rgKeys [iKey];
-                                               if (Convert.ToInt64 (key) == kb.nFirst + iJump)
+                                               if (System.Convert.ToInt64 (key) == kb.nFirst + iJump)
                                                {
                                                        SwitchLabel sl = (SwitchLabel) Elements [key];
                                                        rgLabels [iJump] = sl.ILLabel;
@@ -3742,7 +2472,6 @@ namespace Mono.CSharp {
 
                        // now emit the code for the sections
                        bool fFoundDefault = false;
-                       bool fAllReturn = true;
                        foreach (SwitchSection ss in Sections)
                        {
                                foreach (SwitchLabel sl in ss.Labels)
@@ -3755,18 +2484,14 @@ namespace Mono.CSharp {
                                                fFoundDefault = true;
                                        }
                                }
-                               bool returns = ss.Block.Emit (ec);
-                               fAllReturn &= returns;
+                               ss.Block.Emit (ec);
                                //ig.Emit (OpCodes.Br, lblEnd);
                        }
                        
                        if (!fFoundDefault) {
                                ig.MarkLabel (lblDefault);
-                               fAllReturn = false;
                        }
                        ig.MarkLabel (lblEnd);
-
-                       return fAllReturn;
                }
                //
                // This simple emit switch works, but does not take advantage of the
@@ -3774,7 +2499,7 @@ namespace Mono.CSharp {
                // TODO: remove non-string logic from here
                // TODO: binary search strings?
                //
-               bool SimpleSwitchEmit (EmitContext ec, LocalBuilder val)
+               void SimpleSwitchEmit (EmitContext ec, LocalBuilder val)
                {
                        ILGenerator ig = ec.ig;
                        Label end_of_switch = ig.DefineLabel ();
@@ -3783,37 +2508,33 @@ namespace Mono.CSharp {
                        bool default_found = false;
                        bool first_test = true;
                        bool pending_goto_end = false;
-                       bool all_return = true;
-                       bool is_string = false;
                        bool null_found;
+                       bool default_at_end = false;
                        
-                       //
-                       // Special processing for strings: we cant compare
-                       // against null.
-                       //
-                       if (SwitchType == TypeManager.string_type){
-                               ig.Emit (OpCodes.Ldloc, val);
-                               is_string = true;
-                               
-                               if (Elements.Contains (NullLiteral.Null)){
-                                       ig.Emit (OpCodes.Brfalse, null_target);
-                               } else
-                                       ig.Emit (OpCodes.Brfalse, default_target);
-
-                               ig.Emit (OpCodes.Ldloc, val);
-                               ig.Emit (OpCodes.Call, TypeManager.string_isinterneted_string);
-                               ig.Emit (OpCodes.Stloc, val);
-                       }
+                       ig.Emit (OpCodes.Ldloc, val);
                        
-                       foreach (SwitchSection ss in Sections){
+                       if (Elements.Contains (NullLiteral.Null)){
+                               ig.Emit (OpCodes.Brfalse, null_target);
+                       } else
+                               ig.Emit (OpCodes.Brfalse, default_target);
+                       
+                       ig.Emit (OpCodes.Ldloc, val);
+                       ig.Emit (OpCodes.Call, TypeManager.string_isinterneted_string);
+                       ig.Emit (OpCodes.Stloc, val);
+               
+                       int section_count = Sections.Count;
+                       for (int section = 0; section < section_count; section++){
+                               SwitchSection ss = (SwitchSection) Sections [section];
                                Label sec_begin = ig.DefineLabel ();
 
                                if (pending_goto_end)
                                        ig.Emit (OpCodes.Br, end_of_switch);
 
                                int label_count = ss.Labels.Count;
+                               bool mark_default = false;
                                null_found = false;
-                               foreach (SwitchLabel sl in ss.Labels){
+                               for (int label = 0; label < label_count; label++){
+                                       SwitchLabel sl = (SwitchLabel) ss.Labels [label];
                                        ig.MarkLabel (sl.ILLabel);
                                        
                                        if (!first_test){
@@ -3824,7 +2545,9 @@ namespace Mono.CSharp {
                                        // If we are the default target
                                        //
                                        if (sl.Label == null){
-                                               ig.MarkLabel (default_target);
+                                               if (label+1 == label_count)
+                                                       default_at_end = true;
+                                               mark_default = true;
                                                default_found = true;
                                        } else {
                                                object lit = sl.Converted;
@@ -3836,52 +2559,39 @@ namespace Mono.CSharp {
                                                        continue;
                                                                              
                                                }
-                                               if (is_string){
-                                                       StringConstant str = (StringConstant) lit;
-
-                                                       ig.Emit (OpCodes.Ldloc, val);
-                                                       ig.Emit (OpCodes.Ldstr, str.Value);
-                                                       if (label_count == 1)
+                                               StringConstant str = (StringConstant) lit;
+                                               
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               ig.Emit (OpCodes.Ldstr, str.Value);
+                                               if (label_count == 1)
+                                                       ig.Emit (OpCodes.Bne_Un, next_test);
+                                               else {
+                                                       if (label+1 == label_count)
                                                                ig.Emit (OpCodes.Bne_Un, next_test);
                                                        else
                                                                ig.Emit (OpCodes.Beq, sec_begin);
-                                               } else {
-                                                       ig.Emit (OpCodes.Ldloc, val);
-                                                       EmitObjectInteger (ig, lit);
-                                                       ig.Emit (OpCodes.Ceq);
-                                                       if (label_count == 1)
-                                                               ig.Emit (OpCodes.Brfalse, next_test);
-                                                       else
-                                                               ig.Emit (OpCodes.Brtrue, sec_begin);
                                                }
                                        }
                                }
-                               if (label_count != 1)
-                                       ig.Emit (OpCodes.Br, next_test);
-                               
                                if (null_found)
                                        ig.MarkLabel (null_target);
                                ig.MarkLabel (sec_begin);
                                foreach (SwitchLabel sl in ss.Labels)
                                        ig.MarkLabel (sl.ILLabelCode);
 
-                               bool returns = ss.Block.Emit (ec);
-                               if (returns)
-                                       pending_goto_end = false;
-                               else {
-                                       all_return = false;
-                                       pending_goto_end = true;
-                               }
+                               if (mark_default)
+                                       ig.MarkLabel (default_target);
+                               ss.Block.Emit (ec);
+                               pending_goto_end = !ss.Block.HasRet;
                                first_test = false;
                        }
-                       if (!default_found){
-                               ig.MarkLabel (default_target);
-                               all_return = false;
-                       }
                        ig.MarkLabel (next_test);
+                       if (default_found){
+                               if (!default_at_end)
+                                       ig.Emit (OpCodes.Br, default_target);
+                       } else 
+                               ig.MarkLabel (default_target);
                        ig.MarkLabel (end_of_switch);
-                       
-                       return all_return;
                }
 
                public override bool Resolve (EmitContext ec)
@@ -3906,12 +2616,14 @@ namespace Mono.CSharp {
                        ec.Switch = this;
                        ec.Switch.SwitchType = SwitchType;
 
-                       ec.StartFlowBranching (FlowBranchingType.SWITCH, loc);
+                       Report.Debug (1, "START OF SWITCH BLOCK", loc, ec.CurrentBranching);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
 
                        bool first = true;
                        foreach (SwitchSection ss in Sections){
                                if (!first)
-                                       ec.CurrentBranching.CreateSibling ();
+                                       ec.CurrentBranching.CreateSibling (
+                                               null, FlowBranching.SiblingType.SwitchSection);
                                else
                                        first = false;
 
@@ -3921,15 +2633,19 @@ namespace Mono.CSharp {
 
 
                        if (!got_default)
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (
+                                       null, FlowBranching.SiblingType.SwitchSection);
 
-                       ec.EndFlowBranching ();
+                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
                        ec.Switch = old_switch;
 
+                       Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching,
+                                     reachability);
+
                        return true;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        // Store variable for comparission purposes
                        LocalBuilder value = ec.ig.DeclareLocal (SwitchType);
@@ -3950,11 +2666,10 @@ namespace Mono.CSharp {
                        ec.Switch = this;
 
                        // Emit Code.
-                       bool all_return;
                        if (SwitchType == TypeManager.string_type)
-                               all_return = SimpleSwitchEmit (ec, value);
+                               SimpleSwitchEmit (ec, value);
                        else
-                               all_return = TableSwitchEmit (ec, value);
+                               TableSwitchEmit (ec, value);
 
                        // Restore context state. 
                        ig.MarkLabel (ec.LoopEnd);
@@ -3964,8 +2679,6 @@ namespace Mono.CSharp {
                        //
                        ec.LoopEnd = old_end;
                        ec.Switch = old_switch;
-                       
-                       return all_return;
                }
        }
 
@@ -3983,21 +2696,27 @@ namespace Mono.CSharp {
                public override bool Resolve (EmitContext ec)
                {
                        expr = expr.Resolve (ec);
-                       return Statement.Resolve (ec) && expr != null;
+                       if (expr == null)
+                               return false;
+
+                       if (expr.Type.IsValueType){
+                               Error (185, "lock statement requires the expression to be " +
+                                      " a reference type (type is: `{0}'",
+                                      TypeManager.CSharpName (expr.Type));
+                               return false;
+                       }
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
+                       bool ok = Statement.Resolve (ec);
+                       ec.EndFlowBranching ();
+
+                       return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        Type type = expr.Type;
-                       bool val;
                        
-                       if (type.IsValueType){
-                               Report.Error (185, loc, "lock statement requires the expression to be " +
-                                             " a reference type (type is: `" +
-                                             TypeManager.CSharpName (type) + "'");
-                               return false;
-                       }
-
                        ILGenerator ig = ec.ig;
                        LocalBuilder temp = ig.DeclareLocal (type);
                                
@@ -4007,12 +2726,9 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
 
                        // try
-                       Label end = ig.BeginExceptionBlock ();
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
+                       ig.BeginExceptionBlock ();
                        Label finish = ig.DefineLabel ();
-                       val = Statement.Emit (ec);
-                       ec.InTry = old_in_try;
+                       Statement.Emit (ec);
                        // ig.Emit (OpCodes.Leave, finish);
 
                        ig.MarkLabel (finish);
@@ -4022,8 +2738,6 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Ldloc, temp);
                        ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
                        ig.EndExceptionBlock ();
-                       
-                       return val;
                }
        }
 
@@ -4033,26 +2747,33 @@ namespace Mono.CSharp {
                public Unchecked (Block b)
                {
                        Block = b;
+                       b.Unchecked = true;
                }
 
                public override bool Resolve (EmitContext ec)
                {
-                       return Block.Resolve (ec);
+                       bool previous_state = ec.CheckState;
+                       bool previous_state_const = ec.ConstantCheckState;
+
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       bool ret = Block.Resolve (ec);
+                       ec.CheckState = previous_state;
+                       ec.ConstantCheckState = previous_state_const;
+
+                       return ret;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        bool previous_state = ec.CheckState;
                        bool previous_state_const = ec.ConstantCheckState;
-                       bool val;
                        
                        ec.CheckState = false;
                        ec.ConstantCheckState = false;
-                       val = Block.Emit (ec);
+                       Block.Emit (ec);
                        ec.CheckState = previous_state;
                        ec.ConstantCheckState = previous_state_const;
-
-                       return val;
                }
        }
 
@@ -4062,6 +2783,7 @@ namespace Mono.CSharp {
                public Checked (Block b)
                {
                        Block = b;
+                       b.Unchecked = false;
                }
 
                public override bool Resolve (EmitContext ec)
@@ -4078,19 +2800,16 @@ namespace Mono.CSharp {
                        return ret;
                }
 
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        bool previous_state = ec.CheckState;
                        bool previous_state_const = ec.ConstantCheckState;
-                       bool val;
                        
                        ec.CheckState = true;
                        ec.ConstantCheckState = true;
-                       val = Block.Emit (ec);
+                       Block.Emit (ec);
                        ec.CheckState = previous_state;
                        ec.ConstantCheckState = previous_state_const;
-
-                       return val;
                }
        }
 
@@ -4114,16 +2833,13 @@ namespace Mono.CSharp {
                        return val;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        bool previous_state = ec.InUnsafe;
-                       bool val;
                        
                        ec.InUnsafe = true;
-                       val = Block.Emit (ec);
+                       Block.Emit (ec);
                        ec.InUnsafe = previous_state;
-
-                       return val;
                }
        }
 
@@ -4136,10 +2852,11 @@ namespace Mono.CSharp {
                Statement statement;
                Type expr_type;
                FixedData[] data;
+               bool has_ret;
 
                struct FixedData {
                        public bool is_object;
-                       public VariableInfo vi;
+                       public LocalInfo vi;
                        public Expression expr;
                        public Expression converted;
                }                       
@@ -4154,10 +2871,20 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
+                       if (!ec.InUnsafe){
+                               Expression.UnsafeError (loc);
+                               return false;
+                       }
+                       
                        expr_type = ec.DeclSpace.ResolveType (type, false, loc);
                        if (expr_type == null)
                                return false;
 
+                       if (ec.RemapToProxy){
+                               Report.Error (-210, loc, "Fixed statement not allowed in iterators");
+                               return false;
+                       }
+                       
                        data = new FixedData [declarators.Count];
 
                        if (!expr_type.IsPointer){
@@ -4167,10 +2894,11 @@ namespace Mono.CSharp {
                        
                        int i = 0;
                        foreach (Pair p in declarators){
-                               VariableInfo vi = (VariableInfo) p.First;
+                               LocalInfo vi = (LocalInfo) p.First;
                                Expression e = (Expression) p.Second;
 
-                               vi.Number = -1;
+                               vi.VariableInfo = null;
+                               vi.ReadOnly = true;
 
                                //
                                // The rules for the possible declarators are pretty wise,
@@ -4183,6 +2911,11 @@ namespace Mono.CSharp {
                                // is present, so we need to test for this particular case.
                                //
 
+                               if (e is Cast){
+                                       Report.Error (254, loc, "Cast expression not allowed as right hand expression in fixed statement");
+                                       return false;
+                               }
+                               
                                //
                                // Case 1: & object.
                                //
@@ -4198,8 +2931,10 @@ namespace Mono.CSharp {
                                                        "fixed)");
                                                return false;
                                        }
-                                       
+
+                                       ec.InFixedInitializer = true;
                                        e = e.Resolve (ec);
+                                       ec.InFixedInitializer = false;
                                        if (e == null)
                                                return false;
 
@@ -4217,7 +2952,9 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
+                               ec.InFixedInitializer = true;
                                e = e.Resolve (ec);
+                               ec.InFixedInitializer = false;
                                if (e == null)
                                        return false;
 
@@ -4225,7 +2962,7 @@ namespace Mono.CSharp {
                                // Case 2: Array
                                //
                                if (e.Type.IsArray){
-                                       Type array_type = e.Type.GetElementType ();
+                                       Type array_type = TypeManager.GetElementType (e.Type);
                                        
                                        vi.MakePinned ();
                                        //
@@ -4240,7 +2977,7 @@ namespace Mono.CSharp {
                                        //
                                        ArrayPtr array_ptr = new ArrayPtr (e, loc);
                                        
-                                       Expression converted = Expression.ConvertImplicitRequired (
+                                       Expression converted = Convert.ImplicitConversionRequired (
                                                ec, array_ptr, vi.VariableType, loc);
                                        if (converted == null)
                                                return false;
@@ -4263,21 +3000,44 @@ namespace Mono.CSharp {
                                        data [i].converted = null;
                                        data [i].vi = vi;
                                        i++;
+                                       continue;
                                }
+
+                               //
+                               // For other cases, flag a `this is already fixed expression'
+                               //
+                               if (e is LocalVariableReference || e is ParameterReference ||
+                                   Convert.ImplicitConversionExists (ec, e, vi.VariableType)){
+                                   
+                                       Report.Error (245, loc, "right hand expression is already fixed, no need to use fixed statement ");
+                                       return false;
+                               }
+
+                               Report.Error (245, loc, "Fixed statement only allowed on strings, arrays or address-of expressions");
+                               return false;
+                       }
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
+
+                       if (!statement.Resolve (ec)) {
+                               ec.KillFlowBranching ();
+                               return false;
                        }
 
-                       return statement.Resolve (ec);
+                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+                       has_ret = reachability.IsUnreachable;
+
+                       return true;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
 
-                       bool is_ret = false;
                        LocalBuilder [] clear_list = new LocalBuilder [data.Length];
                        
                        for (int i = 0; i < data.Length; i++) {
-                               VariableInfo vi = data [i].vi;
+                               LocalInfo vi = data [i].vi;
 
                                //
                                // Case 1: & object.
@@ -4318,7 +3078,7 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Stloc, pinned_string);
 
                                        Expression sptr = new StringPtr (pinned_string, loc);
-                                       Expression converted = Expression.ConvertImplicitRequired (
+                                       Expression converted = Convert.ImplicitConversionRequired (
                                                ec, sptr, vi.VariableType, loc);
                                        
                                        if (converted == null)
@@ -4329,16 +3089,15 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       is_ret = statement.Emit (ec);
+                       statement.Emit (ec);
+
+                       if (has_ret)
+                               return;
 
-                       if (is_ret)
-                               return is_ret;
                        //
                        // Clear the pinned variable
                        //
                        for (int i = 0; i < data.Length; i++) {
-                               VariableInfo vi = data [i].vi;
-
                                if (data [i].is_object || data [i].expr.Type.IsArray) {
                                        ig.Emit (OpCodes.Ldc_I4_0);
                                        ig.Emit (OpCodes.Conv_U);
@@ -4348,8 +3107,6 @@ namespace Mono.CSharp {
                                        ig.Emit (OpCodes.Stloc, clear_list [i]);
                                }
                        }
-
-                       return is_ret;
                }
        }
        
@@ -4429,133 +3186,96 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
                        
-                       ec.StartFlowBranching (FlowBranchingType.EXCEPTION, Block.StartLocation);
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, Block.StartLocation);
 
                        Report.Debug (1, "START OF TRY BLOCK", Block.StartLocation);
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
-
                        if (!Block.Resolve (ec))
                                ok = false;
 
-                       ec.InTry = old_in_try;
-
                        FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
 
                        Report.Debug (1, "START OF CATCH BLOCKS", vector);
 
                        foreach (Catch c in Specific){
-                               ec.CurrentBranching.CreateSibling ();
+                               ec.CurrentBranching.CreateSibling (
+                                       c.Block, FlowBranching.SiblingType.Catch);
+
                                Report.Debug (1, "STARTED SIBLING FOR CATCH", ec.CurrentBranching);
 
                                if (c.Name != null) {
-                                       VariableInfo vi = c.Block.GetVariableInfo (c.Name);
+                                       LocalInfo vi = c.Block.GetLocalInfo (c.Name);
                                        if (vi == null)
                                                throw new Exception ();
 
-                                       vi.Number = -1;
+                                       vi.VariableInfo = null;
                                }
 
-                               bool old_in_catch = ec.InCatch;
-                               ec.InCatch = true;
-
                                if (!c.Resolve (ec))
                                        ok = false;
-
-                               ec.InCatch = old_in_catch;
-
-                               FlowBranching.UsageVector current = ec.CurrentBranching.CurrentUsageVector;
-
-                               if (!current.AlwaysReturns && !current.AlwaysBreaks)
-                                       vector.AndLocals (current);
-                               else
-                                       vector.Or (current);
                        }
 
                        Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
 
                        if (General != null){
-                               ec.CurrentBranching.CreateSibling ();
-                               Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
+                               ec.CurrentBranching.CreateSibling (
+                                       General.Block, FlowBranching.SiblingType.Catch);
 
-                               bool old_in_catch = ec.InCatch;
-                               ec.InCatch = true;
+                               Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
 
                                if (!General.Resolve (ec))
                                        ok = false;
-
-                               ec.InCatch = old_in_catch;
-
-                               FlowBranching.UsageVector current = ec.CurrentBranching.CurrentUsageVector;
-
-                               if (!current.AlwaysReturns && !current.AlwaysBreaks)
-                                       vector.AndLocals (current);
-                               else    
-                                       vector.Or (current);
                        }
 
                        Report.Debug (1, "END OF GENERAL CATCH BLOCKS", ec.CurrentBranching);
 
                        if (Fini != null) {
-                               ec.CurrentBranching.CreateSiblingForFinally ();
-                               Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
+                               if (ok)
+                                       ec.CurrentBranching.CreateSibling (
+                                               Fini, FlowBranching.SiblingType.Finally);
 
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
+                               Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
 
                                if (!Fini.Resolve (ec))
                                        ok = false;
-
-                               ec.InFinally = old_in_finally;
                        }
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
 
                        FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
 
-                       Report.Debug (1, "END OF FINALLY", ec.CurrentBranching, returns, vector, f_vector);
+                       Report.Debug (1, "END OF TRY", ec.CurrentBranching, reachability, vector, f_vector);
 
-                       if ((returns == FlowReturns.SOMETIMES) || (returns == FlowReturns.ALWAYS)) {
-                               ec.CurrentBranching.CheckOutParameters (f_vector.Parameters, loc);
+                       if (reachability.Returns != FlowBranching.FlowReturns.Always) {
+                               // Unfortunately, System.Reflection.Emit automatically emits a leave
+                               // to the end of the finally block.  This is a problem if `returns'
+                               // is true since we may jump to a point after the end of the method.
+                               // As a workaround, emit an explicit ret here.
+                               ec.NeedReturnLabel ();
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Or (vector);
-
-                       Report.Debug (1, "END OF TRY", ec.CurrentBranching);
-
                        return ok;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       Label end;
                        Label finish = ig.DefineLabel ();;
-                       bool returns;
 
-                       ec.TryCatchLevel++;
-                       end = ig.BeginExceptionBlock ();
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
-                       returns = Block.Emit (ec);
-                       ec.InTry = old_in_try;
+                       ig.BeginExceptionBlock ();
+                       Block.Emit (ec);
 
                        //
                        // System.Reflection.Emit provides this automatically:
                        // ig.Emit (OpCodes.Leave, finish);
 
-                       bool old_in_catch = ec.InCatch;
-                       ec.InCatch = true;
-                       DeclSpace ds = ec.DeclSpace;
-
                        foreach (Catch c in Specific){
-                               VariableInfo vi;
+                               LocalInfo vi;
                                
                                ig.BeginCatchBlock (c.CatchType);
 
                                if (c.Name != null){
-                                       vi = c.Block.GetVariableInfo (c.Name);
+                                       vi = c.Block.GetLocalInfo (c.Name);
                                        if (vi == null)
                                                throw new Exception ("Variable does not exist in this block");
 
@@ -4563,43 +3283,22 @@ namespace Mono.CSharp {
                                } else
                                        ig.Emit (OpCodes.Pop);
                                
-                               if (!c.Block.Emit (ec))
-                                       returns = false;
+                               c.Block.Emit (ec);
                        }
 
                        if (General != null){
                                ig.BeginCatchBlock (TypeManager.object_type);
                                ig.Emit (OpCodes.Pop);
-                               if (!General.Block.Emit (ec))
-                                       returns = false;
+                               General.Block.Emit (ec);
                        }
-                       ec.InCatch = old_in_catch;
 
                        ig.MarkLabel (finish);
                        if (Fini != null){
                                ig.BeginFinallyBlock ();
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
                                Fini.Emit (ec);
-                               ec.InFinally = old_in_finally;
                        }
                        
                        ig.EndExceptionBlock ();
-                       ec.TryCatchLevel--;
-
-                       if (!returns || ec.InTry || ec.InCatch)
-                               return returns;
-
-                       // Unfortunately, System.Reflection.Emit automatically emits a leave
-                       // to the end of the finally block.  This is a problem if `returns'
-                       // is true since we may jump to a point after the end of the method.
-                       // As a workaround, emit an explicit ret here.
-
-                       if (ec.ReturnType != null)
-                               ec.ig.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
-                       ec.ig.Emit (OpCodes.Ret);
-
-                       return true;
                }
        }
 
@@ -4646,7 +3345,7 @@ namespace Mono.CSharp {
                                        if (var == null)
                                                return false;
                                        
-                                       converted_vars [i] = Expression.ConvertImplicitRequired (
+                                       converted_vars [i] = Convert.ImplicitConversionRequired (
                                                ec, var, TypeManager.idisposable_type, loc);
 
                                        if (converted_vars [i] == null)
@@ -4679,7 +3378,7 @@ namespace Mono.CSharp {
                bool ResolveExpression (EmitContext ec)
                {
                        if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
-                               conv = Expression.ConvertImplicitRequired (
+                               conv = Convert.ImplicitConversionRequired (
                                        ec, expr, TypeManager.idisposable_type, loc);
 
                                if (conv == null)
@@ -4697,18 +3396,13 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        int i = 0;
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        for (i = 0; i < assign.Length; i++) {
                                assign [i].EmitStatement (ec);
                                
                                ig.BeginExceptionBlock ();
                        }
                        Statement.Emit (ec);
-                       ec.InTry = old_in_try;
 
-                       bool old_in_finally = ec.InFinally;
-                       ec.InFinally = true;
                        var_list.Reverse ();
                        foreach (DictionaryEntry e in var_list){
                                LocalVariableReference var = (LocalVariableReference) e.Key;
@@ -4716,15 +3410,42 @@ namespace Mono.CSharp {
                                i--;
                                
                                ig.BeginFinallyBlock ();
-                               
-                               var.Emit (ec);
-                               ig.Emit (OpCodes.Brfalse, skip);
-                               converted_vars [i].Emit (ec);
-                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+
+                               if (!var.Type.IsValueType) {
+                                       var.Emit (ec);
+                                       ig.Emit (OpCodes.Brfalse, skip);
+                                       converted_vars [i].Emit (ec);
+                                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               } else {
+                                       Expression ml = Expression.MemberLookup(ec, TypeManager.idisposable_type, var.Type, "Dispose", Mono.CSharp.Location.Null);
+
+                                       if (!(ml is MethodGroupExpr)) {
+                                               var.Emit (ec);
+                                               ig.Emit (OpCodes.Box, var.Type);
+                                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                                       } else {
+                                               MethodInfo mi = null;
+
+                                               foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
+                                                       if (mk.GetParameters().Length == 0) {
+                                                               mi = mk;
+                                                               break;
+                                                       }
+                                               }
+
+                                               if (mi == null) {
+                                                       Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+                                                       return false;
+                                               }
+
+                                               var.AddressOf (ec, AddressOp.Load);
+                                               ig.Emit (OpCodes.Call, mi);
+                                       }
+                               }
+
                                ig.MarkLabel (skip);
                                ig.EndExceptionBlock ();
                        }
-                       ec.InFinally = old_in_finally;
 
                        return false;
                }
@@ -4742,21 +3463,16 @@ namespace Mono.CSharp {
                                expr.Emit (ec);
                        ig.Emit (OpCodes.Stloc, local_copy);
 
-                       bool old_in_try = ec.InTry;
-                       ec.InTry = true;
                        ig.BeginExceptionBlock ();
                        Statement.Emit (ec);
-                       ec.InTry = old_in_try;
                        
                        Label skip = ig.DefineLabel ();
-                       bool old_in_finally = ec.InFinally;
                        ig.BeginFinallyBlock ();
                        ig.Emit (OpCodes.Ldloc, local_copy);
                        ig.Emit (OpCodes.Brfalse, skip);
                        ig.Emit (OpCodes.Ldloc, local_copy);
                        ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                        ig.MarkLabel (skip);
-                       ec.InFinally = old_in_finally;
                        ig.EndExceptionBlock ();
 
                        return false;
@@ -4782,19 +3498,36 @@ namespace Mono.CSharp {
 
                                if (!ResolveExpression (ec))
                                        return false;
-                       }                       
+                       }
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
 
-                       return Statement.Resolve (ec);
+                       bool ok = Statement.Resolve (ec);
+
+                       if (!ok) {
+                               ec.KillFlowBranching ();
+                               return false;
+                       }
+                                       
+                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+
+                       if (reachability.Returns != FlowBranching.FlowReturns.Always) {
+                               // Unfortunately, System.Reflection.Emit automatically emits a leave
+                               // to the end of the finally block.  This is a problem if `returns'
+                               // is true since we may jump to a point after the end of the method.
+                               // As a workaround, emit an explicit ret here.
+                               ec.NeedReturnLabel ();
+                       }
+
+                       return true;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
                        if (expression_or_block is DictionaryEntry)
-                               return EmitLocalVariableDecls (ec);
+                               EmitLocalVariableDecls (ec);
                        else if (expression_or_block is Expression)
-                               return EmitExpression (ec);
-
-                       return false;
+                               EmitExpression (ec);
                }
        }
 
@@ -4803,7 +3536,7 @@ namespace Mono.CSharp {
        /// </summary>
        public class Foreach : Statement {
                Expression type;
-               LocalVariableReference variable;
+               Expression variable;
                Expression expr;
                Statement statement;
                ForeachHelperMethods hm;
@@ -4846,7 +3579,7 @@ namespace Mono.CSharp {
 
                        if (expr.Type.IsArray) {
                                array_type = expr.Type;
-                               element_type = array_type.GetElementType ();
+                               element_type = TypeManager.GetElementType (array_type);
 
                                empty = new EmptyExpression (element_type);
                        } else {
@@ -4854,7 +3587,7 @@ namespace Mono.CSharp {
                                if (hm == null){
                                        error1579 (expr.Type);
                                        return false;
-                               }
+                               }                       
 
                                array_type = expr.Type;
                                element_type = hm.element_type;
@@ -4862,7 +3595,9 @@ namespace Mono.CSharp {
                                empty = new EmptyExpression (hm.element_type);
                        }
 
-                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       bool ok = true;
+
+                       ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                        ec.CurrentBranching.CreateSibling ();
 
                        //
@@ -4873,19 +3608,27 @@ namespace Mono.CSharp {
                        // Although it is not as important in this case, as the type
                        // will not likely be object (what the enumerator will return).
                        //
-                       conv = Expression.ConvertExplicit (ec, empty, var_type, loc);
+                       conv = Convert.ExplicitConversion (ec, empty, var_type, loc);
                        if (conv == null)
-                               return false;
+                               ok = false;
 
-                       if (variable.ResolveLValue (ec, empty) == null)
-                               return false;
+                       variable = variable.ResolveLValue (ec, empty);
+                       if (variable == null)
+                               ok = false;
+
+                       bool disposable = (hm != null) && hm.is_disposable;
+                       if (disposable)
+                               ec.StartFlowBranching (FlowBranching.BranchingType.Exception, loc);
 
                        if (!statement.Resolve (ec))
-                               return false;
+                               ok = false;
 
-                       FlowReturns returns = ec.EndFlowBranching ();
+                       if (disposable)
+                               ec.EndFlowBranching ();
 
-                       return true;
+                       ec.EndFlowBranching ();
+
+                       return ok;
                }
                
                //
@@ -4920,16 +3663,16 @@ namespace Mono.CSharp {
                //
                static MethodInfo FetchMethodGetCurrent (Type t)
                {
-                       MemberList move_next_list;
-                       
-                       move_next_list = TypeContainer.FindMembers (
+                       MemberList get_current_list;
+
+                       get_current_list = TypeContainer.FindMembers (
                                t, MemberTypes.Method,
                                BindingFlags.Public | BindingFlags.Instance,
                                Type.FilterName, "get_Current");
-                       if (move_next_list.Count == 0)
+                       if (get_current_list.Count == 0)
                                return null;
 
-                       foreach (MemberInfo m in move_next_list){
+                       foreach (MemberInfo m in get_current_list){
                                MethodInfo mi = (MethodInfo) m;
                                Type [] args;
 
@@ -5012,36 +3755,69 @@ namespace Mono.CSharp {
                                        return false;
                        }
 
+                       if ((mi.ReturnType == TypeManager.ienumerator_type) && (declaring == TypeManager.string_type))
+                               //
+                               // Apply the same optimization as MS: skip the GetEnumerator
+                               // returning an IEnumerator, and use the one returning a 
+                               // CharEnumerator instead. This allows us to avoid the 
+                               // try-finally block and the boxing.
+                               //
+                               return false;
+
                        //
                        // Ok, we can access it, now make sure that we can do something
                        // with this `GetEnumerator'
                        //
-
-                       if (mi.ReturnType == TypeManager.ienumerator_type ||
-                           TypeManager.ienumerator_type.IsAssignableFrom (mi.ReturnType) ||
-                           (!RootContext.StdLib && TypeManager.ImplementsInterface (mi.ReturnType, TypeManager.ienumerator_type))) {
-                               hm.move_next = TypeManager.bool_movenext_void;
-                               hm.get_current = TypeManager.object_getcurrent_void;
-                               return true;
-                       }
-
-                       //
-                       // Ok, so they dont return an IEnumerable, we will have to
-                       // find if they support the GetEnumerator pattern.
-                       //
+                       
                        Type return_type = mi.ReturnType;
+                       if (mi.ReturnType == TypeManager.ienumerator_type ||
+                           TypeManager.ienumerator_type.IsAssignableFrom (return_type) ||
+                           (!RootContext.StdLib && TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type))) {
+                               
+                               //
+                               // If it is not an interface, lets try to find the methods ourselves.
+                               // For example, if we have:
+                               // public class Foo : IEnumerator { public bool MoveNext () {} public int Current { get {}}}
+                               // We can avoid the iface call. This is a runtime perf boost.
+                               // even bigger if we have a ValueType, because we avoid the cost
+                               // of boxing.
+                               //
+                               // We have to make sure that both methods exist for us to take
+                               // this path. If one of the methods does not exist, we will just
+                               // use the interface. Sadly, this complex if statement is the only
+                               // way I could do this without a goto
+                               //
+                               
+                               if (return_type.IsInterface ||
+                                   (hm.move_next = FetchMethodMoveNext (return_type)) == null ||
+                                   (hm.get_current = FetchMethodGetCurrent (return_type)) == null) {
+                                       
+                                       hm.move_next = TypeManager.bool_movenext_void;
+                                       hm.get_current = TypeManager.object_getcurrent_void;
+                                       return true;    
+                               }
 
-                       hm.move_next = FetchMethodMoveNext (return_type);
-                       if (hm.move_next == null)
-                               return false;
-                       hm.get_current = FetchMethodGetCurrent (return_type);
-                       if (hm.get_current == null)
-                               return false;
+                       } else {
 
+                               //
+                               // Ok, so they dont return an IEnumerable, we will have to
+                               // find if they support the GetEnumerator pattern.
+                               //
+                               
+                               hm.move_next = FetchMethodMoveNext (return_type);
+                               if (hm.move_next == null)
+                                       return false;
+                               
+                               hm.get_current = FetchMethodGetCurrent (return_type);
+                               if (hm.get_current == null)
+                                       return false;
+                       }
+                       
                        hm.element_type = hm.get_current.ReturnType;
                        hm.enumerator_type = return_type;
-                       hm.is_disposable = TypeManager.ImplementsInterface (
-                               hm.enumerator_type, TypeManager.idisposable_type);
+                       hm.is_disposable = !hm.enumerator_type.IsSealed ||
+                               TypeManager.ImplementsInterface (
+                                       hm.enumerator_type, TypeManager.idisposable_type);
 
                        return true;
                }
@@ -5071,7 +3847,7 @@ namespace Mono.CSharp {
                        
                        mi = TypeContainer.FindMembers (t, MemberTypes.Method,
                                                        BindingFlags.Public | BindingFlags.NonPublic |
-                                                       BindingFlags.Instance,
+                                                       BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                                        FilterEnumerator, hm);
 
                        if (mi.Count == 0)
@@ -5089,8 +3865,11 @@ namespace Mono.CSharp {
                {
                        ForeachHelperMethods hm = new ForeachHelperMethods (ec);
 
-                       if (TryType (t, hm))
-                               return hm;
+                       for (Type tt = t; tt != null && tt != TypeManager.object_type;){
+                               if (TryType (tt, hm))
+                                       return hm;
+                               tt = tt.BaseType;
+                       }
 
                        //
                        // Now try to find the method in the interfaces
@@ -5125,14 +3904,10 @@ namespace Mono.CSharp {
                bool EmitCollectionForeach (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       LocalBuilder enumerator, disposable;
+                       VariableStorage enumerator;
 
-                       enumerator = ig.DeclareLocal (hm.enumerator_type);
-                       if (hm.is_disposable)
-                               disposable = ig.DeclareLocal (TypeManager.idisposable_type);
-                       else
-                               disposable = null;
-                       
+                       enumerator = new VariableStorage (ec, hm.enumerator_type);
+                       enumerator.EmitThis ();
                        //
                        // Instantiate the enumerator
                        //
@@ -5140,42 +3915,52 @@ namespace Mono.CSharp {
                                if (expr is IMemoryLocation){
                                        IMemoryLocation ml = (IMemoryLocation) expr;
 
-                                       ml.AddressOf (ec, AddressOp.Load);
+                                       Expression ml1 = Expression.MemberLookup(ec, TypeManager.ienumerator_type, expr.Type, "GetEnumerator", Mono.CSharp.Location.Null);
+
+                                       if (!(ml1 is MethodGroupExpr)) {
+                                               expr.Emit(ec);
+                                               ec.ig.Emit(OpCodes.Box, expr.Type);
+                                       } else {
+                                               ml.AddressOf (ec, AddressOp.Load);
+                                       }
                                } else
                                        throw new Exception ("Expr " + expr + " of type " + expr.Type +
                                                             " does not implement IMemoryLocation");
-                               ig.Emit (OpCodes.Call, hm.get_enumerator);
+                               ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
                        } else {
                                expr.Emit (ec);
                                ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
                        }
-                       ig.Emit (OpCodes.Stloc, enumerator);
+                       enumerator.EmitStore ();
 
                        //
                        // Protect the code in a try/finalize block, so that
                        // if the beast implement IDisposable, we get rid of it
                        //
-                       Label l;
-                       bool old_in_try = ec.InTry;
-
-                       if (hm.is_disposable) {
-                               l = ig.BeginExceptionBlock ();
-                               ec.InTry = true;
-                       }
+                       if (hm.is_disposable)
+                               ig.BeginExceptionBlock ();
                        
                        Label end_try = ig.DefineLabel ();
                        
                        ig.MarkLabel (ec.LoopBegin);
-                       ig.Emit (OpCodes.Ldloc, enumerator);
-                       ig.Emit (OpCodes.Callvirt, hm.move_next);
+                       
+                       enumerator.EmitCall (hm.move_next);
+                       
                        ig.Emit (OpCodes.Brfalse, end_try);
-                       ig.Emit (OpCodes.Ldloc, enumerator);
-                       ig.Emit (OpCodes.Callvirt, hm.get_current);
-                       variable.EmitAssign (ec, conv);
+                       if (ec.InIterator)
+                               ec.EmitThis ();
+                       
+                       enumerator.EmitCall (hm.get_current);
+
+                       if (ec.InIterator){
+                               conv.Emit (ec);
+                               ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                       } else 
+                               ((IAssignMethod)variable).EmitAssign (ec, conv);
+                               
                        statement.Emit (ec);
                        ig.Emit (OpCodes.Br, ec.LoopBegin);
                        ig.MarkLabel (end_try);
-                       ec.InTry = old_in_try;
                        
                        // The runtime provides this for us.
                        // ig.Emit (OpCodes.Leave, end);
@@ -5184,20 +3969,20 @@ namespace Mono.CSharp {
                        // Now the finally block
                        //
                        if (hm.is_disposable) {
-                               Label end_finally = ig.DefineLabel ();
-                               bool old_in_finally = ec.InFinally;
-                               ec.InFinally = true;
+                               Label call_dispose = ig.DefineLabel ();
                                ig.BeginFinallyBlock ();
-                       
-                               ig.Emit (OpCodes.Ldloc, enumerator);
+                               
+                               enumerator.EmitThis ();
+                               enumerator.EmitLoad ();
                                ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                               ig.Emit (OpCodes.Stloc, disposable);
-                               ig.Emit (OpCodes.Ldloc, disposable);
-                               ig.Emit (OpCodes.Brfalse, end_finally);
-                               ig.Emit (OpCodes.Ldloc, disposable);
+                               ig.Emit (OpCodes.Dup);
+                               ig.Emit (OpCodes.Brtrue_S, call_dispose);
+                               ig.Emit (OpCodes.Pop);
+                               ig.Emit (OpCodes.Endfinally);
+                               
+                               ig.MarkLabel (call_dispose);
                                ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               ig.MarkLabel (end_finally);
-                               ec.InFinally = old_in_finally;
+                               
 
                                // The runtime generates this anyways.
                                // ig.Emit (OpCodes.Endfinally);
@@ -5218,78 +4003,106 @@ namespace Mono.CSharp {
                        int rank = array_type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
 
-                       LocalBuilder copy = ig.DeclareLocal (array_type);
+                       VariableStorage copy = new VariableStorage (ec, array_type);
                        
                        //
                        // Make our copy of the array
                        //
+                       copy.EmitThis ();
                        expr.Emit (ec);
-                       ig.Emit (OpCodes.Stloc, copy);
+                       copy.EmitStore ();
                        
                        if (rank == 1){
-                               LocalBuilder counter = ig.DeclareLocal (TypeManager.int32_type);
+                               VariableStorage counter = new VariableStorage (ec,TypeManager.int32_type);
 
                                Label loop, test;
-                               
+
+                               counter.EmitThis ();
                                ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Stloc, counter);
+                               counter.EmitStore ();
                                test = ig.DefineLabel ();
                                ig.Emit (OpCodes.Br, test);
 
                                loop = ig.DefineLabel ();
                                ig.MarkLabel (loop);
 
-                               ig.Emit (OpCodes.Ldloc, copy);
-                               ig.Emit (OpCodes.Ldloc, counter);
-                               ArrayAccess.EmitLoadOpcode (ig, var_type);
+                               if (ec.InIterator)
+                                       ec.EmitThis ();
+                               
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
 
-                               variable.EmitAssign (ec, conv);
+                               //
+                               // Load the value, we load the value using the underlying type,
+                               // then we use the variable.EmitAssign to load using the proper cast.
+                               //
+                               ArrayAccess.EmitLoadOpcode (ig, element_type);
+                               if (ec.InIterator){
+                                       conv.Emit (ec);
+                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                               } else 
+                                       ((IAssignMethod)variable).EmitAssign (ec, conv);
 
                                statement.Emit (ec);
 
                                ig.MarkLabel (ec.LoopBegin);
-                               ig.Emit (OpCodes.Ldloc, counter);
+                               counter.EmitThis ();
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
                                ig.Emit (OpCodes.Ldc_I4_1);
                                ig.Emit (OpCodes.Add);
-                               ig.Emit (OpCodes.Stloc, counter);
+                               counter.EmitStore ();
 
                                ig.MarkLabel (test);
-                               ig.Emit (OpCodes.Ldloc, counter);
-                               ig.Emit (OpCodes.Ldloc, copy);
+                               counter.EmitThis ();
+                               counter.EmitLoad ();
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
                                ig.Emit (OpCodes.Ldlen);
                                ig.Emit (OpCodes.Conv_I4);
                                ig.Emit (OpCodes.Blt, loop);
                        } else {
-                               LocalBuilder [] dim_len   = new LocalBuilder [rank];
-                               LocalBuilder [] dim_count = new LocalBuilder [rank];
+                               VariableStorage [] dim_len   = new VariableStorage [rank];
+                               VariableStorage [] dim_count = new VariableStorage [rank];
                                Label [] loop = new Label [rank];
                                Label [] test = new Label [rank];
                                int dim;
                                
                                for (dim = 0; dim < rank; dim++){
-                                       dim_len [dim] = ig.DeclareLocal (TypeManager.int32_type);
-                                       dim_count [dim] = ig.DeclareLocal (TypeManager.int32_type);
+                                       dim_len [dim] = new VariableStorage (ec, TypeManager.int32_type);
+                                       dim_count [dim] = new VariableStorage (ec, TypeManager.int32_type);
                                        test [dim] = ig.DefineLabel ();
                                        loop [dim] = ig.DefineLabel ();
                                }
                                        
                                for (dim = 0; dim < rank; dim++){
-                                       ig.Emit (OpCodes.Ldloc, copy);
+                                       dim_len [dim].EmitThis ();
+                                       copy.EmitThis ();
+                                       copy.EmitLoad ();
                                        IntLiteral.EmitInt (ig, dim);
                                        ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
-                                       ig.Emit (OpCodes.Stloc, dim_len [dim]);
+                                       dim_len [dim].EmitStore ();
+                                       
                                }
 
                                for (dim = 0; dim < rank; dim++){
+                                       dim_count [dim].EmitThis ();
                                        ig.Emit (OpCodes.Ldc_I4_0);
-                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+                                       dim_count [dim].EmitStore ();
                                        ig.Emit (OpCodes.Br, test [dim]);
                                        ig.MarkLabel (loop [dim]);
                                }
 
-                               ig.Emit (OpCodes.Ldloc, copy);
-                               for (dim = 0; dim < rank; dim++)
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                               if (ec.InIterator)
+                                       ec.EmitThis ();
+                               copy.EmitThis ();
+                               copy.EmitLoad ();
+                               for (dim = 0; dim < rank; dim++){
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
+                               }
 
                                //
                                // FIXME: Maybe we can cache the computation of `get'?
@@ -5300,24 +4113,32 @@ namespace Mono.CSharp {
                                for (int i = 0; i < rank; i++)
                                        args [i] = TypeManager.int32_type;
 
-                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ModuleBuilder mb = CodeGen.Module.Builder;
                                get = mb.GetArrayMethod (
                                        array_type, "Get",
                                        CallingConventions.HasThis| CallingConventions.Standard,
                                        var_type, args);
                                ig.Emit (OpCodes.Call, get);
-                               variable.EmitAssign (ec, conv);
+                               if (ec.InIterator){
+                                       conv.Emit (ec);
+                                       ig.Emit (OpCodes.Stfld, ((FieldExpr) variable).FieldInfo);
+                               } else 
+                                       ((IAssignMethod)variable).EmitAssign (ec, conv);
                                statement.Emit (ec);
                                ig.MarkLabel (ec.LoopBegin);
                                for (dim = rank - 1; dim >= 0; dim--){
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
                                        ig.Emit (OpCodes.Ldc_I4_1);
                                        ig.Emit (OpCodes.Add);
-                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+                                       dim_count [dim].EmitStore ();
 
                                        ig.MarkLabel (test [dim]);
-                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
-                                       ig.Emit (OpCodes.Ldloc, dim_len [dim]);
+                                       dim_count [dim].EmitThis ();
+                                       dim_count [dim].EmitLoad ();
+                                       dim_len [dim].EmitThis ();
+                                       dim_len [dim].EmitLoad ();
                                        ig.Emit (OpCodes.Blt, loop [dim]);
                                }
                        }
@@ -5326,31 +4147,21 @@ namespace Mono.CSharp {
                        return false;
                }
                
-               protected override bool DoEmit (EmitContext ec)
+               protected override void DoEmit (EmitContext ec)
                {
-                       bool ret_val;
-                       
                        ILGenerator ig = ec.ig;
                        
                        Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
-                       bool old_inloop = ec.InLoop;
-                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
                        ec.LoopBegin = ig.DefineLabel ();
                        ec.LoopEnd = ig.DefineLabel ();
-                       ec.InLoop = true;
-                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
                        
                        if (hm != null)
-                               ret_val = EmitCollectionForeach (ec);
+                               EmitCollectionForeach (ec);
                        else
-                               ret_val = EmitArrayForeach (ec);
+                               EmitArrayForeach (ec);
                        
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
-                       ec.InLoop = old_inloop;
-                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
-
-                       return ret_val;
                }
        }
 }