Allow setting nullable values in sdb. Fixes #4385.
authorZoltan Varga <vargaz@gmail.com>
Wed, 25 Apr 2012 09:11:00 +0000 (11:11 +0200)
committerZoltan Varga <vargaz@gmail.com>
Wed, 25 Apr 2012 09:11:19 +0000 (11:11 +0200)
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mono/mini/debugger-agent.c

index 5fdda3e7fa6dcb8c62ac2ecc6814f0197035cb83..2947fa0a42d959a388933e75ec619a58d32c3350 100644 (file)
@@ -170,6 +170,7 @@ public class Tests : TestsBase
        double field_double;
        Thread field_class;
        IntPtr field_intptr;
+       int? field_nullable;
        static int static_i = 55;
        static string static_s = "A";
        public const int literal_i = 56;
index 417eca4c3cb5cbd51e890017e2a675ae75d3405a..480642bb89a3f310026442591266fc6819f565f3 100644 (file)
@@ -867,7 +867,6 @@ public class DebuggerTests
                AssertValue (Int32.MaxValue - 5, (f as StructMirror).Fields [0]);
 
                // enums
-
                FieldInfoMirror field = o.Type.GetField ("field_enum");
                f = o.GetValue (field);
                (f as EnumMirror).Value = 5;
@@ -885,6 +884,20 @@ public class DebuggerTests
                f = o.GetValue (field);
                o.SetValue (field, f);
 
+               // nullables
+               field = o.Type.GetField ("field_nullable");
+               f = o.GetValue (field);
+               AssertValue (0, (f as StructMirror).Fields [0]);
+               AssertValue (false, (f as StructMirror).Fields [1]);
+               o.SetValue (field, vm.CreateValue (6));
+               f = o.GetValue (field);
+               AssertValue (6, (f as StructMirror).Fields [0]);
+               AssertValue (true, (f as StructMirror).Fields [1]);
+               o.SetValue (field, vm.CreateValue (null));
+               f = o.GetValue (field);
+               AssertValue (0, (f as StructMirror).Fields [0]);
+               AssertValue (false, (f as StructMirror).Fields [1]);
+
                // Argument checking
                AssertThrows<ArgumentNullException> (delegate () {
                                o.SetValues (null, new Value [0]);
index 2edf3947b09a71dad4e6668be5c925b5d5319f56..0ded1da3319c5774d3dec3f9557d170111c0f91c 100644 (file)
@@ -5324,10 +5324,12 @@ buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain)
 }
 
 static ErrorCode
-decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
+decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit);
+
+static ErrorCode
+decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
 {
        int err;
-       int type = decode_byte (buf, &buf, limit);
 
        if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
                !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
@@ -5462,6 +5464,37 @@ decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8
        return 0;
 }
 
+static ErrorCode
+decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
+{
+       int err;
+       int type = decode_byte (buf, &buf, limit);
+
+       if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
+               MonoType *targ = t->data.generic_class->context.class_inst->type_argv [0];
+               guint8 *nullable_buf;
+
+               if (targ->type == type) {
+                       nullable_buf = g_malloc (mono_class_instance_size (mono_class_from_mono_type (targ)));
+                       err = decode_value_internal (targ, type, domain, nullable_buf, buf, endbuf, limit);
+                       if (err) {
+                               g_free (nullable_buf);
+                               return err;
+                       }
+                       mono_nullable_init (addr, mono_value_box (domain, mono_class_from_mono_type (targ), nullable_buf), mono_class_from_mono_type (t));
+                       g_free (nullable_buf);
+                       *endbuf = buf;
+                       return ERR_NONE;
+               } else if (type == VALUE_TYPE_ID_NULL) {
+                       mono_nullable_init (addr, NULL, mono_class_from_mono_type (t));
+                       *endbuf = buf;
+                       return ERR_NONE;
+               }
+       }
+
+       return decode_value_internal (t, type, domain, addr, buf, endbuf, limit);
+}
+
 static void
 add_var (Buffer *buf, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype)
 {