In mcs:
authorBen Maurer <benm@mono-cvs.ximian.com>
Sun, 4 Dec 2005 02:33:53 +0000 (02:33 -0000)
committerBen Maurer <benm@mono-cvs.ximian.com>
Sun, 4 Dec 2005 02:33:53 +0000 (02:33 -0000)
2005-12-03  Ben Maurer  <bmaurer@ximian.com>

* anonymous.cs: Have the param code handle leaving copies on the
stack etc. Allows anonymous params to take part in the assignment
code (++, +=, etc). Fixes bug #76550

* expression.cs: Handle the prepare_for_load/leave_copy by passing
it down to the anon code.

* iterators.cs: Use dummy var here

* codegen.cs: Handle new vars

In tests:
2005-12-03  Ben Maurer  <bmaurer@ximian.com>

* test-474.cs: new test.

svn path=/trunk/mcs/; revision=53896

mcs/mcs/ChangeLog
mcs/mcs/anonymous.cs
mcs/mcs/codegen.cs
mcs/mcs/expression.cs
mcs/mcs/iterators.cs
mcs/tests/ChangeLog
mcs/tests/test-474.cs [new file with mode: 0644]

index 113e87ae33e873e2a78ac2d5e414453d547314ba..500157ad621baa60a541328c4c509f9091a963a8 100644 (file)
@@ -1,3 +1,16 @@
+2005-12-03  Ben Maurer  <bmaurer@ximian.com>
+
+       * anonymous.cs: Have the param code handle leaving copies on the
+       stack etc. Allows anonymous params to take part in the assignment
+       code (++, +=, etc). Fixes bug #76550
+
+       * expression.cs: Handle the prepare_for_load/leave_copy by passing
+       it down to the anon code.
+
+       * iterators.cs: Use dummy var here
+
+       * codegen.cs: Handle new vars
+
 2005-12-01  Marek Safar  <marek.safar@seznam.cz>
 
        Fix #76849.
index e7db211d6d45464c2ee435b0f5923d3560d4a4bc..422719f38483c184eee60bc5a717592b159a2c14 100644 (file)
@@ -1182,14 +1182,15 @@ namespace Mono.CSharp {
                // Emits the code necessary to load the parameter named `name' within
                // an anonymous method.
                //
-               public void EmitParameter (EmitContext ec, string name)
+               public void EmitParameter (EmitContext ec, string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
                {
                        CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
                        if (cc != this){
-                               cc.EmitParameter (ec, name);
+                               cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
                                return;
                        }
-                       EmitParameterInstance (ec, name);
+                       if (!prepared)
+                               EmitParameterInstance (ec, name);
                        CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
                        if (par_info != null){
                                // 
@@ -1197,30 +1198,40 @@ namespace Mono.CSharp {
                                //
                        }
                        ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+
+                       if (leave_copy){
+                               ec.ig.Emit (OpCodes.Dup);
+                               temp = new LocalTemporary (ec, par_info.FieldBuilder.FieldType);
+                               temp.Store (ec);
+                       }
                }
 
                //
                // Implements the assignment of `source' to the paramenter named `name' within
                // an anonymous method.
                //
-               public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load)
+               public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
                {
                        CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
                        if (cc != this){
-                               cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load);
+                               cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
                                return;
                        }
                        ILGenerator ig = ec.ig;
                        CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
 
                        EmitParameterInstance (ec, name);
-                       if (leave_copy)
+                       if (prepare_for_load)
                                ig.Emit (OpCodes.Dup);
                        source.Emit (ec);
-                       ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
                        if (leave_copy){
-                               ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+                               ig.Emit (OpCodes.Dup);
+                               temp = new LocalTemporary (ec, par_info.FieldBuilder.FieldType);
+                               temp.Store (ec);
                        }
+                       ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
+                       if (temp != null)
+                               temp.Emit (ec);
                }
 
                //
index 4f90c9f60056ffa020a7f0a20510440f2ecf78ae..15ee80f1dda053eb216ed4851ba3c48fb92316c4 100644 (file)
@@ -915,14 +915,14 @@ namespace Mono.CSharp {
                        capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
                }
 
-               public void EmitParameter (string name)
+               public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
                {
-                       capture_context.EmitParameter (this, name);
+                       capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
                }
 
-               public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load)
+               public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary  temp)
                {
-                       capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load);
+                       capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
                }
 
                public void EmitAddressOfParameter (string name)
index ba6731f8ae98e244d6ea53b558c53df23cfa5450..dcddc2f68fe3174db59d57762263396a0ad9f55e 100644 (file)
@@ -3789,11 +3789,8 @@ namespace Mono.CSharp {
                        ILGenerator ig = ec.ig;
                        int arg_idx = idx;
 
-                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-                               if (leave_copy)
-                                       throw new InternalErrorException ();
-                               
-                               ec.EmitParameter (name);
+                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){                               
+                               ec.EmitParameter (name, leave_copy, prepared, ref temp);
                                return;
                        }
 
@@ -3825,15 +3822,16 @@ namespace Mono.CSharp {
                
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
+                       prepared = prepare_for_load;
                        if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
-                               ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load);
+                               ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
                                return;
                        }
 
                        ILGenerator ig = ec.ig;
                        int arg_idx = idx;
                        
-                       prepared = prepare_for_load;
+                       
                        
                        if (!ec.MethodIsStatic)
                                arg_idx++;
index 385273452c7edbc4a099feecceab8df442695462..c3dd930fe86b4644afb76c7266a4b20c1f80b6f2 100644 (file)
@@ -759,7 +759,9 @@ namespace Mono.CSharp {
                        {
                                ec.CurrentAnonymousMethod = iterator.move_next_method;
 
-                               iterator.cc.EmitParameter (ec, name);
+                               LocalTemporary dummy = null;
+                               
+                               iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
                        }
                }
 
index 424fab33c17ac415cf74cfb13840b47f5dfdb9b3..aaf580a4ad669f287a972211cd7e216904524ea7 100644 (file)
@@ -1,3 +1,7 @@
+2005-12-03  Ben Maurer  <bmaurer@ximian.com>
+
+       * test-474.cs: new test.
+
 2005-11-16  Atsushi Enomoto  <atsushi@ximian.com>
 
        * test-xml-048-ref.xml test-xml-048.cs : test for bug #76730
diff --git a/mcs/tests/test-474.cs b/mcs/tests/test-474.cs
new file mode 100644 (file)
index 0000000..09408fb
--- /dev/null
@@ -0,0 +1,44 @@
+// Test for bug 76550 -- EmitAssign getting called
+// on captured params.
+
+class Z {
+       static void Main ()
+       {
+               TestPreinc (1);
+               TestPostinc (1);
+       }
+       
+       delegate void X ();
+
+       static void TestPreinc (int i)
+       {
+               Assert (i, 1);
+               X x = delegate {
+                       int z = ++i;
+                       Assert (z, 2);
+                       Assert (i, 2);
+               };
+               x ();
+               Assert (i, 2);
+       }
+
+       static void TestPostinc (int i)
+       {
+               Assert (i, 1);
+               X x = delegate {
+                       int z = i++;
+                       Assert (z, 1);
+                       Assert (i, 2);
+               };
+               x ();
+               Assert (i, 2);
+       }
+       
+       static void Assert (int a, int b)
+       {
+               if (a == b)
+                       return;
+
+               throw new System.Exception ("Incorrect was: " + a + " should have been " + b + ".");
+       }
+}