Merge pull request #438 from mattleibow/master
[mono.git] / mcs / mcs / statement.cs
index cb1da27d81feeb5330a5fcd87999fd30db8392e6..1742956bda77768ed2ec64df7130610f19398150 100644 (file)
@@ -49,13 +49,21 @@ namespace Mono.CSharp {
                        // in unreachable code, for instance.
                        //
 
-                       if (warn)
+                       bool unreachable = false;
+                       if (warn && !ec.UnreachableReported) {
+                               ec.UnreachableReported = true;
+                               unreachable = true;
                                ec.Report.Warning (162, 2, loc, "Unreachable code detected");
+                       }
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        bool ok = Resolve (ec);
                        ec.KillFlowBranching ();
 
+                       if (unreachable) {
+                               ec.UnreachableReported = false;
+                       }
+
                        return ok;
                }
                                
@@ -281,11 +289,16 @@ namespace Mono.CSharp {
                public Expression expr;
                public Statement  EmbeddedStatement;
 
-               public Do (Statement statement, BooleanExpression bool_expr, Location l)
+               public Do (Statement statement, BooleanExpression bool_expr, Location doLocation, Location whileLocation)
                {
                        expr = bool_expr;
                        EmbeddedStatement = statement;
-                       loc = l;
+                       loc = doLocation;
+                       WhileLocation = whileLocation;
+               }
+
+               public Location WhileLocation {
+                       get; private set;
                }
 
                public override bool Resolve (BlockContext ec)
@@ -332,7 +345,7 @@ namespace Mono.CSharp {
                        ec.MarkLabel (ec.LoopBegin);
 
                        // Mark start of while condition
-                       ec.Mark (expr.Location);
+                       ec.Mark (WhileLocation);
 
                        //
                        // Dead code elimination
@@ -461,7 +474,7 @@ namespace Mono.CSharp {
                        
                                ec.MarkLabel (ec.LoopBegin);
 
-                               ec.Mark (expr.Location);
+                               ec.Mark (loc);
                                expr.EmitBranchable (ec, while_loop, true);
                                
                                ec.MarkLabel (ec.LoopEnd);
@@ -784,12 +797,10 @@ namespace Mono.CSharp {
 
                public sealed override bool Resolve (BlockContext ec)
                {
-                       if (!DoResolve (ec))
-                               return false;
-
+                       var res = DoResolve (ec);
                        unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this);
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
-                       return true;
+                       return res;
                }
        }
 
@@ -880,7 +891,6 @@ namespace Mono.CSharp {
                                                        return true;
                                                }
 
-                                               // TODO: Better error message
                                                if (async_type.Kind == MemberKind.Void) {
                                                        ec.Report.Error (127, loc,
                                                                "`{0}': A return keyword must not be followed by any expression when method returns void",
@@ -911,6 +921,15 @@ namespace Mono.CSharp {
                                                }
                                        }
                                } else {
+                                       // Same error code as .NET but better error message
+                                       if (block_return_type.Kind == MemberKind.Void) {
+                                               ec.Report.Error (127, loc,
+                                                       "`{0}': A return keyword must not be followed by any expression when delegate returns void",
+                                                       am.GetSignatureForError ());
+
+                                               return false;
+                                       }
+
                                        var l = am as AnonymousMethodBody;
                                        if (l != null && l.ReturnTypeInference != null && expr != null) {
                                                l.ReturnTypeInference.AddCommonTypeBound (expr.Type);
@@ -952,10 +971,9 @@ namespace Mono.CSharp {
                                                async_return.EmitAssign (ec);
 
                                                ec.EmitEpilogue ();
-
-                                               ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, async_body.BodyEnd);
                                        }
 
+                                       ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, async_body.BodyEnd);
                                        return;
                                }
 
@@ -1215,9 +1233,9 @@ namespace Mono.CSharp {
                                res = c;
                        } else {
                                TypeSpec type = ec.Switch.SwitchType;
-                               res = c.TryReduce (ec, type, c.Location);
+                               res = c.Reduce (ec, type);
                                if (res == null) {
-                                       c.Error_ValueCannotBeConverted (ec, loc, type, true);
+                                       c.Error_ValueCannotBeConverted (ec, type, true);
                                        return false;
                                }
 
@@ -1438,6 +1456,7 @@ namespace Mono.CSharp {
                protected FullNamedExpression type_expr;
                protected LocalVariable li;
                protected List<Declarator> declarators;
+               TypeSpec type;
 
                public BlockVariableDeclaration (FullNamedExpression type, LocalVariable li)
                {
@@ -1514,8 +1533,7 @@ namespace Mono.CSharp {
 
                public bool Resolve (BlockContext bc, bool resolveDeclaratorInitializers)
                {
-                       if (li.Type == null) {
-                               TypeSpec type = null;
+                       if (type == null && !li.IsCompilerGenerated) {
                                var vexpr = type_expr as VarExpr;
 
                                //
@@ -1623,8 +1641,10 @@ namespace Mono.CSharp {
                        if (declarators != null) {
                                foreach (var d in declarators) {
                                        d.Variable.CreateBuilder (ec);
-                                       if (d.Initializer != null)
+                                       if (d.Initializer != null) {
+                                               ec.Mark (d.Variable.Location);
                                                ((ExpressionStatement) d.Initializer).EmitStatement (ec);
+                                       }
                                }
                        }
                }
@@ -1681,7 +1701,7 @@ namespace Mono.CSharp {
                                if (TypeSpec.IsReferenceType (li.Type))
                                        initializer.Error_ConstantCanBeInitializedWithNullOnly (bc, li.Type, initializer.Location, li.Name);
                                else
-                                       initializer.Error_ValueCannotBeConverted (bc, initializer.Location, li.Type, false);
+                                       initializer.Error_ValueCannotBeConverted (bc, li.Type, false);
 
                                return null;
                        }
@@ -2061,9 +2081,7 @@ namespace Mono.CSharp {
 #endif
 
 //             int assignable_slots;
-               bool unreachable_shown;
-               bool unreachable;
-               
+
                public Block (Block parent, Location start, Location end)
                        : this (parent, 0, start, end)
                {
@@ -2235,6 +2253,8 @@ namespace Mono.CSharp {
 
                        Block prev_block = ec.CurrentBlock;
                        bool ok = true;
+                       bool unreachable = ec.IsUnreachable;
+                       bool prev_unreachable = unreachable;
 
                        ec.CurrentBlock = this;
                        ec.StartFlowBranching (this);
@@ -2267,14 +2287,10 @@ namespace Mono.CSharp {
                                        if (s is EmptyStatement)
                                                continue;
 
-                                       if (!unreachable_shown && !(s is LabeledStatement)) {
+                                       if (!ec.UnreachableReported && !(s is LabeledStatement)) {
                                                ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
-                                               unreachable_shown = true;
+                                               ec.UnreachableReported = true;
                                        }
-
-                                       Block c_block = s as Block;
-                                       if (c_block != null)
-                                               c_block.unreachable = c_block.unreachable_shown = true;
                                }
 
                                //
@@ -2298,8 +2314,15 @@ namespace Mono.CSharp {
                                        statements [ix] = new EmptyStatement (s.loc);
 
                                unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-                               if (unreachable && s is LabeledStatement)
-                                       throw new InternalErrorException ("should not happen");
+                               if (unreachable) {
+                                       ec.IsUnreachable = true;
+                               } else if (ec.IsUnreachable)
+                                       ec.IsUnreachable = false;
+                       }
+
+                       if (unreachable != prev_unreachable) {
+                               ec.IsUnreachable = prev_unreachable;
+                               ec.UnreachableReported = false;
                        }
 
                        while (ec.CurrentBranching is FlowBranchingLabeled)
@@ -2323,17 +2346,21 @@ namespace Mono.CSharp {
 
                public override bool ResolveUnreachable (BlockContext ec, bool warn)
                {
-                       unreachable_shown = true;
-                       unreachable = true;
-
-                       if (warn)
+                       bool unreachable = false;
+                       if (warn && !ec.UnreachableReported) {
+                               ec.UnreachableReported = true;
+                               unreachable = true;
                                ec.Report.Warning (162, 2, loc, "Unreachable code detected");
+                       }
 
                        var fb = ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
                        fb.CurrentUsageVector.IsUnreachable = true;
                        bool ok = Resolve (ec);
                        ec.KillFlowBranching ();
 
+                       if (unreachable)
+                               ec.UnreachableReported = false;
+
                        return ok;
                }
                
@@ -2464,15 +2491,6 @@ namespace Mono.CSharp {
                        if (ec.CurrentAnonymousMethod is StateMachineInitializer && ParametersBlock.Original == ec.CurrentAnonymousMethod.Block.Original)
                                return ec.CurrentAnonymousMethod.Storey;
 
-                       //
-                       // When referencing a variable inside iterator where all
-                       // variables are already captured and we don't need to create
-                       // another storey context
-                       //
-                       if (ParametersBlock.am_storey is StateMachine) {
-                               return ParametersBlock.am_storey;
-                       }
-
                        if (am_storey == null) {
                                MemberBase mc = ec.MemberContext as MemberBase;
 
@@ -2487,8 +2505,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       // TODO: The is check should go once state machine is fully separated
-                       if (am_storey != null && !(am_storey is StateMachine)) {
+                       if (am_storey != null) {
                                DefineStoreyContainer (ec, am_storey);
                                am_storey.EmitStoreyInstantiation (ec, this);
                        }
@@ -2516,22 +2533,6 @@ namespace Mono.CSharp {
                protected void DefineStoreyContainer (EmitContext ec, AnonymousMethodStorey storey)
                {
                        if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null) {
-                               //
-                               // Creates parent storey reference when access to hoisted this is required
-                               //
-                               var block = storey.OriginalSourceBlock;
-                               if (block.HasCapturedThis && block.Parent != null) {
-                                       var parent = block.Parent.Explicit;
-
-                                       //
-                                       // Hoisted this variable lives in top-level storey only
-                                       //
-                                       while (parent.AnonymousMethodStorey == null || parent.AnonymousMethodStorey.Parent is AnonymousMethodStorey)
-                                               parent = parent.Parent.Explicit;
-
-                                       storey.AddParentStoreyReference (ec, parent.AnonymousMethodStorey);
-                               }
-
                                storey.SetNestedStoryParent (ec.CurrentAnonymousMethod.Storey);
                                storey.Mutator = ec.CurrentAnonymousMethod.Storey.Mutator;
                        }
@@ -2542,10 +2543,79 @@ namespace Mono.CSharp {
                        storey.CreateContainer ();
                        storey.DefineContainer ();
 
+                       if (Original.Explicit.HasCapturedThis && Original.ParametersBlock.TopBlock.ThisReferencesFromChildrenBlock != null) {
+
+                               //
+                               // Only first storey in path will hold this reference. All children blocks will
+                               // reference it indirectly using $ref field
+                               //
+                               for (Block b = Original.Explicit; b != null; b = b.Parent) {
+                                       if (b.Parent != null) {
+                                               var s = b.Parent.Explicit.AnonymousMethodStorey;
+                                               if (s != null) {
+                                                       storey.HoistedThis = s.HoistedThis;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (b.Explicit == b.Explicit.ParametersBlock && b.Explicit.ParametersBlock.StateMachine != null) {
+                                               storey.HoistedThis = b.Explicit.ParametersBlock.StateMachine.HoistedThis;
+                                               break;
+                                       }
+                               }
+
+                               //
+                               // We are the first storey on path and this has to be hoisted
+                               //
+                               if (storey.HoistedThis == null) {
+                                       foreach (ExplicitBlock ref_block in Original.ParametersBlock.TopBlock.ThisReferencesFromChildrenBlock) {
+                                               //
+                                               // ThisReferencesFromChildrenBlock holds all reference even if they
+                                               // are not on this path. It saves some memory otherwise it'd have to
+                                               // be in every explicit block. We run this check to see if the reference
+                                               // is valid for this storey
+                                               //
+                                               Block block_on_path = ref_block;
+                                               for (; block_on_path != null && block_on_path != Original; block_on_path = block_on_path.Parent);
+
+                                               if (block_on_path == null)
+                                                       continue;
+
+                                               if (storey.HoistedThis == null)
+                                                       storey.AddCapturedThisField (ec);
+
+                                               for (ExplicitBlock b = ref_block; b.AnonymousMethodStorey != storey; b = b.Parent.Explicit) {
+                                                       if (b.AnonymousMethodStorey != null) {
+                                                               b.AnonymousMethodStorey.AddParentStoreyReference (ec, storey);
+                                                               b.AnonymousMethodStorey.HoistedThis = storey.HoistedThis;
+
+                                                               //
+                                                               // Stop propagation inside same top block
+                                                               //
+                                                               if (b.ParametersBlock == ParametersBlock.Original)
+                                                                       break;
+
+                                                               b = b.ParametersBlock;
+                                                       }
+
+                                                       var pb = b as ParametersBlock;
+                                                       if (pb != null && pb.StateMachine != null) {
+                                                               if (pb.StateMachine == storey)
+                                                                       break;
+
+                                                               pb.StateMachine.AddParentStoreyReference (ec, storey);
+                                                       }
+
+                                                       b.HasCapturedVariable = true;
+                                               }
+                                       }
+                               }
+                       }
+
                        var ref_blocks = storey.ReferencesFromChildrenBlock;
                        if (ref_blocks != null) {
                                foreach (ExplicitBlock ref_block in ref_blocks) {
-                                       for (ExplicitBlock b = ref_block.Explicit; b.AnonymousMethodStorey != storey; b = b.Parent.Explicit) {
+                                       for (ExplicitBlock b = ref_block; b.AnonymousMethodStorey != storey; b = b.Parent.Explicit) {
                                                if (b.AnonymousMethodStorey != null) {
                                                        b.AnonymousMethodStorey.AddParentStoreyReference (ec, storey);
 
@@ -2787,7 +2857,7 @@ namespace Mono.CSharp {
                        // Overwrite original for comparison purposes when linking cross references
                        // between anonymous methods
                        //
-                       Original = source;
+                       Original = source.Original;
                }
 
                #region Properties
@@ -2882,7 +2952,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       if (state_machine != null) {
+                       if (state_machine != null && state_machine.OriginalSourceBlock != this) {
                                DefineStoreyContainer (ec, state_machine);
                                state_machine.EmitStoreyInstantiation (ec, this);
                        }
@@ -2892,7 +2962,7 @@ namespace Mono.CSharp {
 
                public void EmitEmbedded (EmitContext ec)
                {
-                       if (state_machine != null) {
+                       if (state_machine != null && state_machine.OriginalSourceBlock != this) {
                                DefineStoreyContainer (ec, state_machine);
                                state_machine.EmitStoreyInstantiation (ec, this);
                        }
@@ -3027,7 +3097,7 @@ namespace Mono.CSharp {
                        var iterator = new Iterator (this, method, host, iterator_type, is_enumerable);
                        var stateMachine = new IteratorStorey (iterator);
 
-                       am_storey = stateMachine;
+                       state_machine = stateMachine;
                        iterator.SetStateMachine (stateMachine);
 
                        var tlb = new ToplevelBlock (host.Compiler, Parameters, Location.Null);
@@ -3073,7 +3143,7 @@ namespace Mono.CSharp {
 
                        var stateMachine = new AsyncTaskStorey (this, context, initializer, returnType);
 
-                       am_storey = stateMachine;
+                       state_machine = stateMachine;
                        initializer.SetStateMachine (stateMachine);
 
                        var b = this is ToplevelBlock ?
@@ -3100,11 +3170,7 @@ namespace Mono.CSharp {
                Dictionary<string, object> names;
                Dictionary<string, object> labels;
 
-               public HoistedVariable HoistedThisVariable;
-
-               public Report Report {
-                       get { return compiler.Report; }
-               }
+               List<ExplicitBlock> this_references;
 
                public ToplevelBlock (CompilerContext ctx, Location loc)
                        : this (ctx, ParametersCompiled.EmptyReadOnlyParameters, loc)
@@ -3141,6 +3207,31 @@ namespace Mono.CSharp {
                        }
                }
 
+               public Report Report {
+                       get {
+                               return compiler.Report;
+                       }
+               }
+
+               //
+               // Used by anonymous blocks to track references of `this' variable
+               //
+               public List<ExplicitBlock> ThisReferencesFromChildrenBlock {
+                       get {
+                               return this_references;
+                       }
+               }
+
+               //
+               // Returns the "this" instance variable of this block.
+               // See AddThisVariable() for more information.
+               //
+               public LocalVariable ThisVariable {
+                       get {
+                               return this_variable;
+                       }
+               }
+
                public void AddLocalName (string name, INamedBlockVariable li, bool ignoreChildrenBlocks)
                {
                        if (names == null)
@@ -3261,6 +3352,20 @@ namespace Mono.CSharp {
                        existing_list.Add (label);
                }
 
+               public void AddThisReferenceFromChildrenBlock (ExplicitBlock block)
+               {
+                       if (this_references == null)
+                               this_references = new List<ExplicitBlock> ();
+
+                       if (!this_references.Contains (block))
+                               this_references.Add (block);
+               }
+
+               public void RemoveThisReferenceFromChildrenBlock (ExplicitBlock block)
+               {
+                       this_references.Remove (block);
+               }
+
                //
                // Creates an arguments set from all parameters, useful for method proxy calls
                //
@@ -3371,14 +3476,6 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               // <summary>
-               //   Returns the "this" instance variable of this block.
-               //   See AddThisVariable() for more information.
-               // </summary>
-               public LocalVariable ThisVariable {
-                       get { return this_variable; }
-               }
-
                // <summary>
                //   This is used by non-static `struct' constructors which do not have an
                //   initializer - in this case, the constructor must initialize all of the
@@ -4176,10 +4273,10 @@ namespace Mono.CSharp {
 
                                Expression cond = null;
                                for (int ci = 0; ci < s.Labels.Count; ++ci) {
-                                       var e = new Binary (Binary.Operator.Equality, value, s.Labels[ci].Converted, loc);
+                                       var e = new Binary (Binary.Operator.Equality, value, s.Labels[ci].Converted);
 
                                        if (ci > 0) {
-                                               cond = new Binary (Binary.Operator.LogicalOr, cond, e, loc);
+                                               cond = new Binary (Binary.Operator.LogicalOr, cond, e);
                                        } else {
                                                cond = e;
                                        }
@@ -4469,6 +4566,12 @@ namespace Mono.CSharp {
                        ec.MarkLabel (start_finally);
 
                        if (finally_host != null) {
+                               finally_host.Define ();
+                               finally_host.Emit ();
+
+                               // Now it's safe to add, to close it properly and emit sequence points
+                               finally_host.Parent.AddMember (finally_host);
+
                                var ce = new CallEmitter ();
                                ce.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc);
                                ce.EmitPredefined (ec, finally_host.Spec, new Arguments (0));
@@ -4552,8 +4655,10 @@ namespace Mono.CSharp {
                        // original block then simply calls the newly generated method.
                        //
                        if (bc.CurrentIterator != null && !bc.IsInProbingMode) {
-                               var iterator = bc.CurrentIterator;
-                               finally_host = iterator.CreateFinallyHost (this);
+                               var b = stmt as Block;
+                               if (b != null && b.Explicit.HasYield) {
+                                       finally_host = bc.CurrentIterator.CreateFinallyHost (this);
+                               }
                        }
 
                        return base.Resolve (bc);
@@ -4681,21 +4786,9 @@ namespace Mono.CSharp {
                                locked = false;
                        }
 
-                       using (ec.Set (ResolveContext.Options.LockScope)) {
-                               ec.StartFlowBranching (this);
-                               Statement.Resolve (ec);
-                               ec.EndFlowBranching ();
-                       }
-
-                       if (lv != null) {
-                               lv.IsLockedByStatement = locked;
-                       }
-
-                       base.Resolve (ec);
-
                        //
                        // Have to keep original lock value around to unlock same location
-                       // in the case the original has changed or is null
+                       // in the case of original value has changed or is null
                        //
                        expr_copy = TemporaryVariableReference.Create (ec.BuiltinTypes.Object, ec.CurrentBlock, loc);
                        expr_copy.Resolve (ec);
@@ -4708,6 +4801,18 @@ namespace Mono.CSharp {
                                lock_taken.Resolve (ec);
                        }
 
+                       using (ec.Set (ResolveContext.Options.LockScope)) {
+                               ec.StartFlowBranching (this);
+                               Statement.Resolve (ec);
+                               ec.EndFlowBranching ();
+                       }
+
+                       if (lv != null) {
+                               lv.IsLockedByStatement = locked;
+                       }
+
+                       base.Resolve (ec);
+
                        return true;
                }
                
@@ -5061,8 +5166,8 @@ namespace Mono.CSharp {
                                        // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0])
                                        //
                                        converted = new Conditional (new BooleanExpression (new Binary (Binary.Operator.LogicalOr,
-                                               new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc), loc),
-                                               new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc), loc), loc)),
+                                               new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc)),
+                                               new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc)))),
                                                        new NullLiteral (loc),
                                                        converted, loc);
 
@@ -5620,7 +5725,7 @@ namespace Mono.CSharp {
 
                                // Add conditional call when disposing possible null variable
                                if (!type.IsStruct || type.IsNullableType)
-                                       dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc), loc), dispose, dispose.loc);
+                                       dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc)), dispose, dispose.loc);
 
                                return dispose;
                        }
@@ -5634,7 +5739,7 @@ namespace Mono.CSharp {
                        {
                                for (int i = declarators.Count - 1; i >= 0; --i) {
                                        var d = declarators [i];
-                                       var vd = new VariableDeclaration (d.Variable, type_expr.Location);
+                                       var vd = new VariableDeclaration (d.Variable, d.Variable.Location);
                                        vd.Initializer = d.Initializer;
                                        vd.IsNested = true;
                                        vd.dispose_call = CreateDisposeCall (bc, d.Variable);
@@ -5870,7 +5975,7 @@ namespace Mono.CSharp {
                                if (variable_ref == null)
                                        return false;
 
-                               for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, access, Location.Null), for_each.variable.Location));
+                               for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, access, Location.Null), for_each.type.Location));
 
                                bool ok = true;
 
@@ -5966,7 +6071,7 @@ namespace Mono.CSharp {
                                        var idisaposable_test = new Binary (Binary.Operator.Inequality, new CompilerAssign (
                                                dispose_variable.CreateReferenceExpression (bc, loc),
                                                new As (lv.CreateReferenceExpression (bc, loc), new TypeExpression (dispose_variable.Type, loc), loc),
-                                               loc), new NullLiteral (loc), loc);
+                                               loc), new NullLiteral (loc));
 
                                        var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc);
 
@@ -6181,7 +6286,7 @@ namespace Mono.CSharp {
                                if (variable_ref == null)
                                        return false;
 
-                               for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, current_pe, Location.Null), variable.Location));
+                               for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, current_pe, Location.Null), for_each.type.Location));
 
                                var init = new Invocation (get_enumerator_mg, null);
 
@@ -6345,6 +6450,7 @@ namespace Mono.CSharp {
                        target.type = type.Clone (clonectx);
                        target.expr = expr.Clone (clonectx);
                        target.body = (Block) body.Clone (clonectx);
+                       target.statement = statement.Clone (clonectx);
                }
                
                public override object Accept (StructuralVisitor visitor)