Fixed the build
[mono.git] / mcs / mcs / statement.cs
index 56b0d24f1e6f15a52f9e56e6b0142f1fdf86eb12..82a35ce629e4a3e93a2ac4f2c26bc69463fffc6a 100644 (file)
@@ -85,9 +85,88 @@ namespace Mono.CSharp {
                {
                        ec.Mark (loc, true);
                        DoEmit (ec);
-               }               
+               }
+
+               //
+               // This routine must be overrided in derived classes and make copies
+               // of all the data that might be modified if resolved
+               // 
+               protected virtual void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       throw new Exception (String.Format ("Statement.CloneTo not implemented for {0}", this.GetType ()));
+               }
+               
+               public Statement Clone (CloneContext clonectx)
+               {
+                       Statement s = (Statement) this.MemberwiseClone ();
+                       if (s is Block)
+                               clonectx.AddBlockMap ((Block) this, (Block) s);
+                       
+                       CloneTo (clonectx, s);
+                       return s;
+               }
+
+               public Statement PerformClone ()
+               {
+                       CloneContext clonectx = new CloneContext ();
+
+                       return Clone (clonectx);
+               }
+
        }
 
+       //
+       // 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;
+               }
+
+               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 () {}
@@ -239,11 +318,20 @@ namespace Mono.CSharp {
                                ig.MarkLabel (false_target);
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       If target = (If) t;
+
+                       target.expr = expr.Clone (clonectx);
+                       target.TrueStatement = TrueStatement.Clone (clonectx);
+                       target.FalseStatement = FalseStatement.Clone (clonectx);
+               }
        }
 
        public class Do : Statement {
                public Expression expr;
-               public readonly Statement  EmbeddedStatement;
+               public Statement  EmbeddedStatement;
                bool infinite;
                
                public Do (Statement statement, Expression boolExpr, Location l)
@@ -316,11 +404,19 @@ namespace Mono.CSharp {
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Do target = (Do) t;
+
+                       target.EmbeddedStatement = EmbeddedStatement.Clone (clonectx);
+                       target.expr = expr.Clone (clonectx);
+               }
        }
 
        public class While : Statement {
                public Expression expr;
-               public readonly Statement Statement;
+               public Statement Statement;
                bool infinite, empty;
                
                public While (Expression boolExpr, Statement statement, Location l)
@@ -413,13 +509,21 @@ namespace Mono.CSharp {
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       While target = (While) t;
+
+                       target.expr = expr.Clone (clonectx);
+                       target.Statement = Statement.Clone (clonectx);
+               }
        }
 
        public class For : Statement {
                Expression Test;
-               readonly Statement InitStatement;
-               readonly Statement Increment;
-               public readonly Statement Statement;
+               Statement InitStatement;
+               Statement Increment;
+               public Statement Statement;
                bool infinite, empty;
                
                public For (Statement initStatement,
@@ -542,6 +646,19 @@ namespace Mono.CSharp {
                        ec.LoopBegin = old_begin;
                        ec.LoopEnd = old_end;
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       For target = (For) t;
+
+                       if (InitStatement != null)
+                               target.InitStatement = InitStatement.Clone (clonectx);
+                       if (Test != null)
+                               target.Test = Test.Clone (clonectx);
+                       if (Increment != null)
+                               target.Increment = Increment.Clone (clonectx);
+                       target.Statement = Statement.Clone (clonectx);
+               }
        }
        
        public class StatementExpression : Statement {
@@ -569,6 +686,13 @@ namespace Mono.CSharp {
                {
                        return "StatementExpression (" + expr + ")";
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       StatementExpression target = (StatementExpression) t;
+
+                       target.expr = (ExpressionStatement) expr.Clone (clonectx);
+               }
        }
 
        /// <summary>
@@ -628,7 +752,7 @@ namespace Mono.CSharp {
                        unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
                        if (unwind_protect)
                                ec.NeedReturnLabel ();
-                       ec.CurrentBranching.CurrentUsageVector.Return ();
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return errors == Report.Errors;
                }
                
@@ -646,6 +770,13 @@ namespace Mono.CSharp {
                        else
                                ec.ig.Emit (OpCodes.Ret);
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Return target = (Return) t;
+
+                       target.Expr = Expr.Clone (clonectx);
+               }
        }
 
        public class Goto : Statement {
@@ -852,6 +983,14 @@ namespace Mono.CSharp {
                {
                        ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       GotoCase target = (GotoCase) t;
+
+                       target.expr = expr.Clone (clonectx);
+                       target.sl = sl.Clone (clonectx);
+               }
        }
        
        public class Throw : Statement {
@@ -865,7 +1004,7 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Throw ();
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
 
                        if (expr != null){
                                expr = expr.Resolve (ec);
@@ -915,6 +1054,13 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Throw);
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Throw target = (Throw) t;
+
+                       target.expr = expr.Clone (clonectx);
+               }
        }
 
        public class Break : Statement {
@@ -1067,7 +1213,7 @@ namespace Mono.CSharp {
                                ec.DefineLocalVariable (name, builder);
                }
 
-               public bool IsThisAssigned (EmitContext ec, Location loc)
+               public bool IsThisAssigned (EmitContext ec)
                {
                        if (VariableInfo == null)
                                throw new Exception ();
@@ -1075,7 +1221,7 @@ namespace Mono.CSharp {
                        if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
                                return true;
 
-                       return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, loc);
+                       return VariableInfo.TypeInfo.IsFullyInitialized (ec.CurrentBranching, VariableInfo, ec.loc);
                }
 
                public bool IsAssigned (EmitContext ec)
@@ -1102,7 +1248,7 @@ namespace Mono.CSharp {
                        }
 
                        if (VariableType.IsAbstract && VariableType.IsSealed) {
-                               FieldMember.Error_VariableOfStaticClass (Location, Name, VariableType);
+                               FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType);
                                return false;
                        }
 
@@ -1259,8 +1405,14 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Ldloca, builder);
                        }
                }
