X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=06bac2ec1f1593f681ceb42db45efa4b61596749;hb=e8e4e2e0c6d00aab6f81f538d9a770ab6d192243;hp=ee5743c9ddbd40999174500999bb8bf5ead32b0e;hpb=ce0a590a5869ab2d73f6ec00a56352c02977b623;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index ee5743c9ddb..06bac2ec1f1 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -2568,6 +2568,24 @@ setup_interface_offsets (MonoClass *class, int cur_slot) interface_offsets_full [i] = -1; } + for (k = class->parent; k ; k = k->parent) { + ifaces = mono_class_get_implemented_interfaces (k); + if (ifaces) { + for (i = 0; i < ifaces->len; ++i) { + int io; + ic = g_ptr_array_index (ifaces, i); + + /*Force the sharing of interface offsets between parent and subtypes.*/ + io = mono_class_interface_offset (k, ic); + g_assert (io >= 0); + interfaces_full [ic->interface_id] = ic; + interface_offsets_full [ic->interface_id] = io; + } + g_ptr_array_free (ifaces, TRUE); + } + } + + ifaces = mono_class_get_implemented_interfaces (class); if (ifaces) { for (i = 0; i < ifaces->len; ++i) { @@ -2581,25 +2599,6 @@ setup_interface_offsets (MonoClass *class, int cur_slot) g_ptr_array_free (ifaces, TRUE); } - for (k = class->parent; k ; k = k->parent) { - ifaces = mono_class_get_implemented_interfaces (k); - if (ifaces) { - for (i = 0; i < ifaces->len; ++i) { - ic = g_ptr_array_index (ifaces, i); - - if (interface_offsets_full [ic->interface_id] == -1) { - int io = mono_class_interface_offset (k, ic); - - g_assert (io >= 0); - - interfaces_full [ic->interface_id] = ic; - interface_offsets_full [ic->interface_id] = io; - } - } - g_ptr_array_free (ifaces, TRUE); - } - } - if (MONO_CLASS_IS_INTERFACE (class)) { interfaces_full [class->interface_id] = class; interface_offsets_full [class->interface_id] = cur_slot; @@ -2795,9 +2794,11 @@ mono_class_setup_vtable (MonoClass *class) #define DEBUG_INTERFACE_VTABLE_CODE 0 #define TRACE_INTERFACE_VTABLE_CODE 0 #define VERIFY_INTERFACE_VTABLE_CODE 0 +#define VTABLE_SELECTOR (1) #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE) #define DEBUG_INTERFACE_VTABLE(stmt) do {\ + if (!(VTABLE_SELECTOR)) break; \ stmt;\ } while (0) #else @@ -2806,6 +2807,7 @@ mono_class_setup_vtable (MonoClass *class) #if TRACE_INTERFACE_VTABLE_CODE #define TRACE_INTERFACE_VTABLE(stmt) do {\ + if (!(VTABLE_SELECTOR)) break; \ stmt;\ } while (0) #else @@ -2814,6 +2816,7 @@ mono_class_setup_vtable (MonoClass *class) #if VERIFY_INTERFACE_VTABLE_CODE #define VERIFY_INTERFACE_VTABLE(stmt) do {\ + if (!(VTABLE_SELECTOR)) break; \ stmt;\ } while (0) #else @@ -3101,10 +3104,9 @@ print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, Mono } static gboolean -verify_class_overrides (MonoClass *class, GPtrArray *ifaces, MonoMethod **overrides, int onum) +verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum) { int i; - gboolean found; for (i = 0; i < onum; ++i) { MonoMethod *decl = overrides [i * 2]; @@ -3124,38 +3126,14 @@ verify_class_overrides (MonoClass *class, GPtrArray *ifaces, MonoMethod **overri } if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) { - if (body->flags & METHOD_ATTRIBUTE_STATIC) - mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type")); - else - mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type")); - return FALSE; - } - - found = FALSE; - /*We can't use mono_class_is_assignable_from since it requires the class to be fully initialized*/ - if (ifaces) { - int j; - for (j = 0; j < ifaces->len; j++) { - MonoClass *ic = g_ptr_array_index (ifaces, j); - if (decl->klass == ic) { - found = TRUE; - break; - } - } - } - - if (!found) { - MonoClass *parent = class; - while (parent) { - if (decl->klass == parent) { - found = TRUE; - break; - } - parent = parent->parent; - } + if (body->flags & METHOD_ATTRIBUTE_STATIC) + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type")); + else + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type")); + return FALSE; } - if (!found) { + if (!mono_class_is_assignable_from_slow (decl->klass, class)) { mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type")); return FALSE; } @@ -3183,13 +3161,10 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o if (class->vtable) return; - ifaces = mono_class_get_implemented_interfaces (class); - - if (overrides && !verify_class_overrides (class, ifaces, overrides, onum)) { - if (ifaces) - g_ptr_array_free (ifaces, TRUE); + if (overrides && !verify_class_overrides (class, overrides, onum)) return; - } + + ifaces = mono_class_get_implemented_interfaces (class); if (ifaces) { for (i = 0; i < ifaces->len; i++) { @@ -3468,6 +3443,10 @@ mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int o cm->slot = slot; } + /*Non final newslot methods must be given a non-interface vtable slot*/ + if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0) + cm->slot = -1; + if (cm->slot < 0) cm->slot = cur_slot++; @@ -3844,6 +3823,16 @@ mono_class_init (MonoClass *class) class->init_pending = 1; + if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) { + MonoClass *element_class = class->element_class; + if (!element_class->inited) + mono_class_init (element_class); + if (element_class->exception_type != MONO_EXCEPTION_NONE) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); + goto fail; + } + } + /* CAS - SecurityAction.InheritanceDemand */ if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) { mono_secman_inheritancedemand_class (class, class->parent); @@ -3945,8 +3934,10 @@ mono_class_init (MonoClass *class) class->has_cctor = gklass->has_cctor; mono_class_setup_vtable (gklass); - if (gklass->exception_type) + if (gklass->exception_type) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); goto fail; + } class->vtable_size = gklass->vtable_size; } else { @@ -4034,12 +4025,20 @@ mono_class_init (MonoClass *class) if (class->parent) { /* This will compute class->parent->vtable_size for some classes */ mono_class_init (class->parent); - if (class->parent->exception_type || mono_loader_get_last_error ()) + if (class->parent->exception_type) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); + goto fail; + } + if (mono_loader_get_last_error ()) goto fail; if (!class->parent->vtable_size) { /* FIXME: Get rid of this somehow */ mono_class_setup_vtable (class->parent); - if (class->parent->exception_type || mono_loader_get_last_error ()) + if (class->parent->exception_type) { + mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL); + goto fail; + } + if (mono_loader_get_last_error ()) goto fail; } setup_interface_offsets (class, class->parent->vtable_size); @@ -5689,9 +5688,8 @@ mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *co if (!type) { char *name = mono_class_name_from_token (image, type_token); char *assembly = mono_assembly_name_from_token (image, type_token); - if (inflated) - mono_metadata_free_type (type); mono_loader_set_error_type_load (name, assembly); + return NULL; } if (inflated) { @@ -6256,6 +6254,67 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) return mono_class_has_parent (oklass, klass); } +/*Check if @candidate implements the interface @target*/ +static gboolean +mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate) +{ + int i; + + do { + if (candidate == target) + return TRUE; + + /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/ + if (candidate->image->dynamic && !candidate->wastypebuilder) { + MonoReflectionTypeBuilder *tb = candidate->reflection_info; + int j; + if (tb->interfaces) { + for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) { + MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j); + MonoClass *iface_class = mono_class_from_mono_type (iface->type); + if (iface_class == target || mono_class_implement_interface_slow (target, iface_class)) + return TRUE; + } + } + } else { + /*setup_interfaces don't mono_class_init anything*/ + mono_class_setup_interfaces (candidate); + for (i = 0; i < candidate->interface_count; ++i) { + if (candidate->interfaces [i] == target || mono_class_implement_interface_slow (target, candidate->interfaces [i])) + return TRUE; + } + } + candidate = candidate->parent; + } while (candidate); + + return FALSE; +} + +/* + * Check if @oklass can be assigned to @klass. + * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context. + */ +gboolean +mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate) +{ + if (candidate == target) + return TRUE; + if (target == mono_defaults.object_class) + return TRUE; + + /*setup_supertypes don't mono_class_init anything */ + mono_class_setup_supertypes (candidate); + mono_class_setup_supertypes (target); + + if (mono_class_has_parent (candidate, target)) + return TRUE; + + /*If target is not an interface there is no need to check them.*/ + if (!MONO_CLASS_IS_INTERFACE (target)) + return FALSE; + return mono_class_implement_interface_slow (target, candidate); +} + /** * mono_class_get_cctor: * @klass: A MonoClass pointer @@ -7733,6 +7792,10 @@ can_access_type (MonoClass *access_klass, MonoClass *member_klass) if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in)) return FALSE; + /*Non nested type with nested visibility. We just fail it.*/ + if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL) + return FALSE; + switch (access_level) { case TYPE_ATTRIBUTE_NOT_PUBLIC: return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);