+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.
// 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){
//
//
}
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);
}
//
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)
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;
}
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++;
{
ec.CurrentAnonymousMethod = iterator.move_next_method;
- iterator.cc.EmitParameter (ec, name);
+ LocalTemporary dummy = null;
+
+ iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
}
}
+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
--- /dev/null
+// 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 + ".");
+ }
+}