CS1526 error recovery
[mono.git] / mcs / mcs / statement.cs
index 75b615f019790d7682465c9073101ba85052f6ef..bb4a8007f7a1b358bf618457d993b7dae3669d38 100644 (file)
@@ -27,7 +27,7 @@ namespace Mono.CSharp {
                ///   Resolves the statement, true means that all sub-statements
                ///   did resolve ok.
                //  </summary>
-               public virtual bool Resolve (EmitContext ec)
+               public virtual bool Resolve (BlockContext ec)
                {
                        return true;
                }
@@ -36,7 +36,7 @@ namespace Mono.CSharp {
                ///   We already know that the statement is unreachable, but we still
                ///   need to resolve it to catch errors.
                /// </summary>
-               public virtual bool ResolveUnreachable (EmitContext ec, bool warn)
+               public virtual bool ResolveUnreachable (BlockContext ec, bool warn)
                {
                        //
                        // This conflicts with csc's way of doing this, but IMHO it's
@@ -48,7 +48,7 @@ namespace Mono.CSharp {
                        //
 
                        if (warn)
-                               Report.Warning (162, 2, loc, "Unreachable code detected");
+                               ec.Report.Warning (162, 2, loc, "Unreachable code detected");
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        bool ok = Resolve (ec);
@@ -62,25 +62,6 @@ namespace Mono.CSharp {
                /// </summary>
                protected abstract void DoEmit (EmitContext ec);
 
-               /// <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 void Error (int error, string s)
-               {
-                       if (!loc.IsNull)
-                               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);
@@ -100,9 +81,9 @@ namespace Mono.CSharp {
                        return s;
                }
 
-               public virtual Expression CreateExpressionTree (EmitContext ec)
+               public virtual Expression CreateExpressionTree (ResolveContext ec)
                {
-                       Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
+                       ec.Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree");
                        return null;
                }
 
@@ -116,82 +97,18 @@ namespace Mono.CSharp {
                public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey);
        }
 
-       //
-       // This class is used during the Statement.Clone operation
-       // to remap objects that have been cloned.
-       //
-       // Since blocks are cloned by Block.Clone, we need a way for
-       // expressions that must reference the block to be cloned
-       // pointing to the new cloned block.
-       //
-       public class CloneContext {
-               Hashtable block_map = new Hashtable ();
-               Hashtable variable_map;
-               
-               public void AddBlockMap (Block from, Block to)
-               {
-                       if (block_map.Contains (from))
-                               return;
-                       block_map [from] = to;
-               }
-               
-               public Block LookupBlock (Block from)
-               {
-                       Block result = (Block) block_map [from];
-
-                       if (result == null){
-                               result = (Block) from.Clone (this);
-                               block_map [from] = result;
-                       }
-
-                       return result;
-               }
-
-               ///
-               /// Remaps block to cloned copy if one exists.
-               ///
-               public Block RemapBlockCopy (Block from)
-               {
-                       Block mapped_to = (Block)block_map[from];
-                       if (mapped_to == null)
-                               return from;
-
-                       return mapped_to;
-               }
-
-               public void AddVariableMap (LocalInfo from, LocalInfo to)
-               {
-                       if (variable_map == null)
-                               variable_map = new Hashtable ();
-                       
-                       if (variable_map.Contains (from))
-                               return;
-                       variable_map [from] = to;
-               }
-               
-               public LocalInfo LookupVariable (LocalInfo from)
-               {
-                       LocalInfo result = (LocalInfo) variable_map [from];
-
-                       if (result == null)
-                               throw new Exception ("LookupVariable: looking up a variable that has not been registered yet");
-
-                       return result;
-               }
-       }
-       
        public sealed class EmptyStatement : Statement {
                
                private EmptyStatement () {}
                
                public static readonly EmptyStatement Value = new EmptyStatement ();
-               
-               public override bool Resolve (EmitContext ec)
+
+               public override bool Resolve (BlockContext ec)
                {
                        return true;
                }
 
-               public override bool ResolveUnreachable (EmitContext ec, bool warn)
+               public override bool ResolveUnreachable (BlockContext ec, bool warn)
                {
                        return true;
                }
@@ -216,20 +133,18 @@ namespace Mono.CSharp {
                public Statement FalseStatement;
 
                bool is_true_ret;
-               
-               public If (Expression expr, Statement true_statement, Location l)
+
+               public If (Expression bool_expr, Statement true_statement, Location l)
+                       : this (bool_expr, true_statement, null, l)
                {
-                       this.expr = expr;
-                       TrueStatement = true_statement;
-                       loc = l;
                }
 
-               public If (Expression expr,
+               public If (Expression bool_expr,
                           Statement true_statement,
                           Statement false_statement,
                           Location l)
                {
-                       this.expr = expr;
+                       this.expr = bool_expr;
                        TrueStatement = true_statement;
                        FalseStatement = false_statement;
                        loc = l;
@@ -243,50 +158,44 @@ namespace Mono.CSharp {
                                FalseStatement.MutateHoistedGenericType (storey);
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
                        Report.Debug (1, "START IF BLOCK", loc);
 
-                       expr = Expression.ResolveBoolean (ec, expr, loc);
-                       if (expr == null){
+                       expr = expr.Resolve (ec);
+                       if (expr == null) {
                                ok = false;
-                               goto skip;
-                       }
-
-                       Assign ass = expr as Assign;
-                       if (ass != null && ass.Source is Constant) {
-                               Report.Warning (665, 3, loc, "Assignment in conditional expression is always constant; did you mean to use == instead of = ?");
-                       }
+                       } else {
+                               //
+                               // Dead code elimination
+                               //
+                               if (expr is Constant) {
+                                       bool take = !((Constant) expr).IsDefaultValue;
 
-                       //
-                       // Dead code elimination
-                       //
-                       if (expr is Constant){
-                               bool take = !((Constant) expr).IsDefaultValue;
+                                       if (take) {
+                                               if (!TrueStatement.Resolve (ec))
+                                                       return false;
 
-                               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.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;
+                                       }
 
-                                       if ((FalseStatement != null) &&
-                                           !FalseStatement.Resolve (ec))
-                                               return false;
+                                       return true;
                                }
-
-                               return true;
                        }
-               skip:
+
                        ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
                        
                        ok &= TrueStatement.Resolve (ec);
@@ -364,15 +273,15 @@ namespace Mono.CSharp {
        public class Do : Statement {
                public Expression expr;
                public Statement  EmbeddedStatement;
-               
-               public Do (Statement statement, Expression bool_expr, Location l)
+
+               public Do (Statement statement, BooleanExpression bool_expr, Location l)
                {
                        expr = bool_expr;
                        EmbeddedStatement = statement;
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
@@ -386,9 +295,9 @@ namespace Mono.CSharp {
                        ec.EndFlowBranching ();
 
                        if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable)
-                               Report.Warning (162, 2, expr.Location, "Unreachable code detected");
+                               ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected");
 
-                       expr = Expression.ResolveBoolean (ec, expr, loc);
+                       expr = expr.Resolve (ec);
                        if (expr == null)
                                ok = false;
                        else if (expr is Constant){
@@ -453,21 +362,21 @@ namespace Mono.CSharp {
                public Expression expr;
                public Statement Statement;
                bool infinite, empty;
-               
-               public While (Expression bool_expr, Statement statement, Location l)
+
+               public While (BooleanExpression bool_expr, Statement statement, Location l)
                {
                        this.expr = bool_expr;
                        Statement = statement;
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
-                       expr = Expression.ResolveBoolean (ec, expr, loc);
+                       expr = expr.Resolve (ec);
                        if (expr == null)
-                               return false;
+                               ok = false;
 
                        //
                        // Inform whether we are infinite or not
@@ -578,7 +487,7 @@ namespace Mono.CSharp {
                bool infinite, empty;
                
                public For (Statement init_statement,
-                           Expression test,
+                           BooleanExpression test,
                            Statement increment,
                            Statement statement,
                            Location l)
@@ -590,7 +499,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
@@ -600,7 +509,7 @@ namespace Mono.CSharp {
                        }
 
                        if (Test != null){
-                               Test = Expression.ResolveBoolean (ec, Test, loc);
+                               Test = Test.Resolve (ec);
                                if (Test == null)
                                        ok = false;
                                else if (Test is Constant){
@@ -737,9 +646,9 @@ namespace Mono.CSharp {
                        loc = expr.Location;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       if (expr != null)
+                       if (expr != null && expr.eclass == ExprClass.Invalid)
                                expr = expr.ResolveStatement (ec);
                        return expr != null;
                }
@@ -771,14 +680,14 @@ namespace Mono.CSharp {
        public abstract class ExitStatement : Statement
        {
                protected bool unwind_protect;
-               protected abstract bool DoResolve (EmitContext ec);
+               protected abstract bool DoResolve (BlockContext ec);
 
-               public virtual void Error_FinallyClause ()
+               public virtual void Error_FinallyClause (Report Report)
                {
                        Report.Error (157, loc, "Control cannot leave the body of a finally clause");
                }
 
-               public sealed override bool Resolve (EmitContext ec)
+               public sealed override bool Resolve (BlockContext ec)
                {
                        if (!DoResolve (ec))
                                return false;
@@ -802,55 +711,48 @@ namespace Mono.CSharp {
                        loc = l;
                }
                
-               protected override bool DoResolve (EmitContext ec)
+               protected override bool DoResolve (BlockContext ec)
                {
                        if (Expr == null) {
                                if (ec.ReturnType == TypeManager.void_type)
                                        return true;
                                
-                               Error (126, "An object of a type convertible to `{0}' is required " +
-                                          "for the return statement",
-                                          TypeManager.CSharpName (ec.ReturnType));
+                               ec.Report.Error (126, loc,
+                                       "An object of a type convertible to `{0}' is required for the return statement",
+                                       TypeManager.CSharpName (ec.ReturnType));
                                return false;
                        }
 
                        if (ec.CurrentBlock.Toplevel.IsIterator) {
-                               Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
+                               ec.Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
                                                  "statement to return a value, or yield break to end the iteration");
                        }
 
                        AnonymousExpression am = ec.CurrentAnonymousMethod;
                        if (am == null && ec.ReturnType == TypeManager.void_type) {
-                               MemberCore mc = ec.ResolveContext as MemberCore;
-                               Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
-                                       mc.GetSignatureForError ());
+                               ec.Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
+                                       ec.GetSignatureForError ());
                        }
 
                        Expr = Expr.Resolve (ec);
                        if (Expr == null)
                                return false;
 
+                       if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
+                               ec.ReturnTypeInference.AddCommonTypeBound (Expr.Type);
+                               return true;
+                       }
+
                        if (Expr.Type != ec.ReturnType) {
-                               if (ec.InferReturnType) {
-                                       //
-                                       // void cannot be used in contextual return
-                                       //
-                                       if (Expr.Type == TypeManager.void_type)
-                                               return false;
+                               Expr = Convert.ImplicitConversionRequired (ec, Expr, ec.ReturnType, loc);
 
-                                       ec.ReturnType = Expr.Type;
-                               } else {
-                                       Expr = Convert.ImplicitConversionRequired (
-                                               ec, Expr, ec.ReturnType, loc);
-
-                                       if (Expr == null) {
-                                               if (am != null) {
-                                                       Report.Error (1662, loc,
-                                                               "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
-                                                               am.ContainerType, am.GetSignatureForError ());
-                                               }
-                                               return false;
+                               if (Expr == null) {
+                                       if (am != null) {
+                                               ec.Report.Error (1662, loc,
+                                                       "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
+                                                       am.ContainerType, am.GetSignatureForError ());
                                        }
+                                       return false;
                                }
                        }
 
@@ -891,13 +793,12 @@ namespace Mono.CSharp {
                string target;
                LabeledStatement label;
                bool unwind_protect;
-               
-               public override bool Resolve (EmitContext ec)
+
+               public override bool Resolve (BlockContext ec)
                {
-                       int errors = Report.Errors;
                        unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this);
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return errors == Report.Errors;
+                       return true;
                }
                
                public Goto (string label, Location l)
@@ -988,7 +889,7 @@ namespace Mono.CSharp {
                        // nothing to clone
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        // this flow-branching will be terminated when the surrounding block ends
                        ec.StartFlowBranching (this);
@@ -1029,23 +930,25 @@ namespace Mono.CSharp {
                        // nothing to clone
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
+
+                       if (ec.Switch == null) {
+                               ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+                               return false;
+                       }
+
+                       if (!ec.Switch.GotDefault) {
+                               FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report);
+                               return false;
+                       }
+
                        return true;
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       if (ec.Switch == null){
-                               Report.Error (153, loc, "A goto case is only valid inside a switch statement");
-                               return;
-                       }
-
-                       if (!ec.Switch.GotDefault){
-                               FlowBranchingBlock.Error_UnknownLabel (loc, "default");
-                               return;
-                       }
                        ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
                }
 
@@ -1067,10 +970,10 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        if (ec.Switch == null){
-                               Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+                               ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
                                return false;
                        }
 
@@ -1082,7 +985,7 @@ namespace Mono.CSharp {
 
                        Constant c = expr as Constant;
                        if (c == null) {
-                               Error (150, "A constant value is expected");
+                               ec.Report.Error (150, expr.Location, "A constant value is expected");
                                return false;
                        }
 
@@ -1094,7 +997,7 @@ namespace Mono.CSharp {
                        }
 
                        if (!Convert.ImplicitStandardConversionExists (c, type))
-                               Report.Warning (469, 2, loc,
+                               ec.Report.Warning (469, 2, loc,
                                        "The `goto case' value is not implicitly convertible to type `{0}'",
                                        TypeManager.CSharpName (type));
 
@@ -1106,7 +1009,7 @@ namespace Mono.CSharp {
 
                        if (sl == null){
                                FlowBranchingBlock.Error_UnknownLabel (loc, "case " + 
-                                       (c.GetValue () == null ? "null" : val.ToString ()));
+                                       (c.GetValue () == null ? "null" : val.ToString ()), ec.Report);
                                return false;
                        }
 
@@ -1140,7 +1043,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        if (expr == null) {
                                ec.CurrentBranching.CurrentUsageVector.Goto ();
@@ -1153,14 +1056,11 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       Type t = expr.Type;
+                       if (Convert.ImplicitConversionExists (ec, expr, TypeManager.exception_type))
+                               expr = Convert.ImplicitConversion (ec, expr, TypeManager.exception_type, loc);
+                       else
+                               ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
 
-                       if ((t != TypeManager.exception_type) &&
-                           !TypeManager.IsSubclassOf (t, TypeManager.exception_type) &&
-                           !(expr is NullLiteral)) {
-                               Error (155, "The type caught or thrown must be derived from System.Exception");
-                               return false;
-                       }
                        return true;
                }
                        
@@ -1199,12 +1099,11 @@ namespace Mono.CSharp {
 
                bool unwind_protect;
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       int errors = Report.Errors;
                        unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return errors == Report.Errors;
+                       return true;
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -1231,12 +1130,11 @@ namespace Mono.CSharp {
 
                bool unwind_protect;
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       int errors = Report.Errors;
                        unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return errors == Report.Errors;
+                       return true;
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -1270,7 +1168,7 @@ namespace Mono.CSharp {
        // The information about a user-perceived local variable
        //
        public class LocalInfo : IKnownVariable, ILocalVariable {
-               public readonly Expression Type;
+               public readonly FullNamedExpression Type;
 
                public Type VariableType;
                public readonly string Name;
@@ -1300,8 +1198,8 @@ namespace Mono.CSharp {
                Flags flags;
                ReadOnlyContext ro_context;
                LocalBuilder builder;
-               
-               public LocalInfo (Expression type, string name, Block block, Location l)
+
+               public LocalInfo (FullNamedExpression type, string name, Block block, Location l)
                {
                        Type = type;
                        Name = name;
@@ -1329,7 +1227,7 @@ namespace Mono.CSharp {
                                        //
                                        builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
                                else
-                                       builder = ec.ig.DeclareLocal (VariableType);
+                                       builder = ec.ig.DeclareLocal (TypeManager.TypeToReflectionType (VariableType));
                        }
                }
 
@@ -1354,7 +1252,7 @@ namespace Mono.CSharp {
                                ec.DefineLocalVariable (Name, builder);
                }
 
-               public bool IsThisAssigned (EmitContext ec)
+               public bool IsThisAssigned (BlockContext ec, Block block)
                {
                        if (VariableInfo == null)
                                throw new Exception ();
@@ -1362,10 +1260,10 @@ namespace Mono.CSharp {
                        if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
                                return true;
 
-                       return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, ec.loc);
+                       return VariableInfo.TypeInfo.IsFullyInitialized (ec, VariableInfo, block.StartLocation);
                }
 
-               public bool IsAssigned (EmitContext ec)
+               public bool IsAssigned (BlockContext ec)
                {
                        if (VariableInfo == null)
                                throw new Exception ();
@@ -1373,7 +1271,7 @@ namespace Mono.CSharp {
                        return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
                }
 
-               public bool Resolve (EmitContext ec)
+               public bool Resolve (ResolveContext ec)
                {
                        if (VariableType != null)
                                return true;
@@ -1388,12 +1286,12 @@ namespace Mono.CSharp {
                                return true;
 
                        if (VariableType.IsAbstract && VariableType.IsSealed) {
-                               FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType);
+                               FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType, ec.Report);
                                return false;
                        }
 
-                       if (VariableType.IsPointer && !ec.InUnsafe)
-                               Expression.UnsafeError (Location);
+                       if (VariableType.IsPointer && !ec.IsUnsafe)
+                               Expression.UnsafeError (ec, Location);
 
                        return true;
                }
@@ -1478,7 +1376,7 @@ namespace Mono.CSharp {
                        // Variables in anonymous block are not resolved yet
                        //
                        if (VariableType == null)
-                               return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+                               return new LocalInfo ((FullNamedExpression) Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
 
                        //
                        // Variables in method block are resolved
@@ -1662,9 +1560,9 @@ namespace Mono.CSharp {
                        EndLocation = loc;
                }
 
-               protected static void Error_158 (string name, Location loc)
+               protected void Error_158 (string name, Location loc)
                {
-                       Report.Error (158, loc, "The label `{0}' shadows another label " +
+                       Toplevel.Report.Error (158, loc, "The label `{0}' shadows another label " +
                                      "by the same name in a contained scope", name);
                }
 
@@ -1688,8 +1586,8 @@ namespace Mono.CSharp {
                        while (cur != null) {
                                LabeledStatement s = cur.DoLookupLabel (name);
                                if (s != null) {
-                                       Report.SymbolRelatedToPreviousError (s.loc, s.Name);
-                                       Report.Error (140, target.loc, "The label `{0}' is a duplicate", name);
+                                       Toplevel.Report.SymbolRelatedToPreviousError (s.loc, s.Name);
+                                       Toplevel.Report.Error (140, target.loc, "The label `{0}' is a duplicate", name);
                                        return false;
                                }
 
@@ -1711,7 +1609,7 @@ namespace Mono.CSharp {
                                                if (s == null)
                                                        continue;
 
-                                               Report.SymbolRelatedToPreviousError (s.loc, s.Name);
+                                               Toplevel.Report.SymbolRelatedToPreviousError (s.loc, s.Name);
                                                Error_158 (name, target.loc);
                                                return false;
                                        }
@@ -1783,8 +1681,8 @@ namespace Mono.CSharp {
                                // block, we violate the invariant meaning in a block.
                                //
                                if (b == this) {
-                                       Report.SymbolRelatedToPreviousError (kvi.Location, name);
-                                       Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", name);
+                                       Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
+                                       Toplevel.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", name);
                                        return false;
                                }
 
@@ -1808,8 +1706,8 @@ namespace Mono.CSharp {
                                return true;
 
                        if (this is ToplevelBlock) {
-                               Report.SymbolRelatedToPreviousError (kvi.Location, name);
-                               e.Error_VariableIsUsedBeforeItIsDeclared (name);
+                               Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
+                               e.Error_VariableIsUsedBeforeItIsDeclared (Toplevel.Report, name);
                                return false;
                        }
 
@@ -1817,7 +1715,7 @@ namespace Mono.CSharp {
                        // Even though we detected the error when the name is used, we
                        // treat it as if the variable declaration was in error.
                        //
-                       Report.SymbolRelatedToPreviousError (loc, name);
+                       Toplevel.Report.SymbolRelatedToPreviousError (loc, name);
                        Error_AlreadyDeclared (kvi.Location, name, "parent or current");
                        return false;
                }
@@ -1826,7 +1724,7 @@ namespace Mono.CSharp {
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
-                               Report.SymbolRelatedToPreviousError (vi.Location, name);
+                               block.Report.SymbolRelatedToPreviousError (vi.Location, name);
                                if (Explicit == vi.Block.Explicit) {
                                        Error_AlreadyDeclared (l, name, null);
                                } else {
@@ -1859,8 +1757,8 @@ namespace Mono.CSharp {
                        if (Toplevel.GenericMethod != null) {
                                foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
                                        if (tp.Name == name) {
-                                               Report.SymbolRelatedToPreviousError (tp);
-                                               Error_AlreadyDeclaredTypeParameter (loc, name, "local variable");
+                                               Toplevel.Report.SymbolRelatedToPreviousError (tp);
+                                               Error_AlreadyDeclaredTypeParameter (Toplevel.Report, loc, name, "local variable");
                                                return null;
                                        }
                                }
@@ -1868,12 +1766,12 @@ namespace Mono.CSharp {
 
                        IKnownVariable kvi = Explicit.GetKnownVariable (name);
                        if (kvi != null) {
-                               Report.SymbolRelatedToPreviousError (kvi.Location, name);
+                               Toplevel.Report.SymbolRelatedToPreviousError (kvi.Location, name);
                                Error_AlreadyDeclared (l, name, "child");
                                return null;
                        }
 
-                       LocalInfo vi = new LocalInfo (type, name, this, l);
+                       LocalInfo vi = new LocalInfo ((FullNamedExpression) type, name, this, l);
                        AddVariable (vi);
 
                        if ((flags & Flags.VariablesInitialized) != 0)
@@ -1895,7 +1793,7 @@ namespace Mono.CSharp {
                                return;
                        }
                        
-                       Report.Error (136, loc, "A local variable named `{0}' cannot be declared " +
+                       Toplevel.Report.Error (136, loc, "A local variable named `{0}' cannot be declared " +
                                      "in this scope because it would give a different meaning " +
                                      "to `{0}', which is already used in a `{1}' scope " +
                                      "to denote something else", var, reason);
@@ -1903,15 +1801,15 @@ namespace Mono.CSharp {
 
                protected virtual void Error_AlreadyDeclared (Location loc, string name)
                {
-                       Report.Error (128, loc,
+                       Toplevel.Report.Error (128, loc,
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
-               public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
+               public virtual void Error_AlreadyDeclaredTypeParameter (Report r, Location loc, string name, string conflict)
                {
-                       Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
+                       r.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
                                name, conflict);
-               }                                       
+               }
 
                public bool AddConstant (Expression type, string name, Expression value, Location l)
                {
@@ -2030,7 +1928,7 @@ namespace Mono.CSharp {
                        anonymous_children.Add (b);
                }
 
-               void DoResolveConstants (EmitContext ec)
+               void DoResolveConstants (BlockContext ec)
                {
                        if (constants == null)
                                return;
@@ -2045,7 +1943,7 @@ namespace Mono.CSharp {
 
                                if (variable_type == null) {
                                        if (vi.Type is VarExpr)
-                                               Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
+                                               ec.Report.Error (822, vi.Type.Location, "An implicitly typed local variable cannot be a constant");
 
                                        continue;
                                }
@@ -2060,13 +1958,13 @@ namespace Mono.CSharp {
                                constants.Remove (name);
 
                                if (!Const.IsConstantTypeValid (variable_type)) {
-                                       Const.Error_InvalidConstantType (variable_type, loc);
+                                       Const.Error_InvalidConstantType (variable_type, loc, ec.Report);
                                        continue;
                                }
 
                                ec.CurrentBlock = this;
                                Expression e;
-                               using (ec.With (EmitContext.Flags.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
+                               using (ec.With (ResolveContext.Options.ConstantCheckState, (flags & Flags.Unchecked) == 0)) {
                                        e = cv.Resolve (ec);
                                }
                                if (e == null)
@@ -2074,14 +1972,14 @@ namespace Mono.CSharp {
 
                                Constant ce = e as Constant;
                                if (ce == null) {
-                                       Const.Error_ExpressionMustBeConstant (vi.Location, name);
+                                       Const.Error_ExpressionMustBeConstant (vi.Location, name, ec.Report);
                                        continue;
                                }
 
                                e = ce.ConvertImplicitly (variable_type);
                                if (e == null) {
                                        if (TypeManager.IsReferenceType (variable_type))
-                                               Const.Error_ConstantCanBeInitializedWithNullOnly (variable_type, vi.Location, vi.Name);
+                                               Const.Error_ConstantCanBeInitializedWithNullOnly (variable_type, vi.Location, vi.Name, ec.Report);
                                        else
                                                ce.Error_ValueCannotBeConverted (ec, vi.Location, variable_type, false);
                                        continue;
@@ -2092,13 +1990,13 @@ namespace Mono.CSharp {
                        }
                }
 
-               protected void ResolveMeta (EmitContext ec, int offset)
+               protected void ResolveMeta (BlockContext ec, int offset)
                {
                        Report.Debug (64, "BLOCK RESOLVE META", this, Parent);
 
                        // If some parent block was unsafe, we remain unsafe even if this block
                        // isn't explicitly marked as such.
-                       using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
+                       using (ec.With (ResolveContext.Options.UnsafeScope, ec.IsUnsafe | Unsafe)) {
                                flags |= Flags.VariablesInitialized;
 
                                if (variables != null) {
@@ -2141,9 +2039,9 @@ namespace Mono.CSharp {
                        }
                }
 
-               void UsageWarning ()
+               void UsageWarning (BlockContext ec)
                {
-                       if (variables == null || Report.WarningLevel < 3)
+                       if (variables == null || ec.Report.WarningLevel < 3)
                                return;
 
                        foreach (DictionaryEntry de in variables) {
@@ -2154,14 +2052,14 @@ namespace Mono.CSharp {
 
                                        // vi.VariableInfo can be null for 'catch' variables
                                        if (vi.VariableInfo != null && vi.VariableInfo.IsEverAssigned)
-                                               Report.Warning (219, 3, vi.Location, "The variable `{0}' is assigned but its value is never used", name);
+                                               ec.Report.Warning (219, 3, vi.Location, "The variable `{0}' is assigned but its value is never used", name);
                                        else
-                                               Report.Warning (168, 3, vi.Location, "The variable `{0}' is declared but never used", name);
+                                               ec.Report.Warning (168, 3, vi.Location, "The variable `{0}' is declared but never used", name);
                                }
                        }
                }
 
-               static void CheckPossibleMistakenEmptyStatement (Statement s)
+               static void CheckPossibleMistakenEmptyStatement (BlockContext ec, Statement s)
                {
                        Statement body;
 
@@ -2190,21 +2088,29 @@ namespace Mono.CSharp {
                                return;
 
                        if (body == null || body is EmptyStatement)
-                               Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");
+                               ec.Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
                        bool ok = true;
 
-                       int errors = Report.Errors;
+                       int errors = ec.Report.Errors;
 
                        ec.CurrentBlock = this;
                        ec.StartFlowBranching (this);
 
                        Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
 
+                       //
+                       // Compiler generated scope statements
+                       //
+                       if (scope_initializers != null) {
+                               foreach (Statement s in scope_initializers)
+                                       s.Resolve (ec);
+                       }
+
                        //
                        // This flag is used to notate nested statements as unreachable from the beginning of this block.
                        // For the purposes of this resolution, it doesn't matter that the whole block is unreachable 
@@ -2215,10 +2121,9 @@ namespace Mono.CSharp {
                        for (int ix = 0; ix < statement_count; ix++){
                                Statement s = (Statement) statements [ix];
                                // Check possible empty statement (CS0642)
-                               if (Report.WarningLevel >= 3 &&
-                                       ix + 1 < statement_count &&
-                                               statements [ix + 1] is ExplicitBlock)
-                                       CheckPossibleMistakenEmptyStatement (s);
+                               if (ix + 1 < statement_count && ec.Report.WarningLevel >= 3 &&
+                                       statements [ix + 1] is ExplicitBlock)
+                                       CheckPossibleMistakenEmptyStatement (ec, s);
 
                                //
                                // Warn if we detect unreachable code.
@@ -2228,7 +2133,7 @@ namespace Mono.CSharp {
                                                continue;
 
                                        if (!unreachable_shown && !(s is LabeledStatement)) {
-                                               Report.Warning (162, 2, s.loc, "Unreachable code detected");
+                                               ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
                                                unreachable_shown = true;
                                        }
 
@@ -2280,25 +2185,25 @@ namespace Mono.CSharp {
                        if (this == Toplevel && !Toplevel.IsThisAssigned (ec) && !flow_unreachable)
                                ok = false;
 
-                       if ((labels != null) && (Report.WarningLevel >= 2)) {
+                       if ((labels != null) && (ec.Report.WarningLevel >= 2)) {
                                foreach (LabeledStatement label in labels.Values)
                                        if (!label.HasBeenReferenced)
-                                               Report.Warning (164, 2, label.loc, "This label has not been referenced");
+                                               ec.Report.Warning (164, 2, label.loc, "This label has not been referenced");
                        }
 
-                       if (ok && errors == Report.Errors)
-                               UsageWarning ();
+                       if (ok && errors == ec.Report.Errors)
+                               UsageWarning (ec);
 
                        return ok;
                }
 
-               public override bool ResolveUnreachable (EmitContext ec, bool warn)
+               public override bool ResolveUnreachable (BlockContext ec, bool warn)
                {
                        unreachable_shown = true;
                        unreachable = true;
 
                        if (warn)
-                               Report.Warning (162, 2, loc, "Unreachable code detected");
+                               ec.Report.Warning (162, 2, loc, "Unreachable code detected");
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        bool ok = Resolve (ec);
@@ -2317,9 +2222,6 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       Block prev_block = ec.CurrentBlock;
-                       ec.CurrentBlock = this;
-
                        if (scope_initializers != null)
                                EmitScopeInitializers (ec);
 
@@ -2328,15 +2230,13 @@ namespace Mono.CSharp {
 
                        if (SymbolWriter.HasSymbolWriter)
                                EmitSymbolInfo (ec);
-
-                       ec.CurrentBlock = prev_block;
                }
 
                protected void EmitScopeInitializers (EmitContext ec)
                {
                        SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
 
-                       using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) {
+                       using (ec.With (EmitContext.Options.OmitDebugInfo, true)) {
                                foreach (Statement s in scope_initializers)
                                        s.Emit (ec);
                        }
@@ -2461,7 +2361,7 @@ namespace Mono.CSharp {
                //
                // Creates anonymous method storey in current block
                //
-               public AnonymousMethodStorey CreateAnonymousMethodStorey (EmitContext ec)
+               public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec)
                {
                        //
                        // When referencing a variable in iterator storey from children anonymous method
@@ -2477,13 +2377,13 @@ namespace Mono.CSharp {
                            return ec.CurrentIterator.Storey;
 
                        if (am_storey == null) {
-                               MemberBase mc = ec.ResolveContext as MemberBase;
+                               MemberBase mc = ec.MemberContext as MemberBase;
                                GenericMethod gm = mc == null ? null : mc.GenericMethod;
 
                                //
                                // Creates anonymous method storey for this block
                                //
-                               am_storey = new AnonymousMethodStorey (this, ec.TypeContainer, mc, gm, "AnonStorey");
+                               am_storey = new AnonymousMethodStorey (this, ec.CurrentTypeDefinition, mc, gm, "AnonStorey");
                        }
 
                        return am_storey;
@@ -2511,9 +2411,16 @@ namespace Mono.CSharp {
                        //
                        if (am_storey != null) {
                                if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null) {
+                                       //
+                                       // Creates parent storey reference when hoisted this is accessible
+                                       //
                                        if (am_storey.OriginalSourceBlock.Explicit.HasCapturedThis) {
                                                ExplicitBlock parent = Toplevel.Parent.Explicit;
-                                               while (parent.am_storey == null)
+
+                                               //
+                                               // Hoisted this exists in top-level parent storey only
+                                               //
+                                               while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey)
                                                        parent = parent.Parent.Explicit;
 
                                                am_storey.AddParentStoreyReference (parent.am_storey);
@@ -2625,17 +2532,16 @@ namespace Mono.CSharp {
                                this.block = block;
                        }
 
-                       public override Expression CreateExpressionTree (EmitContext ec)
+                       public override Expression CreateExpressionTree (ResolveContext ec)
                        {
                                throw new NotSupportedException ();
                        }
 
-                       public override Expression DoResolve (EmitContext ec)
+                       public override Expression DoResolve (ResolveContext ec)
                        {
                                if (child == null)
                                        return null;
                                
-                               block.ResolveMeta (ec, ParametersCompiled.EmptyReadOnlyParameters);
                                child = child.Resolve (ec);
                                if (child == null)
                                        return null;
@@ -2661,13 +2567,21 @@ namespace Mono.CSharp {
                }
 
                GenericMethod generic;
-               FlowBranchingToplevel top_level_branching;
                protected ParametersCompiled parameters;
                ToplevelParameterInfo[] parameter_info;
                LocalInfo this_variable;
+               bool resolved;
+               bool unreachable;
+               CompilerContext compiler;
 
                public HoistedVariable HoistedThisVariable;
 
+               public bool Resolved {
+                       get {
+                               return resolved;
+                       }
+               }
+
                //
                // The parameters for the block.
                //
@@ -2675,6 +2589,10 @@ namespace Mono.CSharp {
                        get { return parameters; }
                }
 
+               public Report Report {
+                       get { return compiler.Report; }
+               }
+
                public GenericMethod GenericMethod {
                        get { return generic; }
                }
@@ -2683,32 +2601,33 @@ namespace Mono.CSharp {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
 
-               public ToplevelBlock (Block parent, ParametersCompiled parameters, Location start) :
-                       this (parent, (Flags) 0, parameters, start)
+               public ToplevelBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, Location start) :
+                       this (ctx, parent, (Flags) 0, parameters, start)
                {
                }
 
-               public ToplevelBlock (Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
-                       this (parent, parameters, start)
+               public ToplevelBlock (CompilerContext ctx, Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
+                       this (ctx, parent, parameters, start)
                {
                        this.generic = generic;
                }
-               
-               public ToplevelBlock (ParametersCompiled parameters, Location start) :
-                       this (null, (Flags) 0, parameters, start)
+
+               public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) :
+                       this (ctx, null, (Flags) 0, parameters, start)
                {
                }
 
-               ToplevelBlock (Flags flags, ParametersCompiled parameters, Location start) :
-                       this (null, flags, parameters, start)
+               ToplevelBlock (CompilerContext ctx, Flags flags, ParametersCompiled parameters, Location start) :
+                       this (ctx, null, flags, parameters, start)
                {
                }
 
                // We use 'Parent' to hook up to the containing block, but don't want to register the current block as a child.
                // So, we use a two-stage setup -- first pass a null parent to the base constructor, and then override 'Parent'.
-               public ToplevelBlock (Block parent, Flags flags, ParametersCompiled parameters, Location start) :
+               public ToplevelBlock (CompilerContext ctx, Block parent, Flags flags, ParametersCompiled parameters, Location start) :
                        base (null, flags, start, Location.Null)
                {
+                       this.compiler = ctx;
                        this.Toplevel = this;
 
                        this.parameters = parameters;
@@ -2720,8 +2639,8 @@ namespace Mono.CSharp {
                                ProcessParameters ();
                }
 
-               public ToplevelBlock (Location loc)
-                       : this (null, (Flags) 0, ParametersCompiled.EmptyReadOnlyParameters, loc)
+               public ToplevelBlock (CompilerContext ctx, Location loc)
+                       : this (ctx, null, (Flags) 0, ParametersCompiled.EmptyReadOnlyParameters, loc)
                {
                }
 
@@ -2787,7 +2706,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override Expression CreateExpressionTree (EmitContext ec)
+               public override Expression CreateExpressionTree (ResolveContext ec)
                {
                        if (statements.Count == 1) {
                                Expression expr = ((Statement) statements[0]).CreateExpressionTree (ec);
@@ -2819,10 +2738,6 @@ namespace Mono.CSharp {
                        return iterator_storey;
                }
 
-               public FlowBranchingToplevel TopLevelBranching {
-                       get { return top_level_branching; }
-               }
-
                //
                // Returns a parameter reference expression for the given name,
                // or null if there is no such parameter
@@ -2878,19 +2793,60 @@ namespace Mono.CSharp {
                        set { flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator; }
                }
 
-               public bool IsThisAssigned (EmitContext ec)
+               public bool IsThisAssigned (BlockContext ec)
                {
-                       return this_variable == null || this_variable.IsThisAssigned (ec);
+                       return this_variable == null || this_variable.IsThisAssigned (ec, this);
                }
 
-               public bool ResolveMeta (EmitContext ec, ParametersCompiled ip)
+               public bool Resolve (FlowBranching parent, BlockContext rc, ParametersCompiled ip, IMethodData md)
                {
-                       int errors = Report.Errors;
-                       int orig_count = parameters.Count;
-
-                       if (top_level_branching != null)
+                       if (resolved)
                                return true;
 
+                       resolved = true;
+
+                       try {
+                               if (!ResolveMeta (rc, ip))
+                                       return false;
+
+                               using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) {
+                                       FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent);
+
+                                       if (!Resolve (rc))
+                                               return false;
+
+                                       unreachable = top_level.End ();
+                               }
+                       } catch (Exception) {
+#if PRODUCTION
+                               if (rc.CurrentBlock != null) {
+                                       ec.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: Phase Resolve");
+                               } else {
+                                       ec.Report.Error (587, "Internal compiler error: Phase Resolve");
+                               }
+#endif
+                               throw;
+                       }
+
+                       if (rc.ReturnType != TypeManager.void_type && !unreachable) {
+                               if (rc.CurrentAnonymousMethod == null) {
+                                       rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+                                       return false;
+                               } else if (!rc.CurrentAnonymousMethod.IsIterator) {
+                                       rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
+                                                         rc.CurrentAnonymousMethod.GetSignatureForError ());
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               bool ResolveMeta (BlockContext ec, ParametersCompiled ip)
+               {
+                       int errors = ec.Report.Errors;
+                       int orig_count = parameters.Count;
+
                        if (ip != null)
                                parameters = ip;
 
@@ -2913,9 +2869,7 @@ namespace Mono.CSharp {
 
                        ResolveMeta (ec, offset);
 
-                       top_level_branching = ec.StartFlowBranching (this);
-
-                       return Report.Errors == errors;
+                       return ec.Report.Errors == errors;
                }
 
                // <summary>
@@ -2942,6 +2896,61 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void Emit (EmitContext ec)
+               {
+                       if (Report.Errors > 0)
+                               return;
+
+#if PRODUCTION
+                       try {
+#endif
+                       EmitMeta (ec);
+
+                       if (ec.HasReturnLabel)
+                               ec.ReturnLabel = ec.ig.DefineLabel ();
+
+                       base.Emit (ec);
+
+                       ec.Mark (EndLocation);
+
+                       if (ec.HasReturnLabel)
+                               ec.ig.MarkLabel (ec.ReturnLabel);
+
+                       if (ec.return_value != null) {
+                               ec.ig.Emit (OpCodes.Ldloc, ec.return_value);
+                               ec.ig.Emit (OpCodes.Ret);
+                       } else {
+                               //
+                               // If `HasReturnLabel' is set, then we already emitted a
+                               // jump to the end of the method, so we must emit a `ret'
+                               // there.
+                               //
+                               // Unfortunately, System.Reflection.Emit automatically emits
+                               // a leave to the end of a finally block.  This is a problem
+                               // if no code is following the try/finally block since we may
+                               // jump to a point after the end of the method.
+                               // As a workaround, we're always creating a return label in
+                               // this case.
+                               //
+
+                               if (ec.HasReturnLabel || !unreachable) {
+                                       if (ec.ReturnType != TypeManager.void_type)
+                                               ec.ig.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
+                                       ec.ig.Emit (OpCodes.Ret);
+                               }
+                       }
+
+#if PRODUCTION
+                       } catch (Exception e){
+                               Console.WriteLine ("Exception caught by the compiler while emitting:");
+                               Console.WriteLine ("   Block that caused the problem begin at: " + block.loc);
+                                       
+                               Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
+                               throw;
+                       }
+#endif
+               }
+
                public override void EmitMeta (EmitContext ec)
                {
                        parameters.ResolveVariable ();
@@ -2961,12 +2970,6 @@ namespace Mono.CSharp {
 
                        base.EmitSymbolInfo (ec);
                }
-
-               public override void Emit (EmitContext ec)
-               {
-                       base.Emit (ec);
-                       ec.Mark (EndLocation);
-               }
        }
        
        public class SwitchLabel {
@@ -3028,7 +3031,7 @@ namespace Mono.CSharp {
                // Resolves the expression, reduces it to a literal if possible
                // and then converts it to the requested type.
                //
-               public bool ResolveAndReduce (EmitContext ec, Type required_type, bool allow_nullable)
+               public bool ResolveAndReduce (ResolveContext ec, Type required_type, bool allow_nullable)
                {       
                        Expression e = label.Resolve (ec);
 
@@ -3037,7 +3040,7 @@ namespace Mono.CSharp {
 
                        Constant c = e as Constant;
                        if (c == null){
-                               Report.Error (150, loc, "A constant value is expected");
+                               ec.Report.Error (150, loc, "A constant value is expected");
                                return false;
                        }
 
@@ -3059,7 +3062,7 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public void Error_AlreadyOccurs (Type switch_type, SwitchLabel collision_with)
+               public void Error_AlreadyOccurs (ResolveContext ec, Type switch_type, SwitchLabel collision_with)
                {
                        string label;
                        if (converted == null)
@@ -3069,8 +3072,8 @@ namespace Mono.CSharp {
                        else
                                label = converted.ToString ();
                        
-                       Report.SymbolRelatedToPreviousError (collision_with.loc, null);
-                       Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
+                       ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null);
+                       ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
                }
 
                public SwitchLabel Clone (CloneContext clonectx)
@@ -3130,20 +3133,14 @@ namespace Mono.CSharp {
                FieldExpr switch_cache_field;
                static int unique_counter;
 
-#if GMCS_SOURCE
                //
-               // Nullable Types support for GMCS.
+               // Nullable Types support
                //
                Nullable.Unwrap unwrap;
 
                protected bool HaveUnwrap {
                        get { return unwrap != null; }
                }
-#else
-               protected bool HaveUnwrap {
-                       get { return false; }
-               }
-#endif
 
                //
                // The types allowed to be implicitly cast from
@@ -3176,7 +3173,7 @@ namespace Mono.CSharp {
                // expression that includes any potential conversions to the
                // integral types or to string.
                //
-               Expression SwitchGoverningType (EmitContext ec, Expression expr)
+               Expression SwitchGoverningType (ResolveContext ec, Expression expr)
                {
                        Type t = expr.Type;
 
@@ -3231,7 +3228,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (converted != null){
-                                       Report.ExtraInformation (loc, "(Ambiguous implicit user defined conversion in previous ");
+                                       ec.Report.ExtraInformation (loc, "(Ambiguous implicit user defined conversion in previous ");
                                        return null;
                                }
 
@@ -3247,7 +3244,7 @@ namespace Mono.CSharp {
                // It also returns a hashtable with the keys that we will later
                // use to compute the switch tables
                //
-               bool CheckSwitch (EmitContext ec)
+               bool CheckSwitch (ResolveContext ec)
                {
                        bool error = false;
                        Elements = Sections.Count > 10 ? 
@@ -3258,7 +3255,7 @@ namespace Mono.CSharp {
                                foreach (SwitchLabel sl in ss.Labels){
                                        if (sl.Label == null){
                                                if (default_section != null){
-                                                       sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]);
+                                                       sl.Error_AlreadyOccurs (ec, SwitchType, (SwitchLabel)default_section.Labels [0]);
                                                        error = true;
                                                }
                                                default_section = ss;
@@ -3277,7 +3274,7 @@ namespace Mono.CSharp {
                                        try {
                                                Elements.Add (key, sl);
                                        } catch (ArgumentException) {
-                                               sl.Error_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]);
+                                               sl.Error_AlreadyOccurs (ec, SwitchType, (SwitchLabel)Elements [key]);
                                                error = true;
                                        }
                                }
@@ -3595,9 +3592,10 @@ namespace Mono.CSharp {
                public static void Reset ()
                {
                        unique_counter = 0;
+                       allowed_types = null;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        Expr = Expr.Resolve (ec);
                        if (Expr == null)
@@ -3605,18 +3603,18 @@ namespace Mono.CSharp {
 
                        new_expr = SwitchGoverningType (ec, Expr);
 
-#if GMCS_SOURCE
                        if ((new_expr == null) && TypeManager.IsNullableType (Expr.Type)) {
-                               unwrap = Nullable.Unwrap.Create (Expr, ec);
+                               unwrap = Nullable.Unwrap.Create (Expr, false);
                                if (unwrap == null)
                                        return false;
 
                                new_expr = SwitchGoverningType (ec, unwrap);
                        }
-#endif
 
                        if (new_expr == null){
-                               Report.Error (151, loc, "A value of an integral type or string expected for switch");
+                               ec.Report.Error (151, loc,
+                                       "A switch expression of type `{0}' cannot be converted to an integral type, bool, char, string, enum or nullable type",
+                                       TypeManager.CSharpName (Expr.Type));
                                return false;
                        }
 
@@ -3624,7 +3622,7 @@ namespace Mono.CSharp {
                        SwitchType = new_expr.Type;
 
                        if (RootContext.Version == LanguageVersion.ISO_1 && SwitchType == TypeManager.bool_type) {
-                               Report.FeatureIsNotAvailable (loc, "switch expression of boolean type");
+                               ec.Report.FeatureIsNotAvailable (loc, "switch expression of boolean type");
                                return false;
                        }
 
@@ -3694,40 +3692,40 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               void ResolveStringSwitchMap (EmitContext ec)
+               void ResolveStringSwitchMap (ResolveContext ec)
                {
                        FullNamedExpression string_dictionary_type;
-#if GMCS_SOURCE
-                       MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
-                               new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc), "Generic", loc);
-
-                       string_dictionary_type = new MemberAccess (system_collections_generic, "Dictionary",
-                               new TypeArguments (
-                                       new TypeExpression (TypeManager.string_type, loc),
-                                       new TypeExpression (TypeManager.int32_type, loc)), loc);
-#else
-                       MemberAccess system_collections_generic = new MemberAccess (
-                               new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc);
-
-                       string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
-#endif
-                       Field field = new Field (ec.TypeContainer, string_dictionary_type,
+                       if (TypeManager.generic_ienumerable_type != null) {
+                               MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
+                                       new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc), "Generic", loc);
+
+                               string_dictionary_type = new MemberAccess (system_collections_generic, "Dictionary",
+                                       new TypeArguments (
+                                               new TypeExpression (TypeManager.string_type, loc),
+                                               new TypeExpression (TypeManager.int32_type, loc)), loc);
+                       } else {
+                               MemberAccess system_collections_generic = new MemberAccess (
+                                       new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc);
+
+                               string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
+                       }
+
+                       Field field = new Field (ec.CurrentTypeDefinition, string_dictionary_type,
                                Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
                                new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null);
                        if (!field.Define ())
                                return;
-                       ec.TypeContainer.PartialContainer.AddField (field);
+                       ec.CurrentTypeDefinition.PartialContainer.AddField (field);
 
                        ArrayList init = new ArrayList ();
                        int counter = 0;
                        Elements.Clear ();
                        string value = null;
                        foreach (SwitchSection section in Sections) {
+                               int last_count = init.Count;
                                foreach (SwitchLabel sl in section.Labels) {
-                                       if (sl.Label == null || sl.Converted == SwitchLabel.NullStringCase) {
-                                               value = null;
+                                       if (sl.Label == null || sl.Converted == SwitchLabel.NullStringCase)
                                                continue;
-                                       }
 
                                        value = (string) sl.Converted;
                                        ArrayList init_args = new ArrayList (2);
@@ -3736,15 +3734,18 @@ namespace Mono.CSharp {
                                        init.Add (new CollectionElementInitializer (init_args, loc));
                                }
 
-                               if (value == null)
+                               //
+                               // Don't add empty sections
+                               //
+                               if (last_count == init.Count)
                                        continue;
 
                                Elements.Add (counter, section.Labels [0]);
                                ++counter;
                        }
 
-                       ArrayList args = new ArrayList (1);
-                       args.Add (new Argument (new IntConstant (Sections.Count, loc)));
+                       Arguments args = new Arguments (1);
+                       args.Add (new Argument (new IntConstant (init.Count, loc)));
                        Expression initializer = new NewInitialize (string_dictionary_type, args,
                                new CollectionOrObjectInitializers (init, loc), loc);
 
@@ -3771,36 +3772,39 @@ namespace Mono.CSharp {
 
                        LocalTemporary string_switch_variable = new LocalTemporary (TypeManager.int32_type);
 
-#if GMCS_SOURCE
-                       ArrayList get_value_args = new ArrayList (2);
-                       get_value_args.Add (new Argument (value));
-                       get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out));
-                       Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (ec);
-                       if (get_item == null)
-                               return;
+                       ResolveContext rc = new ResolveContext (ec.MemberContext);
 
-                       //
-                       // A value was not found, go to default case
-                       //
-                       get_item.EmitBranchable (ec, default_target, false);
-#else
-                       ArrayList get_value_args = new ArrayList (1);
-                       get_value_args.Add (value);
+                       if (TypeManager.generic_ienumerable_type != null) {
+                               Arguments get_value_args = new Arguments (2);
+                               get_value_args.Add (new Argument (value));
+                               get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out));
+                               Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (rc);
+                               if (get_item == null)
+                                       return;
 
-                       Expression get_item = new IndexerAccess (new ElementAccess (switch_cache_field, get_value_args), loc).Resolve (ec);
-                       if (get_item == null)
-                               return;
+                               //
+                               // A value was not found, go to default case
+                               //
+                               get_item.EmitBranchable (ec, default_target, false);
+                       } else {
+                               Arguments get_value_args = new Arguments (1);
+                               get_value_args.Add (new Argument (value));
 
-                       LocalTemporary get_item_object = new LocalTemporary (TypeManager.object_type);
-                       get_item_object.EmitAssign (ec, get_item, true, false);
-                       ec.ig.Emit (OpCodes.Brfalse, default_target);
+                               Expression get_item = new IndexerAccess (new ElementAccess (switch_cache_field, get_value_args), loc).Resolve (rc);
+                               if (get_item == null)
+                                       return;
 
-                       ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
-                               new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (ec);
+                               LocalTemporary get_item_object = new LocalTemporary (TypeManager.object_type);
+                               get_item_object.EmitAssign (ec, get_item, true, false);
+                               ec.ig.Emit (OpCodes.Brfalse, default_target);
+
+                               ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
+                                       new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (rc);
+
+                               get_item_int.EmitStatement (ec);
+                               get_item_object.Release (ec);
+                       }
 
-                       get_item_int.EmitStatement (ec);
-                       get_item_object.Release (ec);
-#endif
                        TableSwitchEmit (ec, string_switch_variable);
                        string_switch_variable.Release (ec);
                }
@@ -3817,12 +3821,10 @@ namespace Mono.CSharp {
                        LocalTemporary value;
                        if (HaveUnwrap) {
                                value = new LocalTemporary (SwitchType);
-#if GMCS_SOURCE
                                unwrap.EmitCheck (ec);
                                ig.Emit (OpCodes.Brfalse, null_target);
                                new_expr.Emit (ec);
                                value.Store (ec);
-#endif
                        } else if (!is_constant) {
                                value = new LocalTemporary (SwitchType);
                                new_expr.Emit (ec);
@@ -3902,6 +3904,7 @@ namespace Mono.CSharp {
        public abstract class ExceptionStatement : ResumableStatement
        {
                bool code_follows;
+               Iterator iter;
 
                protected abstract void EmitPreTryBody (EmitContext ec);
                protected abstract void EmitTryBody (EmitContext ec);
@@ -3915,7 +3918,7 @@ namespace Mono.CSharp {
 
                        if (resume_points != null) {
                                IntConstant.EmitInt (ig, (int) Iterator.State.Running);
-                               ig.Emit (OpCodes.Stloc, ec.CurrentIterator.CurrentPC);
+                               ig.Emit (OpCodes.Stloc, iter.CurrentPC);
                        }
 
                        ig.BeginExceptionBlock ();
@@ -3925,7 +3928,7 @@ namespace Mono.CSharp {
 
                                // For normal control flow, we want to fall-through the Switch
                                // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above
-                               ig.Emit (OpCodes.Ldloc, ec.CurrentIterator.CurrentPC);
+                               ig.Emit (OpCodes.Ldloc, iter.CurrentPC);
                                IntConstant.EmitInt (ig, first_resume_pc);
                                ig.Emit (OpCodes.Sub);
 
@@ -3941,7 +3944,7 @@ namespace Mono.CSharp {
 
                        Label start_finally = ec.ig.DefineLabel ();
                        if (resume_points != null) {
-                               ig.Emit (OpCodes.Ldloc, ec.CurrentIterator.SkipFinally);
+                               ig.Emit (OpCodes.Ldloc, iter.SkipFinally);
                                ig.Emit (OpCodes.Brfalse_S, start_finally);
                                ig.Emit (OpCodes.Endfinally);
                        }
@@ -3957,13 +3960,15 @@ namespace Mono.CSharp {
                        code_follows = true;
                }
 
-               protected void ResolveReachability (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause
                        // So, ensure there's some IL code after this statement.
                        if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable)
                                ec.NeedReturnLabel ();
 
+                       iter = ec.CurrentIterator;
+                       return true;
                }
 
                ArrayList resume_points;
@@ -4067,14 +4072,14 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return false;
 
                        if (!TypeManager.IsReferenceType (expr.Type)){
-                               Report.Error (185, loc,
+                               ec.Report.Error (185, loc,
                                              "`{0}' is not a reference type as required by the lock statement",
                                              TypeManager.CSharpName (expr.Type));
                                return false;
@@ -4084,7 +4089,7 @@ namespace Mono.CSharp {
                        bool ok = Statement.Resolve (ec);
                        ec.EndFlowBranching ();
 
-                       ResolveReachability (ec);
+                       ok &= base.Resolve (ec);
 
                        // Avoid creating libraries that reference the internal
                        // mcs NullType:
@@ -4096,7 +4101,7 @@ namespace Mono.CSharp {
                        temp.Resolve (ec);
 
                        if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) {
-                               Type monitor_type = TypeManager.CoreLookupType ("System.Threading", "Monitor", Kind.Class, true);
+                               Type monitor_type = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Monitor", Kind.Class, true);
                                TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod (
                                        monitor_type, "Enter", loc, TypeManager.object_type);
                                TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod (
@@ -4151,15 +4156,15 @@ namespace Mono.CSharp {
                        b.Unchecked = true;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+                       using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
                                return Block.Resolve (ec);
                }
                
                protected override void DoEmit (EmitContext ec)
                {
-                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
+                       using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
                                Block.Emit (ec);
                }
 
@@ -4185,15 +4190,15 @@ namespace Mono.CSharp {
                        b.Unchecked = false;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
-                               return Block.Resolve (ec);
+                       using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
+                               return Block.Resolve (ec);
                }
 
                protected override void DoEmit (EmitContext ec)
                {
-                       using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
+                       using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
                                Block.Emit (ec);
                }
 
@@ -4217,18 +4222,21 @@ namespace Mono.CSharp {
                {
                        Block = b;
                        Block.Unsafe = true;
+                       loc = b.StartLocation;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       using (ec.With (EmitContext.Flags.InUnsafe, true))
+                       if (ec.CurrentIterator != null)
+                               ec.Report.Error (1629, loc, "Unsafe code may not appear in iterators");
+
+                       using (ec.Set (ResolveContext.Options.UnsafeScope))
                                return Block.Resolve (ec);
                }
                
                protected override void DoEmit (EmitContext ec)
                {
-                       using (ec.With (EmitContext.Flags.InUnsafe, true))
-                               Block.Emit (ec);
+                       Block.Emit (ec);
                }
 
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
@@ -4292,81 +4300,52 @@ namespace Mono.CSharp {
                        }
                }
 
-               class StringEmitter : Emitter {
-                       class StringPtr : Expression
-                       {
-                               LocalBuilder b;
-
-                               public StringPtr (LocalBuilder b, Location l)
-                               {
-                                       this.b = b;
-                                       eclass = ExprClass.Value;
-                                       type = TypeManager.char_ptr_type;
-                                       loc = l;
-                               }
-
-                               public override Expression CreateExpressionTree (EmitContext ec)
-                               {
-                                       throw new NotSupportedException ("ET");
-                               }
-
-                               public override Expression DoResolve (EmitContext ec)
-                               {
-                                       // This should never be invoked, we are born in fully
-                                       // initialized state.
-
-                                       return this;
-                               }
+               class StringEmitter : Emitter
+               {
+                       LocalInfo pinned_string;
 
-                               public override void Emit (EmitContext ec)
-                               {
-                                       if (TypeManager.int_get_offset_to_string_data == null) {
-                                               // TODO: Move to resolve !!
-                                               TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
-                                                       TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
-                                       }
+                       public StringEmitter (Expression expr, LocalInfo li, Location loc):
+                               base (expr, li)
+                       {
+                               pinned_string = new LocalInfo (new TypeExpression (TypeManager.string_type, loc), null, null, loc);
+                               pinned_string.Pinned = true;
+                       }
 
-                                       ILGenerator ig = ec.ig;
+                       public StringEmitter Resolve (ResolveContext rc)
+                       {
+                               pinned_string.Resolve (rc);
 
-                                       ig.Emit (OpCodes.Ldloc, b);
-                                       ig.Emit (OpCodes.Conv_I);
-                                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
-                                       ig.Emit (OpCodes.Add);
+                               if (TypeManager.int_get_offset_to_string_data == null) {
+                                       TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
+                                               TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
                                }
-                       }
-
-                       LocalBuilder pinned_string;
-                       Location loc;
 
-                       public StringEmitter (Expression expr, LocalInfo li, Location loc):
-                               base (expr, li)
-                       {
-                               this.loc = loc;
+                               return this;
                        }
 
                        public override void Emit (EmitContext ec)
                        {
-                               ILGenerator ig = ec.ig;
-                               pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
-                                       
+                               pinned_string.ResolveVariable (ec);
+
                                converted.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, pinned_string);
+                               pinned_string.EmitAssign (ec);
 
-                               Expression sptr = new StringPtr (pinned_string, loc);
-                               converted = Convert.ImplicitConversionRequired (
-                                       ec, sptr, vi.VariableType, loc);
-                                       
-                               if (converted == null)
-                                       return;
+                               // TODO: Should use Binary::Add
+                               pinned_string.Emit (ec);
+                               ec.ig.Emit (OpCodes.Conv_I);
 
-                               converted.Emit (ec);
+                               PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, TypeManager.int_get_offset_to_string_data, pinned_string.Location);
+                               //pe.InstanceExpression = pinned_string;
+                               pe.Resolve (new ResolveContext (ec.MemberContext)).Emit (ec);
+
+                               ec.ig.Emit (OpCodes.Add);
                                vi.EmitAssign (ec);
                        }
 
                        public override void EmitExit (EmitContext ec)
                        {
                                ec.ig.Emit (OpCodes.Ldnull);
-                               ec.ig.Emit (OpCodes.Stloc, pinned_string);
+                               pinned_string.EmitAssign (ec);
                        }
                }
 
@@ -4382,17 +4361,17 @@ namespace Mono.CSharp {
                        get { return statement; }
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       if (!ec.InUnsafe){
-                               Expression.UnsafeError (loc);
+                       if (!ec.IsUnsafe){
+                               Expression.UnsafeError (ec, loc);
                                return false;
                        }
                        
                        TypeExpr texpr = type.ResolveAsContextualType (ec, false);
                        if (texpr == null) {
                                if (type is VarExpr)
-                                       Report.Error (821, type.Location, "A fixed statement cannot use an implicitly typed local variable");
+                                       ec.Report.Error (821, type.Location, "A fixed statement cannot use an implicitly typed local variable");
 
                                return false;
                        }
@@ -4402,7 +4381,7 @@ namespace Mono.CSharp {
                        data = new Emitter [declarators.Count];
 
                        if (!expr_type.IsPointer){
-                               Report.Error (209, loc, "The type of locals declared in a fixed statement must be a pointer type");
+                               ec.Report.Error (209, loc, "The type of locals declared in a fixed statement must be a pointer type");
                                return false;
                        }
                        
@@ -4426,13 +4405,14 @@ namespace Mono.CSharp {
                                //
 
                                if (e is Cast){
-                                       Report.Error (254, loc, "The right hand side of a fixed statement assignment may not be a cast expression");
+                                       ec.Report.Error (254, loc, "The right hand side of a fixed statement assignment may not be a cast expression");
                                        return false;
                                }
 
-                               ec.InFixedInitializer = true;
-                               e = e.Resolve (ec);
-                               ec.InFixedInitializer = false;
+                               using (ec.Set (ResolveContext.Options.FixedInitializerScope)) {
+                                       e = e.Resolve (ec);
+                               }
+
                                if (e == null)
                                        return false;
 
@@ -4462,9 +4442,9 @@ namespace Mono.CSharp {
                                        //
                                        // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0])
                                        //
-                                       converted = new Conditional (new Binary (Binary.Operator.LogicalOr,
+                                       converted = new Conditional (new BooleanExpression (new Binary (Binary.Operator.LogicalOr,
                                                new Binary (Binary.Operator.Equality, e, new NullLiteral (loc)),
-                                               new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))),
+                                               new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc)))),
                                                        new NullPointer (loc),
                                                        converted);
 
@@ -4480,7 +4460,7 @@ namespace Mono.CSharp {
                                // Case 3: string
                                //
                                if (e.Type == TypeManager.string_type){
-                                       data [i] = new StringEmitter (e, vi, loc);
+                                       data [i] = new StringEmitter (e, vi, loc).Resolve (ec);
                                        i++;
                                        continue;
                                }
@@ -4503,7 +4483,7 @@ namespace Mono.CSharp {
                                }
 
                                if (data [i++] == null)
-                                       Report.Error (213, vi.Location, "You cannot use the fixed statement to take the address of an already fixed expression");
+                                       ec.Report.Error (213, vi.Location, "You cannot use the fixed statement to take the address of an already fixed expression");
 
                                e = Convert.ImplicitConversionRequired (ec, e, expr_type, loc);
                        }
@@ -4603,7 +4583,11 @@ namespace Mono.CSharp {
                        if (Name != null) {
                                // TODO: Move to resolve
                                LocalVariableReference lvr = new LocalVariableReference (Block, Name, loc);
-                               lvr.Resolve (ec);
+                               lvr.Resolve (new ResolveContext (ec.MemberContext));
+                               
+                               // Only to make verifier happy
+                               if (TypeManager.IsGenericParameter (lvr.Type))
+                                       ig.Emit (OpCodes.Unbox_Any, lvr.Type);
 
                                Expression source;
                                if (lvr.IsHoisted) {
@@ -4622,9 +4606,9 @@ namespace Mono.CSharp {
                        Block.Emit (ec);
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
-                       using (ec.With (EmitContext.Flags.InCatch, true)) {
+                       using (ec.With (ResolveContext.Options.CatchScope, true)) {
                                if (type_expr != null) {
                                        TypeExpr te = type_expr.ResolveAsTypeTerminal (ec, false);
                                        if (te == null)
@@ -4633,7 +4617,7 @@ namespace Mono.CSharp {
                                        type = te.Type;
 
                                        if (type != TypeManager.exception_type && !TypeManager.IsSubclassOf (type, TypeManager.exception_type)){
-                                               Error (155, "The type caught or thrown must be derived from System.Exception");
+                                               ec.Report.Error (155, loc, "The type caught or thrown must be derived from System.Exception");
                                                return false;
                                        }
                                } else
@@ -4683,7 +4667,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
@@ -4694,14 +4678,14 @@ namespace Mono.CSharp {
 
                        if (ok)
                                ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally);
-                       using (ec.With (EmitContext.Flags.InFinally, true)) {
+                       using (ec.With (ResolveContext.Options.FinallyScope, true)) {
                                if (!fini.Resolve (ec))
                                        ok = false;
                        }
 
                        ec.EndFlowBranching ();
 
-                       ResolveReachability (ec);
+                       ok &= base.Resolve (ec);
 
                        return ok;
                }
@@ -4746,24 +4730,18 @@ namespace Mono.CSharp {
                {
                        this.Block = block;
                        this.Specific = catch_clauses;
-                       this.General = null;
                        this.inside_try_finally = inside_try_finally;
 
-                       for (int i = 0; i < catch_clauses.Count; ++i) {
-                               Catch c = (Catch) catch_clauses [i];
-                               if (c.IsGeneral) {
-                                       if (i != catch_clauses.Count - 1)
-                                               Report.Error (1017, c.loc, "Try statement already has an empty catch block");
-                                       this.General = c;
-                                       catch_clauses.RemoveAt (i);
-                                       i--;
-                               }
+                       Catch c = (Catch) catch_clauses [0];
+                       if (c.IsGeneral) {
+                               this.General = c;                       
+                               catch_clauses.RemoveAt (0);
                        }
 
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        bool ok = true;
 
@@ -4785,13 +4763,15 @@ namespace Mono.CSharp {
                                        vi.VariableInfo = null;
                                }
 
-                               if (!c.Resolve (ec))
+                               if (!c.Resolve (ec)) {
                                        ok = false;
+                                       continue;
+                               }
 
                                Type resolved_type = c.CatchType;
                                for (int ii = 0; ii < last_index; ++ii) {
                                        if (resolved_type == prev_catches [ii] || TypeManager.IsSubclassOf (resolved_type, prev_catches [ii])) {
-                                               Report.Error (160, c.loc,
+                                               ec.Report.Error (160, c.loc,
                                                        "A previous catch clause already catches all exceptions of this or a super type `{0}'",
                                                        TypeManager.CSharpName (prev_catches [ii]));
                                                ok = false;
@@ -4804,8 +4784,8 @@ namespace Mono.CSharp {
                        if (General != null) {
                                if (CodeGen.Assembly.WrapNonExceptionThrows) {
                                        foreach (Catch c in Specific){
-                                               if (c.CatchType == TypeManager.exception_type) {
-                                                       Report.Warning (1058, 1, c.loc, "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
+                                               if (c.CatchType == TypeManager.exception_type && PredefinedAttributes.Get.RuntimeCompatibility.IsDefined) {
+                                                       ec.Report.Warning (1058, 1, c.loc, "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
                                                }
                                        }
                                }
@@ -4877,6 +4857,7 @@ namespace Mono.CSharp {
                }
        }
 
+       // FIXME: Why is it almost exact copy of Using ??
        public class UsingTemporary : ExceptionStatement {
                TemporaryVariable local_copy;
                public Statement Statement;
@@ -4890,7 +4871,7 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
@@ -4900,7 +4881,7 @@ namespace Mono.CSharp {
 
                        if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)) {
                                if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
-                                       Using.Error_IsNotConvertibleToIDisposable (expr);
+                                       Using.Error_IsNotConvertibleToIDisposable (ec, expr);
                                        return false;
                                }
                        }
@@ -4914,7 +4895,7 @@ namespace Mono.CSharp {
 
                        ec.EndFlowBranching ();
 
-                       ResolveReachability (ec);
+                       ok &= base.Resolve (ec);
 
                        if (TypeManager.void_dispose_void == null) {
                                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
@@ -4947,8 +4928,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       Expression ml = Expression.MemberLookup (
-                               ec.ContainerType, TypeManager.idisposable_type, expr_type,
+                       Expression ml = Expression.MemberLookup (RootContext.ToplevelTypes.Compiler,
+                               ec.CurrentType, TypeManager.idisposable_type, expr_type,
                                "Dispose", Location.Null);
 
                        if (!(ml is MethodGroupExpr)) {
@@ -4968,7 +4949,7 @@ namespace Mono.CSharp {
                        }
 
                        if (mi == null) {
-                               Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
+                               RootContext.ToplevelTypes.Compiler.Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
                                return;
                        }
 
@@ -5001,7 +4982,6 @@ namespace Mono.CSharp {
                Expression var;
                Expression init;
 
-               Expression converted_var;
                ExpressionStatement assign;
 
                public Using (Expression var, Expression init, Statement stmt, Location l)
@@ -5012,36 +4992,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               bool ResolveVariable (EmitContext ec)
+               static public void Error_IsNotConvertibleToIDisposable (BlockContext ec, Expression expr)
                {
-                       ExpressionStatement a = new SimpleAssign (var, init, loc);
-                       a = a.ResolveStatement (ec);
-                       if (a == null)
-                               return false;
-
-                       assign = a;
-
-                       if (TypeManager.ImplementsInterface (a.Type, TypeManager.idisposable_type)) {
-                               converted_var = var;
-                               return true;
-                       }
-
-                       Expression e = Convert.ImplicitConversionStandard (ec, a, TypeManager.idisposable_type, var.Location);
-                       if (e == null) {
-                               Error_IsNotConvertibleToIDisposable (var);
-                               return false;
-                       }
-
-                       converted_var = e;
-
-                       return true;
-               }
-
-               static public void Error_IsNotConvertibleToIDisposable (Expression expr)
-               {
-                       Report.SymbolRelatedToPreviousError (expr.Type);
-                       Report.Error (1674, expr.Location, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
-                               expr.GetSignatureForError ());
+                       ec.Report.SymbolRelatedToPreviousError (expr.Type);
+                       ec.Report.Error (1674, expr.Location, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
+                               TypeManager.CSharpName (expr.Type));
                }
 
                protected override void EmitPreTryBody (EmitContext ec)
@@ -5057,42 +5012,18 @@ namespace Mono.CSharp {
                protected override void EmitFinallyBody (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
+                       Label skip = ig.DefineLabel ();
 
-                       if (!TypeManager.IsStruct (var.Type)) {
-                               Label skip = ig.DefineLabel ();
+                       bool emit_null_check = !TypeManager.IsValueType (var.Type);
+                       if (emit_null_check) {
                                var.Emit (ec);
                                ig.Emit (OpCodes.Brfalse, skip);
-                               converted_var.Emit (ec);
-                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               ig.MarkLabel (skip);
-                       } else {
-                               Expression ml = Expression.MemberLookup(ec.ContainerType, 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 (TypeManager.GetParameterData (mk).Count == 0) {
-                                                       mi = mk;
-                                                       break;
-                                               }
-                                       }
-
-                                       if (mi == null) {
-                                               Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
-                                               return;
-                                       }
+                       }
 
-                                       IMemoryLocation mloc = (IMemoryLocation) var;
+                       Invocation.EmitCall (ec, false, var, TypeManager.void_dispose_void, null, loc);
 
-                                       mloc.AddressOf (ec, AddressOp.Load);
-                                       ig.Emit (OpCodes.Call, mi);
-                               }
-                       }
+                       if (emit_null_check)
+                               ig.MarkLabel (skip);
                }
 
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
@@ -5102,7 +5033,7 @@ namespace Mono.CSharp {
                        stmt.MutateHoistedGenericType (storey);
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        if (!ResolveVariable (ec))
                                return false;
@@ -5113,7 +5044,7 @@ namespace Mono.CSharp {
 
                        ec.EndFlowBranching ();
 
-                       ResolveReachability (ec);
+                       ok &= base.Resolve (ec);
 
                        if (TypeManager.void_dispose_void == null) {
                                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
@@ -5123,6 +5054,27 @@ namespace Mono.CSharp {
                        return ok;
                }
 
+               bool ResolveVariable (BlockContext ec)
+               {
+                       assign = new SimpleAssign (var, init, loc);
+                       assign = assign.ResolveStatement (ec);
+                       if (assign == null)
+                               return false;
+
+                       if (assign.Type == TypeManager.idisposable_type ||
+                               TypeManager.ImplementsInterface (assign.Type, TypeManager.idisposable_type)) {
+                               return true;
+                       }
+
+                       Expression e = Convert.ImplicitConversionStandard (ec, assign, TypeManager.idisposable_type, var.Location);
+                       if (e == null) {
+                               Error_IsNotConvertibleToIDisposable (ec, var);
+                               return false;
+                       }
+
+                       throw new NotImplementedException ("covariance?");
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Using target = (Using) t;
@@ -5149,7 +5101,7 @@ namespace Mono.CSharp {
                                {
                                }
 
-                               public void ResolveIncrement (EmitContext ec)
+                               public void ResolveIncrement (BlockContext ec)
                                {
                                        increment = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, this));
                                        increment.Resolve (ec);
@@ -5194,13 +5146,13 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
-                       public override bool Resolve (EmitContext ec)
+                       public override bool Resolve (BlockContext ec)
                        {
                                copy = new TemporaryVariable (for_each.expr.Type, loc);
                                copy.Resolve (ec);
 
                                int rank = length_exprs.Length;
-                               ArrayList list = new ArrayList (rank);
+                               Arguments list = new Arguments (rank);
                                for (int i = 0; i < rank; i++) {
                                        counter [i] = new ArrayCounter (loc);
                                        counter [i].ResolveIncrement (ec);                                      
@@ -5211,12 +5163,12 @@ namespace Mono.CSharp {
                                                lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc);
                                                lengths [i].Resolve (ec);
 
-                                               ArrayList args = new ArrayList (1);
+                                               Arguments args = new Arguments (1);
                                                args.Add (new Argument (new IntConstant (i, loc)));
                                                length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec);
                                        }
 
-                                       list.Add (counter [i]);
+                                       list.Add (new Argument (counter [i]));
                                }
 
                                access = new ElementAccess (copy, list).Resolve (ec);
@@ -5243,7 +5195,7 @@ namespace Mono.CSharp {
                                ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                                ec.CurrentBranching.CreateSibling ();
 
-                               for_each.variable = for_each.variable.ResolveLValue (ec, conv, loc);
+                               for_each.variable = for_each.variable.ResolveLValue (ec, conv);
                                if (for_each.variable == null)
                                        ok = false;
 
@@ -5350,7 +5302,7 @@ namespace Mono.CSharp {
                                        throw new NotImplementedException ();
                                }
 
-                               public override bool Resolve (EmitContext ec)
+                               public override bool Resolve (BlockContext ec)
                                {
                                        current = current.Resolve (ec);
                                        if (current == null)
@@ -5413,7 +5365,7 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
-                       bool GetEnumeratorFilter (EmitContext ec, MethodInfo mi)
+                       bool GetEnumeratorFilter (ResolveContext ec, MethodInfo mi)
                        {
                                Type return_type = mi.ReturnType;
 
@@ -5448,20 +5400,18 @@ namespace Mono.CSharp {
                                                        TypeManager.ienumerator_type, "Current", loc, TypeManager.object_type);
                                        }
 
-#if GMCS_SOURCE
                                        //
                                        // Prefer a generic enumerator over a non-generic one.
                                        //
-                                       if (return_type.IsInterface && return_type.IsGenericType) {
+                                       if (return_type.IsInterface && TypeManager.IsGenericType (return_type)) {
                                                enumerator_type = return_type;
                                                if (!FetchGetCurrent (ec, return_type))
                                                        get_current = new PropertyExpr (
-                                                               ec.ContainerType, TypeManager.ienumerator_getcurrent, loc);
+                                                               ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
                                                if (!FetchMoveNext (return_type))
                                                        move_next = TypeManager.bool_movenext_void;
                                                return true;
                                        }
-#endif
 
                                        if (return_type.IsInterface ||
                                            !FetchMoveNext (return_type) ||
@@ -5469,7 +5419,7 @@ namespace Mono.CSharp {
                                                enumerator_type = return_type;
                                                move_next = TypeManager.bool_movenext_void;
                                                get_current = new PropertyExpr (
-                                                       ec.ContainerType, TypeManager.ienumerator_getcurrent, loc);
+                                                       ec.CurrentType, TypeManager.ienumerator_getcurrent, loc);
                                                return true;
                                        }
                                } else {
@@ -5479,7 +5429,7 @@ namespace Mono.CSharp {
                                        //
 
                                        if (TypeManager.HasElementType (return_type) || !FetchMoveNext (return_type) || !FetchGetCurrent (ec, return_type)) {
-                                               Report.Error (202, loc, "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property",
+                                               ec.Report.Error (202, loc, "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property",
                                                        TypeManager.CSharpName (return_type), TypeManager.CSharpSignature (mi));
                                                return false;
                                        }
@@ -5495,13 +5445,12 @@ namespace Mono.CSharp {
                        //
                        bool FetchMoveNext (Type t)
                        {
-                               MemberList move_next_list;
-
-                               move_next_list = TypeContainer.FindMembers (
-                                       t, MemberTypes.Method,
+                               MemberInfo[] move_next_list = TypeManager.MemberLookup (null, null, t,
+                                       MemberTypes.Method,
                                        BindingFlags.Public | BindingFlags.Instance,
-                                       Type.FilterName, "MoveNext");
-                               if (move_next_list.Count == 0)
+                                       "MoveNext", null);
+
+                               if (move_next_list == null)
                                        return false;
 
                                foreach (MemberInfo m in move_next_list){
@@ -5520,10 +5469,10 @@ namespace Mono.CSharp {
                        //
                        // Retrieves a `public T get_Current ()' method from the Type `t'
                        //
-                       bool FetchGetCurrent (EmitContext ec, Type t)
+                       bool FetchGetCurrent (ResolveContext ec, Type t)
                        {
-                               PropertyExpr pe = Expression.MemberLookup (
-                                       ec.ContainerType, t, "Current", MemberTypes.Property,
+                               PropertyExpr pe = Expression.MemberLookup (ec.Compiler,
+                                       ec.CurrentType, t, "Current", MemberTypes.Property,
                                        Expression.AllBindingFlags, loc) as PropertyExpr;
                                if (pe == null)
                                        return false;
@@ -5532,38 +5481,13 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       // 
-                       // Retrieves a `public void Dispose ()' method from the Type `t'
-                       //
-                       static MethodInfo FetchMethodDispose (Type t)
-                       {
-                               MemberList dispose_list;
-
-                               dispose_list = TypeContainer.FindMembers (
-                                       t, MemberTypes.Method,
-                                       BindingFlags.Public | BindingFlags.Instance,
-                                       Type.FilterName, "Dispose");
-                               if (dispose_list.Count == 0)
-                                       return null;
-
-                               foreach (MemberInfo m in dispose_list){
-                                       MethodInfo mi = (MethodInfo) m;
-
-                                       if (TypeManager.GetParameterData (mi).Count == 0){
-                                               if (mi.ReturnType == TypeManager.void_type)
-                                                       return mi;
-                                       }
-                               }
-                               return null;
-                       }
-
-                       void Error_Enumerator ()
+                       void Error_Enumerator (BlockContext ec)
                        {
                                if (enumerator_found) {
                                        return;
                                }
 
-                           Report.Error (1579, loc,
+                           ec.Report.Error (1579, loc,
                                        "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `GetEnumerator' or is not accessible",
                                        TypeManager.CSharpName (expr.Type));
                        }
@@ -5581,10 +5505,10 @@ namespace Mono.CSharp {
                                return base_method != m;
                        }
 
-                       bool TryType (EmitContext ec, Type t)
+                       bool TryType (ResolveContext ec, Type t)
                        {
-                               MethodGroupExpr mg = Expression.MemberLookup (
-                                       ec.ContainerType, t, "GetEnumerator", MemberTypes.Method,
+                               MethodGroupExpr mg = Expression.MemberLookup (ec.Compiler,
+                                       ec.CurrentType, t, "GetEnumerator", MemberTypes.Method,
                                        Expression.AllBindingFlags, loc) as MethodGroupExpr;
                                if (mg == null)
                                        return false;
@@ -5615,8 +5539,8 @@ namespace Mono.CSharp {
                                                                continue;
 
                                                        MethodBase mb = TypeManager.DropGenericMethodArguments (mi);
-                                                       Report.SymbolRelatedToPreviousError (t);
-                                                       Report.Error(1640, loc, "foreach statement cannot operate on variables of type `{0}' " +
+                                                       ec.Report.SymbolRelatedToPreviousError (t);
+                                                       ec.Report.Error(1640, loc, "foreach statement cannot operate on variables of type `{0}' " +
                                                                     "because it contains multiple implementation of `{1}'. Try casting to a specific implementation",
                                                                     TypeManager.CSharpName (t), TypeManager.CSharpSignature (mb));
                                                        return false;
@@ -5628,9 +5552,9 @@ namespace Mono.CSharp {
                                                            TypeManager.ImplementsInterface (result.DeclaringType, mi.DeclaringType))
                                                                continue;
 
-                                                       Report.SymbolRelatedToPreviousError (result);
-                                                       Report.SymbolRelatedToPreviousError (mi);
-                                                       Report.Warning (278, 2, loc, "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'",
+                                                       ec.Report.SymbolRelatedToPreviousError (result);
+                                                       ec.Report.SymbolRelatedToPreviousError (mi);
+                                                       ec.Report.Warning (278, 2, loc, "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'",
                                                                        TypeManager.CSharpName (t), "enumerable", TypeManager.CSharpSignature (result), TypeManager.CSharpSignature (mi));
                                                        return false;
                                                }
@@ -5664,18 +5588,18 @@ namespace Mono.CSharp {
                                }
 
                                return false;
-                       }               
+                       }
 
-                       bool ProbeCollectionType (EmitContext ec, Type t)
+                       bool ProbeCollectionType (ResolveContext ec, Type t)
                        {
-                               int errors = Report.Errors;
+                               int errors = ec.Report.Errors;
                                for (Type tt = t; tt != null && tt != TypeManager.object_type;){
                                        if (TryType (ec, tt))
                                                return true;
                                        tt = tt.BaseType;
                                }
 
-                               if (Report.Errors > errors)
+                               if (ec.Report.Errors > errors)
                                        return false;
 
                                //
@@ -5690,18 +5614,15 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       public override bool Resolve (EmitContext ec)
+                       public override bool Resolve (BlockContext ec)
                        {
                                enumerator_type = TypeManager.ienumerator_type;
 
                                if (!ProbeCollectionType (ec, expr.Type)) {
-                                       Error_Enumerator ();
+                                       Error_Enumerator (ec);
                                        return false;
                                }
 
-                               bool is_disposable = !enumerator_type.IsSealed ||
-                                       TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type);
-
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
                                        // Infer implicitly typed local variable from foreach enumerable type
@@ -5734,11 +5655,16 @@ namespace Mono.CSharp {
                                Statement block = new CollectionForeachStatement (
                                        var_type.Type, variable, get_current, statement, loc);
 
-                               loop = new While (move_next_expr, block, loc);
+                               loop = new While (new BooleanExpression (move_next_expr), block, loc);
+
+
+                               bool implements_idisposable = TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type);
+                               if (implements_idisposable || !enumerator_type.IsSealed) {
+                                       wrapper = new DisposableWrapper (this, implements_idisposable);
+                               } else {
+                                       wrapper = new NonDisposableWrapper (this);
+                               }
 
-                               wrapper = is_disposable ?
-                                       (Statement) new DisposableWrapper (this) :
-                                       (Statement) new NonDisposableWrapper (this);
                                return wrapper.Resolve (ec);
                        }
 
@@ -5760,7 +5686,7 @@ namespace Mono.CSharp {
                                        throw new NotSupportedException ();
                                }
 
-                               public override bool Resolve (EmitContext ec)
+                               public override bool Resolve (BlockContext ec)
                                {
                                        return parent.ResolveLoop (ec);
                                }
@@ -5777,12 +5703,15 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       class DisposableWrapper : ExceptionStatement {
+                       sealed class DisposableWrapper : ExceptionStatement
+                       {
                                CollectionForeach parent;
+                               bool implements_idisposable;
 
-                               internal DisposableWrapper (CollectionForeach parent)
+                               internal DisposableWrapper (CollectionForeach parent, bool implements)
                                {
                                        this.parent = parent;
+                                       this.implements_idisposable = implements;
                                }
 
                                protected override void CloneTo (CloneContext clonectx, Statement target)
@@ -5790,7 +5719,7 @@ namespace Mono.CSharp {
                                        throw new NotSupportedException ();
                                }
 
-                               public override bool Resolve (EmitContext ec)
+                               public override bool Resolve (BlockContext ec)
                                {
                                        bool ok = true;
 
@@ -5801,7 +5730,7 @@ namespace Mono.CSharp {
 
                                        ec.EndFlowBranching ();
 
-                                       ResolveReachability (ec);
+                                       ok &= base.Resolve (ec);
 
                                        if (TypeManager.void_dispose_void == null) {
                                                TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod (
@@ -5822,7 +5751,30 @@ namespace Mono.CSharp {
 
                                protected override void EmitFinallyBody (EmitContext ec)
                                {
-                                       parent.EmitFinallyBody (ec);
+                                       Expression instance = parent.enumerator;
+                                       if (!TypeManager.IsValueType (parent.enumerator_type)) {
+                                               ILGenerator ig = ec.ig;
+
+                                               parent.enumerator.Emit (ec);
+
+                                               Label call_dispose = ig.DefineLabel ();
+
+                                               if (!implements_idisposable) {
+                                                       ec.ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
+                                                       LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type);
+                                                       temp.Store (ec);
+                                                       temp.Emit (ec);
+                                                       instance = temp;
+                                               }
+                                               
+                                               ig.Emit (OpCodes.Brtrue_S, call_dispose);
+
+                                               // using 'endfinally' to empty the evaluation stack
+                                               ig.Emit (OpCodes.Endfinally);
+                                               ig.MarkLabel (call_dispose);
+                                       }
+
+                                       Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, null, loc);
                                }
 
                                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
@@ -5831,7 +5783,7 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       bool ResolveLoop (EmitContext ec)
+                       bool ResolveLoop (BlockContext ec)
                        {
                                return loop.Resolve (ec);
                        }
@@ -5846,37 +5798,6 @@ namespace Mono.CSharp {
                                loop.Emit (ec);
                        }
 
-                       void EmitFinallyBody (EmitContext ec)
-                       {
-                               ILGenerator ig = ec.ig;
-
-                               if (TypeManager.IsStruct (enumerator_type)) {
-                                       MethodInfo mi = FetchMethodDispose (enumerator_type);
-                                       if (mi != null) {
-                                               enumerator.AddressOf (ec, AddressOp.Load);
-                                               ig.Emit (OpCodes.Call, mi);
-                                       } else {
-                                               enumerator.Emit (ec);
-                                               ig.Emit (OpCodes.Box, enumerator_type);
-                                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                                       }
-                               } else {
-                                       Label call_dispose = ig.DefineLabel ();
-
-                                       enumerator.Emit (ec);
-                                       ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                                       ig.Emit (OpCodes.Dup);
-                                       ig.Emit (OpCodes.Brtrue_S, call_dispose);
-
-                                       // 'endfinally' empties the evaluation stack, and can appear anywhere inside a finally block
-                                       // (Partition III, Section 3.35)
-                                       ig.Emit (OpCodes.Endfinally);
-
-                                       ig.MarkLabel (call_dispose);
-                                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               }
-                       }
-
                        public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                        {
                                enumerator_type = storey.MutateType (enumerator_type);
@@ -5904,14 +5825,14 @@ namespace Mono.CSharp {
                        get { return statement; }
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (BlockContext ec)
                {
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return false;
 
                        if (expr.IsNull) {
-                               Report.Error (186, loc, "Use of null is not valid in this context");
+                               ec.Report.Error (186, loc, "Use of null is not valid in this context");
                                return false;
                        }
 
@@ -5921,7 +5842,7 @@ namespace Mono.CSharp {
                                statement = new ArrayForeach (this, expr.Type.GetArrayRank ());
                        } else {
                                if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
-                                       Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
+                                       ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
                                                expr.ExprClassName);
                                        return false;
                                }