Merge pull request #3082 from alexanderkyte/no_alloc_klass_error
[mono.git] / mono / metadata / class.c
index 91d31b60cc5eece43d13deef99d9933319b734b9..39fc6e491df965cc8ba8e37d76072cb467533c3e 100644 (file)
@@ -1369,6 +1369,53 @@ mono_type_has_exceptions (MonoType *type)
        }
 }
 
+void
+mono_error_set_for_class_failure (MonoError *oerror, MonoClass *klass)
+{
+       gpointer exception_data = mono_class_get_exception_data (klass);
+
+       switch (mono_class_get_failure(klass)) {
+       case MONO_EXCEPTION_TYPE_LOAD: {
+               mono_error_set_type_load_class (oerror, klass, "Error Loading class");
+               return;
+       }
+       case MONO_EXCEPTION_MISSING_METHOD: {
+               char *class_name = (char *)exception_data;
+               char *member_name = class_name + strlen (class_name) + 1;
+
+               mono_error_set_method_load (oerror, klass, member_name, "Error Loading Method");
+               return;
+       }
+       case MONO_EXCEPTION_MISSING_FIELD: {
+               char *class_name = (char *)exception_data;
+               char *member_name = class_name + strlen (class_name) + 1;
+
+               mono_error_set_field_load (oerror, klass, member_name, "Error Loading Field");
+               return;
+       }
+       case MONO_EXCEPTION_FILE_NOT_FOUND: {
+               char *msg_format = (char *)exception_data;
+               char *assembly_name = msg_format + strlen (msg_format) + 1;
+               char *msg = g_strdup_printf (msg_format, assembly_name);
+
+               mono_error_set_assembly_load (oerror, assembly_name, msg);
+               return;
+       }
+       case MONO_EXCEPTION_BAD_IMAGE: {
+               mono_error_set_bad_image (oerror, NULL, (const char *)exception_data);
+               return;
+       }
+       case MONO_EXCEPTION_INVALID_PROGRAM: {
+               mono_error_set_invalid_program (oerror, (const char *)exception_data);
+               return;
+       }
+       default: {
+               g_assert_not_reached ();
+       }
+       }
+}
+
+
 /*
  * mono_class_alloc:
  *
@@ -8022,7 +8069,9 @@ gboolean
 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
                           gboolean check_interfaces)
 {
-/*FIXME test for interfaces with variant generic arguments*/
+       /* FIXME test for interfaces with variant generic arguments */
+       mono_class_init (klass);
+       mono_class_init (klassc);
        
        if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
                if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
@@ -10017,8 +10066,6 @@ is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
        return FALSE;
 }
 
-static gboolean debug_check;
-
 MonoClass *
 mono_class_get_generic_type_definition (MonoClass *klass)
 {
@@ -10162,9 +10209,6 @@ can_access_type (MonoClass *access_klass, MonoClass *member_klass)
 {
        int access_level;
 
-       if (access_klass == member_klass)
-               return TRUE;
-
        if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
                return TRUE;
 
@@ -10313,15 +10357,26 @@ mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
 gboolean
 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
 {
-       gboolean res = mono_method_can_access_method_full (method, called, NULL);
-       if (!res) {
-               printf ("FAILED TO VERIFY %s calling %s\n", mono_method_full_name (method, 1), mono_method_full_name (called, 1));
-               debug_check = TRUE;
-               mono_method_can_access_method_full (method, called, NULL);
-               debug_check = FALSE;
+       int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+       if (!can) {
+               MonoClass *nested = method->klass->nested_in;
+               while (nested) {
+                       can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
+                       if (can)
+                               return TRUE;
+                       nested = nested->nested_in;
+               }
        }
-
-       return res;
+       /* 
+        * FIXME:
+        * with generics calls to explicit interface implementations can be expressed
+        * directly: the method is private, but we must allow it. This may be opening
+        * a hole or the generics code should handle this differently.
+        * Maybe just ensure the interface type is public.
+        */
+       if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
+               return TRUE;
+       return can;
 }
 
 /*
@@ -10338,12 +10393,10 @@ mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
 gboolean
 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
 {
-       if (debug_check) printf ("CHECKING %s -> %s (%p)\n", mono_method_full_name (method, 1), mono_method_full_name (called, 1), context_klass);
        MonoClass *access_class = method->klass;
        MonoClass *member_class = called->klass;
        int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
        if (!can) {
-               if (debug_check) printf ("\tcan_access_member failed\n");
                MonoClass *nested = access_class->nested_in;
                while (nested) {
                        can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
@@ -10351,18 +10404,13 @@ mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, Mono
                                break;
                        nested = nested->nested_in;
                }
-               if (!can && debug_check) printf ("\tcan_access_member nest check failed\n");
        }
 
        if (!can)
                return FALSE;
 
-       if (debug_check) printf ("\ttype checking %s(%p) -> %s(%p)\n", 
-               mono_type_get_full_name (access_class), access_class,
-               mono_type_get_full_name (member_class), member_class);
        can = can_access_type (access_class, member_class);
        if (!can) {
-               if (debug_check) printf ("\tcan_access_type check failed\n");
                MonoClass *nested = access_class->nested_in;
                while (nested) {
                        can = can_access_type (nested, member_class);
@@ -10370,7 +10418,6 @@ mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, Mono
                                break;
                        nested = nested->nested_in;
                }
-               if (!can && debug_check) printf ("\tcan_access_type nest check failed\n");
        }
 
        if (!can)
@@ -10378,10 +10425,8 @@ mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, Mono
 
        if (called->is_inflated) {
                MonoMethodInflated * infl = (MonoMethodInflated*)called;
-               if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst)) {
-                       if (debug_check) printf ("\tginst check failed\n");
+               if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
                        return FALSE;
-               }
        }
                
        return TRUE;