#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#if !HOST_WIN32
-#include <mono/io-layer/atomic.h>
-#endif
#include <mono/metadata/image.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/metadata.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/utils/mono-memory-model.h>
+#include <mono/utils/atomic.h>
+#include <mono/utils/bsearch.h>
+
MonoStats mono_stats;
gboolean mono_print_vtable = FALSE;
/* Function supplied by the runtime to find classes by name using information from the AOT file */
static MonoGetClassFromName get_class_from_name = NULL;
-static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
+static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
-void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
/*
guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
- if (strcmp (nname, name) == 0)
- return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
+ if (strcmp (nname, name) == 0) {
+ MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
+ if (!mono_error_ok (&error)) {
+ mono_loader_set_error_from_mono_error (&error);
+ mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
+ return NULL;
+ }
+ return res;
+ }
i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
}
{
switch (type->type) {
case MONO_TYPE_VOID:
- case MONO_TYPE_TYPEDBYREF:
+ //case MONO_TYPE_TYPEDBYREF:
return FALSE;
}
return TRUE;
MonoGenericContainer *container = NULL;
MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
- if (class->size_inited)
+ /*
+ * FIXME: We have a race condition here. It's possible that this function returns
+ * to its caller with `instance_size` set to `0` instead of the actual size. This
+ * is not a problem when the function is called recursively on the same class,
+ * because the size will be initialized by the outer invocation. What follows is a
+ * description of how it can occur in other cases, too. There it is a problem,
+ * because it can lead to the GC being asked to allocate an object of size `0`,
+ * which SGen chokes on. The race condition is triggered infrequently by
+ * `tests/sgen-suspend.cs`.
+ *
+ * This function is called for a class whenever one of its subclasses is inited.
+ * For example, it's called for every subclass of Object. What it does is this:
+ *
+ * if (class->setup_fields_called)
+ * return;
+ * ...
+ * class->instance_size = 0;
+ * ...
+ * class->setup_fields_called = 1;
+ * ... critical point
+ * class->instance_size = actual_instance_size;
+ *
+ * The last two steps are sometimes reversed, but that only changes the way in which
+ * the race condition works.
+ *
+ * Assume thread A goes through this function and makes it to the critical point.
+ * Now thread B runs the function and, since `setup_fields_called` is set, returns
+ * immediately, but `instance_size` is incorrect.
+ *
+ * The other case looks like this:
+ *
+ * if (class->setup_fields_called)
+ * return;
+ * ... critical point X
+ * class->instance_size = 0;
+ * ... critical point Y
+ * class->instance_size = actual_instance_size;
+ * ...
+ * class->setup_fields_called = 1;
+ *
+ * Assume thread A goes through the function and makes it to critical point X. Now
+ * thread B runs through the whole of the function, returning, assuming
+ * `instance_size` is set. At that point thread A gets to run and makes it to
+ * critical point Y, at which time `instance_size` is `0` again, invalidating thread
+ * B's assumption.
+ */
+ if (class->setup_fields_called)
return;
if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
if (explicit_size && real_size) {
class->instance_size = MAX (real_size, class->instance_size);
}
- class->size_inited = 1;
class->blittable = blittable;
mono_memory_barrier ();
+ class->size_inited = 1;
class->fields_inited = 1;
+ class->setup_fields_called = 1;
return;
}
blittable = FALSE;
/* Prevent infinite loops if the class references itself */
- class->size_inited = 1;
+ class->setup_fields_called = 1;
if (class->generic_container) {
container = class->generic_container;
class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
}
+ mono_memory_barrier ();
class->size_inited = 1;
/*
class->methods = methods;
- if (mono_debugger_class_loaded_methods_func)
- mono_debugger_class_loaded_methods_func (class);
-
mono_loader_unlock ();
}
/*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
int
mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
- MonoClass **result = bsearch (
+ MonoClass **result = mono_binary_search (
itf,
klass->interfaces_packed,
klass->interface_offsets_count,
* We collect the types needed to build the
* instantiations in interfaces at intervals of 3/5, because 3/5 are
* the generic interfaces needed to implement.
+ *
+ * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
+ * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
*/
- nifaces = generic_ireadonlylist_class ? 5 : 3;
if (eclass->valuetype) {
+ nifaces = generic_ireadonlylist_class ? 5 : 3;
fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
/* IList, ICollection, IEnumerable, IReadOnlyList`1 */
int idepth = eclass->idepth;
if (!internal_enumerator)
idepth--;
+ nifaces = generic_ireadonlylist_class ? 2 : 3;
// FIXME: This doesn't seem to work/required for generic params
if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
- interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
- if (generic_ireadonlylist_class) {
- interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
- interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+
+ if (eclass->valuetype) {
+ interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
+ if (generic_ireadonlylist_class) {
+ interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
+ interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+ }
+ } else {
+ if (!generic_ireadonlylist_class)
+ interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
}
}
if (internal_enumerator) {
if (class->vtable)
return;
- if (mono_debug_using_mono_debugger ())
- /* The debugger currently depends on this */
- mono_class_setup_methods (class);
-
if (MONO_CLASS_IS_INTERFACE (class)) {
/* This sets method->slot for all methods if this is an interface */
mono_class_setup_methods (class);
mono_secman_inheritancedemand_method (cm, im);
}
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
+
TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
char *body_name = mono_method_full_name (cm, TRUE);
mono_secman_inheritancedemand_method (cm, im);
}
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, im);
-
+
TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
char *body_name = mono_method_full_name (cm, TRUE);
int i, max_vtsize = 0, max_iid, cur_slot = 0;
GPtrArray *ifaces = NULL;
GHashTable *override_map = NULL;
- gboolean security_enabled = mono_is_security_manager_active ();
+ gboolean security_enabled = mono_security_enabled ();
MonoMethod *cm;
gpointer class_iter;
#if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, vtable [dslot], decl);
}
}
mono_secman_inheritancedemand_method (cm, m1);
}
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, cm, m1);
slot = mono_method_get_vtable_slot (m1);
mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
}
}
mono_class_setup_vtable (method->klass);
if (method->klass->exception_type)
return -1;
+ if (method->slot == -1) {
+ MonoClass *gklass;
+ int i;
+
+ /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
+ g_assert (method->klass->generic_class);
+ gklass = method->klass->generic_class->container_class;
+ mono_class_setup_methods (method->klass);
+ g_assert (method->klass->methods);
+ for (i = 0; i < method->klass->method.count; ++i) {
+ if (method->klass->methods [i] == method)
+ break;
+ }
+ g_assert (i < method->klass->method.count);
+ g_assert (gklass->methods);
+ method->slot = gklass->methods [i]->slot;
+ }
g_assert (method->slot != -1);
}
return method->slot;
}
/* CAS - SecurityAction.InheritanceDemand */
- if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
+ if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
mono_secman_inheritancedemand_class (class, class->parent);
}
setup_interface_offsets (class, 0, TRUE);
}
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
+ if (mono_security_core_clr_enabled ())
mono_security_core_clr_check_inheritance (class);
if (mono_loader_get_last_error ()) {
#ifndef DISABLE_COM
/*
- * COM initialization (using mono_init_com_types) is delayed until needed.
+ * COM initialization is delayed until needed.
* However when a [ComImport] attribute is present on a type it will trigger
* the initialization. This is not a problem unless the BCL being executed
* lacks the types that COM depends on (e.g. Variant on Silverlight).
init_com_from_comimport (MonoClass *class)
{
/* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
- if ((mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)) {
+ if (mono_security_core_clr_enabled ()) {
/* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
if (!mono_security_core_clr_determine_platform_image (class->image)) {
/* but it can not be made available for application (i.e. user code) since all COM calls
return;
}
}
+
/* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
- mono_init_com_types ();
}
#endif /*DISABLE_COM*/
if (MONO_CLASS_IS_IMPORT (class)) {
init_com_from_comimport (class);
if (parent == mono_defaults.object_class)
- parent = mono_defaults.com_object_class;
+ parent = mono_class_get_com_object_class ();
}
#endif
if (!parent) {
return;
}
+#ifndef DISABLE_REMOTING
class->marshalbyref = parent->marshalbyref;
class->contextbound = parent->contextbound;
+#endif
+
class->delegate = parent->delegate;
- if (MONO_CLASS_IS_IMPORT (class))
- class->is_com_object = 1;
- else
- class->is_com_object = parent->is_com_object;
+
+ if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
+ mono_class_set_is_com_object (class);
if (system_namespace) {
+#ifndef DISABLE_REMOTING
if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
class->marshalbyref = 1;
if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
class->contextbound = 1;
-
+#endif
if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
class->delegate = 1;
}
* - supertypes: array of classes: each element has a class in the hierarchy
* starting from @class up to System.Object
*
- * LOCKING: this assumes the loader lock is held
+ * LOCKING: This function is atomic, in case of contention we waste memory.
*/
void
mono_class_setup_supertypes (MonoClass *class)
int ms;
MonoClass **supertypes;
- if (class->supertypes)
+ mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
+ if (supertypes)
return;
if (class->parent && !class->parent->supertypes)
return TRUE;
}
+static void
+mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
+{
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
+ mono_error_set_type_load_class (error, class, msg);
+}
+
+static void
+mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
+{
+ MonoLoaderError *lerror = mono_loader_get_last_error ();
+
+ if (lerror) {
+ set_failure_from_loader_error (class, lerror);
+ mono_error_set_from_loader_error (error);
+ if (msg)
+ g_free (msg);
+ } else {
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
+ mono_error_set_type_load_class (error, class, msg);
+ }
+}
+
/**
* mono_class_create_from_typedef:
* @image: image where the token is valid
* @type_token: typedef token
+ * @error: used to return any error found while creating the type
*
* Create the MonoClass* representing the specified type token.
* @type_token must be a TypeDef token.
* FIXME: don't return NULL on failure, just the the caller figure it out.
*/
static MonoClass *
-mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
+mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
{
MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
MonoClass *class, *parent = NULL;
guint32 field_last, method_last;
guint32 nesting_tokeen;
- if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows)
+ mono_error_init (error);
+
+ if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
+ mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
+ g_assert (!mono_loader_get_last_error ());
return NULL;
+ }
mono_loader_lock ();
if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
mono_loader_unlock ();
+ g_assert (!mono_loader_get_last_error ());
return class;
}
}
parent = mono_class_get_full (image, parent_token, context);
- if (parent == NULL){
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load parent type"));
- mono_loader_clear_error ();
+ if (parent == NULL) {
+ mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
goto parent_failure;
}
for (tmp = parent; tmp; tmp = tmp->parent) {
if (tmp == class) {
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cycle found while resolving parent"));
+ mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
goto parent_failure;
}
if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Parent extends generic instance of this type"));
+ mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
goto parent_failure;
}
}
* so it has to come after setup_mono_type ().
*/
if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
- class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
- if (!class->nested_in) {
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load nestedin type"));
+ class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
+ if (!mono_error_ok (error)) {
+ /*FIXME implement a mono_class_set_failure_from_mono_error */
+ mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+ g_assert (!mono_loader_get_last_error ());
return NULL;
}
}
if (!class->enumtype) {
if (!mono_metadata_interfaces_from_typedef_full (
image, type_token, &interfaces, &icount, FALSE, context)){
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load interfaces"));
+ mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
return NULL;
if (!enum_basetype) {
/*set it to a default value as the whole runtime can't handle this to be null*/
class->cast_class = class->element_class = mono_defaults.int32_class;
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
+ mono_class_set_failure_and_error (class, error, "Could not enum basetype");
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+ g_assert (!mono_loader_get_last_error ());
return NULL;
}
class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
* work.
*/
if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
- char *class_name = g_strdup_printf("%s.%s", class->name_space, class->name);
- char *error = concat_two_strings_with_zero (class->image, class_name, class->image->assembly_name);
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, error);
- g_free (class_name);
+ mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+ g_assert (!mono_loader_get_last_error ());
return NULL;
}
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_OK);
+ g_assert (!mono_loader_get_last_error ());
return class;
mono_class_setup_mono_type (class);
mono_loader_unlock ();
mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
+ g_assert (!mono_loader_get_last_error ());
return NULL;
-
}
/** is klass Nullable<T>? */
*/
klass->instance_size = gklass->instance_size;
klass->sizes.class_size = gklass->sizes.class_size;
+ mono_memory_barrier ();
klass->size_inited = 1;
}
}
/*Init these fields to sane values*/
klass->min_align = 1;
klass->instance_size = sizeof (gpointer);
+ mono_memory_barrier ();
klass->size_inited = 1;
mono_class_setup_supertypes (klass);
{
if (!klass->inited)
mono_class_init (klass);
+ /* This can happen with dynamically created types */
+ if (!klass->fields_inited)
+ mono_class_setup_fields_locking (klass);
/* in arrays, sizes.class_size is unioned with element_size
* and arrays have no static fields
switch (type_token & 0xff000000){
case MONO_TOKEN_TYPE_DEF:
- class = mono_class_create_from_typedef (image, type_token);
+ class = mono_class_create_from_typedef (image, type_token, &error);
+ if (!mono_error_ok (&error)) {
+ mono_loader_set_error_from_mono_error (&error);
+ /*FIXME don't swallow the error message*/
+ mono_error_cleanup (&error);
+ return NULL;
+ }
break;
case MONO_TOKEN_TYPE_REF:
class = mono_class_from_typeref (image, type_token);
* @name: the type short name.
*
* Obtains a MonoClass with a given namespace and a given name which
- * is located in the given MonoImage.
+ * is located in the given MonoImage.
+ *
+ * To reference nested classes, use the "/" character as a separator.
+ * For example use "Foo/Bar" to reference the class Bar that is nested
+ * inside Foo, like this: "class Foo { class Bar {} }".
*/
MonoClass *
mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
return class;
}
-/*FIXME test for interfaces with variant generic arguments*/
+/**
+ * mono_class_is_subclass_of:
+ * @klass: class to probe if it is a subclass of another one
+ * @klassc: the class we suspect is the base class
+ * @check_interfaces: whether we should perform interface checks
+ *
+ * This method determines whether @klass is a subclass of @klassc.
+ *
+ * If the @check_interfaces flag is set, then if @klassc is an interface
+ * this method return true if the @klass implements the interface or
+ * if @klass is an interface, if one of its base classes is @klass.
+ *
+ * If @check_interfaces is false then, then if @klass is not an interface
+ * then it returns true if the @klass is a subclass of @klassc.
+ *
+ * if @klass is an interface and @klassc is System.Object, then this function
+ * return true.
+ *
+ */
gboolean
mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
gboolean check_interfaces)
{
+/*FIXME test for interfaces with variant generic arguments*/
+
if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
return TRUE;
MonoMethod** method;
if (!iter)
return NULL;
- if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
+ if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
if (!*iter) {
mono_class_setup_methods (klass);
/*
MonoClass*
mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
{
+ MonoError error;
GList *item;
int i;
MonoClass* nclass;
guint32 cols [MONO_NESTED_CLASS_SIZE];
mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
- nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
- if (!nclass) {
- mono_loader_clear_error ();
+ nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
+ if (!mono_error_ok (&error)) {
+ /*FIXME don't swallow the error message*/
+ mono_error_cleanup (&error);
+
i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
continue;
}
return NULL;
}
+
+/**
+ * mono_class_is_delegate
+ * @klass: the MonoClass to act on
+ *
+ * Returns: true if the MonoClass represents a System.Delegate.
+ */
+mono_bool
+mono_class_is_delegate (MonoClass *klass)
+{
+ return klass->delegate;
+}
+
+/**
+ * mono_class_implements_interface
+ * @klass: The MonoClass to act on
+ * @interface: The interface to check if @klass implements.
+ *
+ * Returns: true if @klass implements @interface.
+ */
+mono_bool
+mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
+{
+ return mono_class_is_assignable_from (iface, klass);
+}
+
/**
* mono_field_get_name:
* @field: the MonoClassField to act on
gpointer exception_data = mono_class_get_exception_data (klass);
switch (klass->exception_type) {
+#ifndef DISABLE_SECURITY
case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
MonoDomain *domain = mono_domain_get ();
MonoSecurityManager* secman = mono_security_manager_get_methods ();
mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
return (MonoException*) exc;
}
+#endif
case MONO_EXCEPTION_TYPE_LOAD: {
MonoString *name;
MonoException *ex;
/* extra safety under CoreCLR - the runtime does not verify the strongname signatures
* anywhere so untrusted friends are not safe to access platform's code internals */
- if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
+ if (mono_security_core_clr_enabled ()) {
if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
return FALSE;
}
return TRUE;
}
+/*
+ * mono_class_can_access_class:
+ * @source_class: The source class
+ * @target_class: The accessed class
+ *
+ * This function returns is @target_class is visible to @source_class
+ *
+ * Returns: TRUE if source have proper visibility and acessibility to target
+ */
+gboolean
+mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
+{
+ return can_access_type (source_class, target_class);
+}
+
/**
* mono_type_is_valid_enum_basetype:
* @type: The MonoType to check
/* FIELD signature == 0x06 */
g_assert (*sig == 0x06);
field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
- if (!field->type) {
- MonoLoaderError *lerror = mono_loader_get_last_error ();
-
- mono_error_set_type_load_class (error, class, "Could not load field %s type", field->name);
- if (lerror)
- set_failure_from_loader_error (class, lerror);
- else
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
- mono_loader_clear_error ();
- }
+ if (!field->type)
+ mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
}
}
}
return NULL;
}
+
+char*
+mono_class_full_name (MonoClass *klass)
+{
+ return mono_type_full_name (&klass->byval_arg);
+}
+