/* a typedef in disguise */
return mono_class_from_name (image, nspace, name);
case MONO_RESOLTION_SCOPE_MODULEREF:
- return mono_class_from_name (image->modules [idx - 1], nspace, name);
+ if (image->modules [idx-1])
+ return mono_class_from_name (image->modules [idx - 1], nspace, name);
+ else {
+ char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
+ char *human_name;
+
+ human_name = mono_stringify_assembly_name (&image->assembly->aname);
+ mono_loader_set_error_type_load (msg, human_name);
+ g_free (msg);
+ g_free (human_name);
+
+ return NULL;
+ }
case MONO_RESOLTION_SCOPE_TYPEREF: {
MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
GList *tmp;
/* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
g_assert (references == image->references);
g_assert (references [idx - 1]);
- if (references [idx - 1] == (gpointer)-1)
+
+ /* If the assembly did not load, register this as a type load exception */
+ if (references [idx - 1] == REFERENCE_MISSING){
+ MonoAssemblyName aname;
+ char *human_name;
+
+ mono_assembly_get_assemblyref (image, idx - 1, &aname);
+ human_name = mono_stringify_assembly_name (&aname);
+ mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
+ g_free (human_name);
+
return NULL;
+ }
return mono_class_from_name (references [idx - 1]->image, nspace, name);
}
class->class_size = 0;
if (class->parent) {
+ /* For generic instances, class->parent might not have been initialized */
+ mono_class_init (class->parent);
if (!class->parent->size_inited)
mono_class_setup_fields (class->parent);
class->instance_size += class->parent->instance_size;
field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
if (!field->type) {
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
- continue;
+ break;
}
if (mono_field_is_deleted (field))
continue;
class->instance_size = MAX (real_size, class->instance_size);
}
+ if (class->exception_type)
+ return;
mono_class_layout_fields (class);
}
}
/* useful until we keep track of gc-references in corlib etc. */
+#ifdef HAVE_SGEN_GC
+#define IS_GC_REFERENCE(t) FALSE
+#else
#define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
+#endif
/*
* mono_class_layout_fields:
MonoGenericContext *context;
guint32 type_token;
int onum = 0;
+ gboolean ok = TRUE;
if (class->vtable)
return;
if (class->image->dynamic)
mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
- else
- mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+ else {
+ /* The following call fails if there are missing methods in the type */
+ ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
+ }
- mono_class_setup_vtable_general (class, overrides, onum);
+ if (ok)
+ mono_class_setup_vtable_general (class, overrides, onum);
+
g_free (overrides);
mono_loader_unlock ();
+
+ return;
}
/*
int j;
for (j = 0; j < k->method.count; ++j) {
MonoMethod *m1 = k->methods [j];
+ MonoMethodSignature *cmsig, *m1sig;
+
if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
continue;
+
+ cmsig = mono_method_signature (cm);
+ m1sig = mono_method_signature (m1);
+
+ if (!cmsig || !m1sig) {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ return;
+ }
+
if (!strcmp(cm->name, m1->name) &&
- mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
+ mono_metadata_signature_equal (cmsig, m1sig)) {
/* CAS - SecurityAction.InheritanceDemand */
if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
* compute the instance_size, class_size and other infos that cannot be
* computed at mono_class_get() time. Also compute a generic vtable and
* the method slot numbers. We use this infos later to create a domain
- * specific vtable.
+ * specific vtable.
+ *
+ * Returns TRUE on success or FALSE if there was a problem in loading
+ * the type (incorrect assemblies, missing assemblies, methods, etc).
*/
-void
+gboolean
mono_class_init (MonoClass *class)
{
int i;
MonoCachedClassInfo cached_info;
gboolean has_cached_info;
-
+ int class_init_ok = TRUE;
+
g_assert (class);
if (class->inited)
- return;
+ return TRUE;
/*g_print ("Init class %s\n", class->name);*/
if (class->inited) {
mono_loader_unlock ();
/* Somebody might have gotten in before us */
- return;
+ return TRUE;
}
if (class->init_pending) {
class->has_static_refs = cached_info.has_static_refs;
}
else
- if (!class->size_inited)
+ if (!class->size_inited){
mono_class_setup_fields (class);
+ if (class->exception_type || mono_loader_get_last_error ()){
+ class_init_ok = FALSE;
+ goto leave;
+ }
+ }
+
/* initialize method pointers */
if (class->rank) {
}
else {
mono_class_setup_vtable (class);
-
+
+ if (class->exception_type || mono_loader_get_last_error ()){
+ class_init_ok = FALSE;
+ goto leave;
+ }
+
class->ghcimpl = 1;
if (class->parent) {
MonoMethod *cmethod = class->vtable [ghc_slot];
setup_interface_offsets (class, 0);
}
+ leave:
class->inited = 1;
class->init_pending = 0;
-
+
mono_loader_unlock ();
if (mono_debugger_class_init_func)
mono_debugger_class_init_func (class);
+
+ return class_init_ok;
}
/*
if (cols [MONO_TYPEDEF_EXTENDS]) {
parent = mono_class_get_full (
image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
+ if (parent == NULL){
+ g_hash_table_remove (image->class_cache, GUINT_TO_POINTER (type_token));
+ mono_loader_unlock ();
+ return NULL;
+ }
}
/* do this early so it's available for interfaces in setup_mono_type () */
result->parent = NULL; /* no parent for PTR types */
result->name_space = "System";
result->name = "MonoFNPtrFakeClass";
- result->image = NULL; /* need to fix... */
+ result->image = mono_defaults.corlib; /* need to fix... */
result->inited = TRUE;
result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
/* Can pointers get boxed? */
}
case MONO_EXCEPTION_TYPE_LOAD:
return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
- /* TODO - handle other class related failures */
- default:
+
+ default: {
+ MonoLoaderError *error;
+ MonoException *ex;
+
+ error = mono_loader_get_last_error ();
+ if (error != NULL){
+ ex = mono_loader_error_prepare_exception (error);
+ return ex;
+ }
+
+ /* TODO - handle other class related failures */
return NULL;
}
+ }
}