+
+               public LocalInfo Clone (CloneContext clonectx)
+               {
+                       // Only this kind is created by the parser.
+                       return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+               }
        }
-               
+
        /// <summary>
        ///   Block represents a C# block.
        /// </summary>
@@ -1844,8 +1996,9 @@ namespace Mono.CSharp {
 
                public VariableMap ParameterMap {
                        get {
-                               if ((flags & Flags.VariablesInitialized) == 0)
+                               if ((flags & Flags.VariablesInitialized) == 0){
                                        throw new Exception ("Variables have not been initialized yet");
+                               }
 
                                return param_map;
                        }
@@ -1973,12 +2126,12 @@ namespace Mono.CSharp {
                                                                continue;
                                                        }
 
-                                                       e = ce.ImplicitConversionRequired (variable_type, vi.Location);
-                                                       if (e == null)
-                                                               continue;
-
-                                                       if (!variable_type.IsValueType && variable_type != TypeManager.string_type && !ce.IsDefaultValue) {
-                                                               Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+                                                       e = ce.ConvertImplicitly (variable_type);
+                                                       if (e == null) {
+                                                               if (!variable_type.IsValueType && variable_type != TypeManager.string_type && !ce.IsDefaultValue)
+                                                                       Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+                                                               else
+                                                                       ce.Error_ValueCannotBeConverted (null, vi.Location, variable_type, false);
                                                                continue;
                                                        }
 
@@ -2152,6 +2305,9 @@ namespace Mono.CSharp {
                        Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
                                      ec.CurrentBranching, statement_count, num_statements);
 
+                       if (!ok)
+                               return false;
+
                        while (ec.CurrentBranching is FlowBranchingLabeled)
                                ec.EndFlowBranching ();
 
@@ -2163,7 +2319,7 @@ namespace Mono.CSharp {
                        // initializer, then we must initialize all of the struct's fields.
                        if ((flags & Flags.IsToplevel) != 0 && 
                            !Toplevel.IsThisAssigned (ec) &&
-                           !vector.Reachability.AlwaysThrows)
+                           !vector.Reachability.IsUnreachable)
                                ok = false;
 
                        if ((labels != null) && (RootContext.WarningLevel >= 2)) {
@@ -2273,6 +2429,42 @@ namespace Mono.CSharp {
                {
                        return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation);
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Block target = (Block) t;
+
+                       if (Parent != null)
+                               target.Parent = clonectx.LookupBlock (Parent);
+                       
+                       target.statements = new ArrayList ();
+                       if (target.children != null){
+                               target.children = new ArrayList ();
+                               foreach (Block b in children){
+                                       Block newblock = (Block) b.Clone (clonectx);
+
+                                       target.children.Add (newblock);
+                               }
+                               
+                       }
+
+                       foreach (Statement s in statements)
+                               target.statements.Add (s.Clone (clonectx));
+
+                       if (variables != null){
+                               target.variables = new Hashtable ();
+
+                               foreach (DictionaryEntry de in variables){
+                                       LocalInfo newlocal = ((LocalInfo) de.Value).Clone (clonectx);
+                                       target.variables [de.Key] = newlocal;
+                                       clonectx.AddVariableMap ((LocalInfo) de.Value, newlocal);
+                               }
+                       }
+
+                       //
+                       // TODO: labels, switch_block, constants (?), anonymous_children
+                       //
+               }
        }
 
        //
@@ -2546,7 +2738,7 @@ namespace Mono.CSharp {
 
                public bool IsThisAssigned (EmitContext ec)
                {
-                       return this_variable == null || this_variable.IsThisAssigned (ec, loc);
+                       return this_variable == null || this_variable.IsThisAssigned (ec);
                }
 
                public bool ResolveMeta (EmitContext ec, Parameters ip)
@@ -2709,18 +2901,26 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public void Erorr_AlreadyOccurs ()
+               public void Erorr_AlreadyOccurs (Type switchType, SwitchLabel collisionWith)
                {
                        string label;
                        if (converted == null)
                                label = "default";
                        else if (converted == NullStringCase)
                                label = "null";
+                       else if (TypeManager.IsEnumType (switchType)) 
+                               label = TypeManager.CSharpEnumValue (switchType, converted);
                        else
                                label = converted.ToString ();
-
+                       
+                       Report.SymbolRelatedToPreviousError (collisionWith.loc, null);
                        Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
                }
+
+               public SwitchLabel Clone (CloneContext clonectx)
+               {
+                       return new SwitchLabel (label.Clone (clonectx), loc);
+               }
        }
 
        public class SwitchSection {
@@ -2733,10 +2933,20 @@ namespace Mono.CSharp {
                        Labels = labels;
                        Block = block;
                }
+
+               public SwitchSection Clone (CloneContext clonectx)
+               {
+                       ArrayList cloned_labels = new ArrayList ();
+
+                       foreach (SwitchLabel sl in cloned_labels)
+                               cloned_labels.Add (sl.Clone (clonectx));
+                       
+                       return new SwitchSection (cloned_labels, clonectx.LookupBlock (Block));
+               }
        }
        
        public class Switch : Statement {
-               public readonly ArrayList Sections;
+               public ArrayList Sections;
                public Expression Expr;
 
                /// <summary>
@@ -2807,7 +3017,7 @@ namespace Mono.CSharp {
                //
                Expression SwitchGoverningType (EmitContext ec, Expression expr)
                {
-                       Type t = expr.Type;
+                       Type t = TypeManager.DropGenericTypeArguments (expr.Type);
 
                        if (t == TypeManager.byte_type ||
                            t == TypeManager.sbyte_type ||
@@ -2891,7 +3101,7 @@ namespace Mono.CSharp {
                                foreach (SwitchLabel sl in ss.Labels){
                                        if (sl.Label == null){
                                                if (default_section != null){
-                                                       sl.Erorr_AlreadyOccurs ();
+                                                       sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)default_section.Labels [0]);
                                                        error = true;
                                                }
                                                default_section = ss;
@@ -2907,7 +3117,7 @@ namespace Mono.CSharp {
                                        try {
                                                Elements.Add (key, sl);
                                        } catch (ArgumentException) {
-                                               sl.Erorr_AlreadyOccurs ();
+                                               sl.Erorr_AlreadyOccurs (SwitchType, (SwitchLabel)Elements [key]);
                                                error = true;
                                        }
                                }
@@ -3219,6 +3429,11 @@ namespace Mono.CSharp {
                        bool pending_goto_end = false;
                        bool null_marked = false;
                        bool null_found;
+                       int section_count = Sections.Count;
+
+                       // TODO: implement switch optimization for string by using Hashtable
+                       //if (SwitchType == TypeManager.string_type && section_count > 7)
+                       //      Console.WriteLine ("Switch optimization possible " + loc);
 
                        ig.Emit (OpCodes.Ldloc, val);
                        
@@ -3228,10 +3443,9 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Brfalse, default_target);
                        
                        ig.Emit (OpCodes.Ldloc, val);
-                       ig.Emit (OpCodes.Call, TypeManager.string_isinterneted_string);
+                       ig.Emit (OpCodes.Call, TypeManager.string_isinterned_string);
                        ig.Emit (OpCodes.Stloc, val);
 
-                       int section_count = Sections.Count;
                        for (int section = 0; section < section_count; section++){
                                SwitchSection ss = (SwitchSection) Sections [section];
 
@@ -3339,6 +3553,11 @@ namespace Mono.CSharp {
                        // Validate switch.
                        SwitchType = new_expr.Type;
 
+                       if (RootContext.Version == LanguageVersion.ISO_1 && SwitchType == TypeManager.bool_type) {
+                               Report.FeatureIsNotISO1 (loc, "switch expression of boolean type");
+                               return false;
+                       }
+
                        if (!CheckSwitch (ec))
                                return false;
 
@@ -3447,6 +3666,17 @@ namespace Mono.CSharp {
                        ec.LoopEnd = old_end;
                        ec.Switch = old_switch;
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Switch target = (Switch) t;
+
+                       target.Expr = Expr.Clone (clonectx);
+                       target.Sections = new ArrayList ();
+                       foreach (SwitchSection ss in Sections){
+                               target.Sections.Add (ss.Clone (clonectx));
+                       }
+               }
        }
 
        public abstract class ExceptionStatement : Statement
@@ -3507,15 +3737,11 @@ namespace Mono.CSharp {
 
                        ResolveFinally (branching);
 
-                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
-                       if (!reachability.AlwaysReturns) {
-                               // Unfortunately, System.Reflection.Emit automatically emits
-                               // a leave to the end of the finally block.
-                               // This is a problem if `returns' is true since we may jump
-                               // to a point after the end of the method.
-                               // As a workaround, emit an explicit ret here.
-                               ec.NeedReturnLabel ();
-                       }
+                       ec.EndFlowBranching ();
+
+                       // System.Reflection.Emit automatically emits a 'leave' to the end of the finally block.
+                       // So, ensure there's some IL code after the finally block.
+                       ec.NeedReturnLabel ();
 
                        // Avoid creating libraries that reference the internal
                        // mcs NullType:
@@ -3553,10 +3779,18 @@ namespace Mono.CSharp {
                        temp.Emit (ec);
                        ec.ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
                }
+               
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Lock target = (Lock) t;
+
+                       target.expr = expr.Clone (clonectx);
+                       target.Statement = Statement.Clone (clonectx);
+               }
        }
 
        public class Unchecked : Statement {
-               public readonly Block Block;
+               public Block Block;
                
                public Unchecked (Block b)
                {
@@ -3575,10 +3809,17 @@ namespace Mono.CSharp {
                        using (ec.With (EmitContext.Flags.AllCheckStateFlags, false))
                                Block.Emit (ec);
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Unchecked target = (Unchecked) t;
+
+                       target.Block = clonectx.LookupBlock (Block);
+               }
        }
 
        public class Checked : Statement {
-               public readonly Block Block;
+               public Block Block;
                
                public Checked (Block b)
                {
@@ -3597,10 +3838,17 @@ namespace Mono.CSharp {
                        using (ec.With (EmitContext.Flags.AllCheckStateFlags, true))
                                Block.Emit (ec);
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Checked target = (Checked) t;
+
+                       target.Block = clonectx.LookupBlock (Block);
+               }
        }
 
        public class Unsafe : Statement {
-               public readonly Block Block;
+               public Block Block;
 
                public Unsafe (Block b)
                {
@@ -3619,6 +3867,12 @@ namespace Mono.CSharp {
                        using (ec.With (EmitContext.Flags.InUnsafe, true))
                                Block.Emit (ec);
                }
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Unsafe target = (Unsafe) t;
+
+                       target.Block = clonectx.LookupBlock (Block);
+               }
        }
 
        // 
@@ -3906,12 +4160,23 @@ namespace Mono.CSharp {
                                data [i].EmitExit (ec);
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Fixed target = (Fixed) t;
+
+                       target.type = type.Clone (clonectx);
+                       target.declarators = new ArrayList ();
+                       foreach (LocalInfo var in declarators)
+                               target.declarators.Add (clonectx.LookupVariable (var));
+                       target.statement = statement.Clone (clonectx);
+               }
        }
        
        public class Catch : Statement {
                public readonly string Name;
-               public readonly Block  Block;
-               public readonly Block  VarBlock;
+               public Block  Block;
+               public Block  VarBlock;
 
                Expression type_expr;
                Type type;
@@ -3997,12 +4262,21 @@ namespace Mono.CSharp {
                                return true;
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Catch target = (Catch) t;
+
+                       target.type_expr = type_expr.Clone (clonectx);
+                       target.Block = clonectx.LookupBlock (Block);
+                       target.VarBlock = clonectx.LookupBlock (VarBlock);
+               }
        }
 
        public class Try : ExceptionStatement {
-               public readonly Block Fini, Block;
-               public readonly ArrayList Specific;
-               public readonly Catch General;
+               public Block Fini, Block;
+               public ArrayList Specific;
+               public Catch General;
 
                bool need_exc_block;
                
@@ -4112,20 +4386,15 @@ namespace Mono.CSharp {
                        } else
                                emit_finally = Fini != null;
 
-                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
+                       ec.EndFlowBranching ();
 
-                       FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
+                       // System.Reflection.Emit automatically emits a 'leave' to the end of the finally block.
+                       // So, ensure there's some IL code after the finally block.
+                       ec.NeedReturnLabel ();
 
-                       Report.Debug (1, "END OF TRY", ec.CurrentBranching, reachability, vector, f_vector);
+                       FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
 
-                       if (!reachability.AlwaysReturns) {
-                               // Unfortunately, System.Reflection.Emit automatically emits
-                               // a leave to the end of the finally block.  This is a problem
-                               // if `returns' is true since we may jump to a point after the
-                               // end of the method.
-                               // As a workaround, emit an explicit ret here.
-                               ec.NeedReturnLabel ();
-                       }
+                       Report.Debug (1, "END OF TRY", ec.CurrentBranching, vector, f_vector);
 
                        return ok;
                }
@@ -4161,6 +4430,22 @@ namespace Mono.CSharp {
                                return General != null || Specific.Count > 0;
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Try target = (Try) t;
+
+                       target.Block = clonectx.LookupBlock (Block);
+                       if (Fini != null)
+                               target.Fini = clonectx.LookupBlock (Fini);
+                       if (General != null)
+                               target.General = (Catch) General.Clone (clonectx);
+                       if (Specific != null){
+                               target.Specific = new ArrayList ();
+                               foreach (Catch c in Specific)
+                                       target.Specific.Add (c.Clone (clonectx));
+                       }
+               }
        }
 
        public class Using : ExceptionStatement {
@@ -4439,15 +4724,12 @@ namespace Mono.CSharp {
                        }
 
                        ResolveFinally (branching);
-                       FlowBranching.Reachability reachability = ec.EndFlowBranching ();
 
-                       if (!reachability.AlwaysReturns) {
-                               // Unfortunately, System.Reflection.Emit automatically emits a leave
-                               // to the end of the finally block.  This is a problem if `returns'
-                               // is true since we may jump to a point after the end of the method.
-                               // As a workaround, emit an explicit ret here.
-                               ec.NeedReturnLabel ();
-                       }
+                       ec.EndFlowBranching ();
+
+                       // System.Reflection.Emit automatically emits a 'leave' to the end of the finally block.
+                       // So, ensure there's some IL code after the finally block.
+                       ec.NeedReturnLabel ();
 
                        return true;
                }
@@ -4467,6 +4749,18 @@ namespace Mono.CSharp {
                        else if (expression_or_block is Expression)
                                EmitExpressionFinally (ec);
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Using target = (Using) t;
+
+                       if (expression_or_block is Expression)
+                               target.expression_or_block = ((Expression) expression_or_block).Clone (clonectx);
+                       else
+                               target.expression_or_block = ((Statement) expression_or_block).Clone (clonectx);
+                       
+                       target.Statement = Statement.Clone (clonectx);
+               }
        }
 
        /// <summary>
@@ -4917,15 +5211,20 @@ namespace Mono.CSharp {
                                                        if (!TypeManager.IsGenericType (mi.ReturnType))
                                                                continue;
 
+                                                       MethodBase mb = TypeManager.DropGenericMethodArguments (mi);
                                                        Report.SymbolRelatedToPreviousError (t);
                                                        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 (mi));
+                                                                    "because it contains multiple implementation of `{1}'. Try casting to a specific implementation",
+                                                                    TypeManager.CSharpName (t), TypeManager.CSharpSignature (mb));
                                                        return false;
                                                }
 
                                                // Always prefer generics enumerators
                                                if (!TypeManager.IsGenericType (mi.ReturnType)) {
+                                                       if (TypeManager.ImplementsInterface (mi.DeclaringType, result.DeclaringType) ||
+                                                           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}'",
@@ -5157,5 +5456,15 @@ namespace Mono.CSharp {
                                statement.Emit (ec);
                        }
                }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       Foreach target = (Foreach) t;
+
+                       target.type = type.Clone (clonectx);
+                       target.variable = variable.Clone (clonectx);
+                       target.expr = expr.Clone (clonectx);
+                       target.statement = statement.Clone (clonectx);
+               }
        }
 }