* Sets the following fields in \p klass:
* - all the fields initialized by mono_class_init_sizes ()
* - element_class/cast_class (for enums)
+ * - sizes:element_size (for arrays)
* - field->type/offset for all fields
* - fields_inited
*
MonoClassField *field;
gboolean blittable;
int instance_size = base_instance_size;
+ int element_size = -1;
int class_size, min_align;
int *field_offsets;
gboolean *fields_has_references;
else if (klass->byval_arg.type == MONO_TYPE_PTR)
instance_size = sizeof (MonoObject) + sizeof (gpointer);
+ if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
+ element_size = mono_class_array_element_size (klass->element_class);
+
/* Publish the data */
mono_loader_lock ();
if (klass->instance_size && !klass->image->dynamic) {
klass->fields [i].offset = field_offsets [i];
}
+ if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
+ klass->sizes.element_size = element_size;
+
mono_memory_barrier ();
klass->size_inited = 1;
mono_loader_unlock ();
GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
if (g_slist_find (init_list, klass)) {
mono_class_set_type_load_failure (klass, "Recursive type definition detected");
- goto leave;
+ goto leave_no_init_pending;
}
init_list = g_slist_prepend (init_list, klass);
mono_native_tls_set_value (init_pending_tls_id, init_list);
goto leave;
- leave:
+leave:
+ init_list = mono_native_tls_get_value (init_pending_tls_id);
init_list = g_slist_remove (init_list, klass);
mono_native_tls_set_value (init_pending_tls_id, init_list);
+leave_no_init_pending:
if (locked)
mono_loader_unlock ();
/* element_size -1 is ok as this is not an instantitable type*/
klass->sizes.element_size = -1;
} else
- klass->sizes.element_size = mono_class_array_element_size (eclass);
+ klass->sizes.element_size = -1;
mono_class_setup_supertypes (klass);
* \param ac pointer to a \c MonoArrayClass
*
* \returns The size of single array element.
+ *
+ * LOCKING: Acquires the loader lock.
*/
gint32
mono_array_element_size (MonoClass *ac)
{
g_assert (ac->rank);
+ if (G_UNLIKELY (!ac->size_inited)) {
+ mono_class_setup_fields (ac);
+ }
return ac->sizes.element_size;
}
mono_class_init (k);
if (retklass)
*retklass = k;
- field = mono_class_get_field (k, token);
- if (!field) {
- mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x", token);
+ if (mono_class_has_failure (k)) {
+ MonoError causedby_error;
+ error_init (&causedby_error);
+ mono_error_set_for_class_failure (&causedby_error, k);
+ mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x, due to: %s", token, mono_error_get_message (&causedby_error));
+ mono_error_cleanup (&causedby_error);
+ } else {
+ field = mono_class_get_field (k, token);
+ if (!field) {
+ mono_error_set_bad_image (error, image, "Could not resolve field token 0x%08x", token);
+ }
}
}
klass.rank = 1;
klass.instance_size = MONO_SIZEOF_MONO_ARRAY;
klass.sizes.element_size = 1;
+ klass.size_inited = 1;
klass.name = "array_filler_type";
vtable->klass = &klass;
runtime-invoke.gen.cs \
imt_big_iface_test.cs \
bug-58782-plain-throw.cs \
- bug-58782-capture-and-throw.cs
+ bug-58782-capture-and-throw.cs \
+ recursive-struct-arrays.cs
if AMD64
TESTS_CS_SRC += async-exc-compilation.cs finally_guard.cs finally_block_ending_in_dead_bb.cs
--- /dev/null
+using System;
+
+/* Test that the runtime can represent value types that have array fields that
+ * recursively refer to the same value type */
+
+struct S1 {
+ static S1[][] foo;
+}
+
+struct S2 {
+ static S2[] foo;
+}
+
+struct S3a {
+ static S3b[] foo;
+}
+
+struct S3b {
+ static S3a[][] foo;
+}
+
+struct P<X> where X : struct {
+ static P<X>[][] foo;
+}
+
+public struct S4
+{
+ private static S4[][] foo;
+
+ public static readonly S4 West = new S4(-1, 0);
+ public static readonly S4 East = new S4(1, 0);
+ public static readonly S4 North = new S4(0, 1);
+ public static readonly S4 South = new S4(0, -1);
+ public static readonly S4[] Directions = { North, South, East, West };
+
+ public readonly int x;
+ public readonly int z;
+
+ public S4(int x, int z)
+ {
+ this.x = x;
+ this.z = z;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("[{0}, {1}]", x, z);
+ }
+}
+
+
+class Program {
+ static int Main() {
+ Console.WriteLine (typeof (S1).Name);
+ Console.WriteLine (typeof (S2).Name);
+ Console.WriteLine (typeof (S3a).Name);
+ Console.WriteLine (typeof (S3b).Name);
+ foreach (var s4 in S4.Directions) {
+ Console.WriteLine (s4);
+ }
+ Console.WriteLine (typeof (P<S1>).Name);
+ Console.WriteLine (typeof (P<int>).Name);
+ return 0;
+ }
+}