[mini] Always emit safepoints, except WASM
[mono-project.git] / mono / metadata / class.c
blobbee36d01181a7841d90ea1cf57c4d98856d10172
1 /**
2 * \file
3 * Class management for the Mono runtime
5 * Author:
6 * Miguel de Icaza (miguel@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13 #include <config.h>
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/metadata.h>
27 #include <mono/metadata/metadata-internals.h>
28 #include <mono/metadata/profiler-private.h>
29 #include <mono/metadata/tabledefs.h>
30 #include <mono/metadata/tokentype.h>
31 #include <mono/metadata/class-init.h>
32 #include <mono/metadata/class-internals.h>
33 #include <mono/metadata/object.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/mono-endian.h>
36 #include <mono/metadata/debug-helpers.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/exception.h>
39 #include <mono/metadata/security-manager.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/attrdefs.h>
42 #include <mono/metadata/gc-internals.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-debug.h>
45 #include <mono/utils/mono-counters.h>
46 #include <mono/utils/mono-string.h>
47 #include <mono/utils/mono-error-internals.h>
48 #include <mono/utils/mono-logger-internals.h>
49 #include <mono/utils/mono-memory-model.h>
50 #include <mono/utils/atomic.h>
51 #include <mono/utils/unlocked.h>
52 #include <mono/utils/bsearch.h>
53 #include <mono/utils/checked-build.h>
55 MonoStats mono_stats;
57 /* Statistics */
58 extern gint32 mono_inflated_methods_size;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name = NULL;
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
65 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
66 static guint32 mono_field_resolve_flags (MonoClassField *field);
68 static MonoProperty* mono_class_get_property_from_name_internal (MonoClass *klass, const char *name);
70 static gboolean mono_class_is_subclass_of_internal (MonoClass *klass, MonoClass *klassc, gboolean check_interfaces);
72 GENERATE_GET_CLASS_WITH_CACHE (valuetype, "System", "ValueType")
73 GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref, "System.Runtime.InteropServices", "HandleRef")
75 static
76 MonoImage *
77 mono_method_get_image (MonoMethod *method)
79 return m_class_get_image (method->klass);
82 /**
83 * mono_class_from_typeref:
84 * \param image a MonoImage
85 * \param type_token a TypeRef token
87 * Creates the \c MonoClass* structure representing the type defined by
88 * the typeref token valid inside \p image.
89 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
90 * not be loaded.
92 MonoClass *
93 mono_class_from_typeref (MonoImage *image, guint32 type_token)
95 ERROR_DECL (error);
96 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, error);
97 g_assert (mono_error_ok (error)); /*FIXME proper error handling*/
98 return klass;
102 * mono_class_from_typeref_checked:
103 * \param image a MonoImage
104 * \param type_token a TypeRef token
105 * \param error error return code, if any.
107 * Creates the \c MonoClass* structure representing the type defined by
108 * the typeref token valid inside \p image.
110 * \returns The \c MonoClass* representing the typeref token, NULL if it could
111 * not be loaded with the \p error value filled with the information about the
112 * error.
114 MonoClass *
115 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
117 guint32 cols [MONO_TYPEREF_SIZE];
118 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
119 guint32 idx;
120 const char *name, *nspace;
121 MonoClass *res = NULL;
122 MonoImage *module;
124 error_init (error);
126 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
127 return NULL;
129 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
131 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
132 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
134 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
135 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
136 case MONO_RESOLUTION_SCOPE_MODULE:
138 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
139 This is not the observed behavior of existing implementations.
140 The defacto behavior is that it's just a typedef in disguise.
142 /* a typedef in disguise */
143 res = mono_class_from_name_checked (image, nspace, name, error);
144 goto done;
146 case MONO_RESOLUTION_SCOPE_MODULEREF:
147 module = mono_image_load_module_checked (image, idx, error);
148 if (module)
149 res = mono_class_from_name_checked (module, nspace, name, error);
150 goto done;
152 case MONO_RESOLUTION_SCOPE_TYPEREF: {
153 MonoClass *enclosing;
154 GList *tmp;
156 if (idx == mono_metadata_token_index (type_token)) {
157 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
158 return NULL;
161 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
162 return_val_if_nok (error, NULL);
164 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
165 if (m_class_is_nested_classes_inited (enclosing) && nested_classes) {
166 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
167 for (tmp = nested_classes; tmp; tmp = tmp->next) {
168 res = (MonoClass *)tmp->data;
169 if (strcmp (m_class_get_name (res), name) == 0)
170 return res;
172 } else {
173 MonoImage *enclosing_image = m_class_get_image (enclosing);
174 guint32 enclosing_type_token = m_class_get_type_token (enclosing);
175 /* Don't call mono_class_init_internal as we might've been called by it recursively */
176 int i = mono_metadata_nesting_typedef (enclosing_image, enclosing_type_token, 1);
177 while (i) {
178 guint32 class_nested = mono_metadata_decode_row_col (&enclosing_image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
179 guint32 string_offset = mono_metadata_decode_row_col (&enclosing_image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
180 const char *nname = mono_metadata_string_heap (enclosing_image, string_offset);
182 if (strcmp (nname, name) == 0)
183 return mono_class_create_from_typedef (enclosing_image, MONO_TOKEN_TYPE_DEF | class_nested, error);
185 i = mono_metadata_nesting_typedef (enclosing_image, enclosing_type_token, i + 1);
188 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
189 goto done;
191 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
192 break;
195 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
196 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
197 return NULL;
200 if (!image->references || !image->references [idx - 1])
201 mono_assembly_load_reference (image, idx - 1);
202 g_assert (image->references [idx - 1]);
204 /* If the assembly did not load, register this as a type load exception */
205 if (image->references [idx - 1] == REFERENCE_MISSING){
206 MonoAssemblyName aname;
207 char *human_name;
209 mono_assembly_get_assemblyref (image, idx - 1, &aname);
210 human_name = mono_stringify_assembly_name (&aname);
211 gboolean refonly = FALSE;
212 if (image->assembly)
213 refonly = mono_asmctx_get_kind (&image->assembly->context) == MONO_ASMCTX_REFONLY;
214 mono_error_set_simple_file_not_found (error, human_name, refonly);
215 g_free (human_name);
216 return NULL;
219 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
221 done:
222 /* Generic case, should be avoided for when a better error is possible. */
223 if (!res && mono_error_ok (error)) {
224 char *name = mono_class_name_from_token (image, type_token);
225 char *assembly = mono_assembly_name_from_token (image, type_token);
226 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x from typeref (expected class '%s' in assembly '%s')", type_token, name, assembly);
228 return res;
232 static void *
233 mono_image_memdup (MonoImage *image, void *data, guint size)
235 void *res = mono_image_alloc (image, size);
236 memcpy (res, data, size);
237 return res;
240 /* Copy everything mono_metadata_free_array free. */
241 MonoArrayType *
242 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
244 if (image) {
245 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
246 if (a->sizes)
247 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
248 if (a->lobounds)
249 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
250 } else {
251 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
252 if (a->sizes)
253 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
254 if (a->lobounds)
255 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
257 return a;
260 /* Copy everything mono_metadata_free_method_signature free. */
261 MonoMethodSignature*
262 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
264 int i;
266 sig = mono_metadata_signature_dup_full (image, sig);
268 sig->ret = mono_metadata_type_dup (image, sig->ret);
269 for (i = 0; i < sig->param_count; ++i)
270 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
272 return sig;
275 static void
276 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
278 MonoAssembly *ta = m_class_get_image (klass)->assembly;
279 char *name;
281 name = mono_stringify_assembly_name (&ta->aname);
282 g_string_append_printf (str, ", %s", name);
283 g_free (name);
286 static inline void
287 mono_type_name_check_byref (MonoType *type, GString *str)
289 if (type->byref)
290 g_string_append_c (str, '&');
294 * mono_identifier_escape_type_name_chars:
295 * \param str a destination string
296 * \param identifier an IDENTIFIER in internal form
298 * \returns \p str
300 * The displayed form of the identifier is appended to str.
302 * The displayed form of an identifier has the characters ,+&*[]\
303 * that have special meaning in type names escaped with a preceeding
304 * backslash (\) character.
306 static GString*
307 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
309 if (!identifier)
310 return str;
312 size_t n = str->len;
313 // reserve space for common case: there will be no escaped characters.
314 g_string_set_size(str, n + strlen(identifier));
315 g_string_set_size(str, n);
317 for (const char* s = identifier; *s != 0 ; s++) {
318 switch (*s) {
319 case ',':
320 case '+':
321 case '&':
322 case '*':
323 case '[':
324 case ']':
325 case '\\':
326 g_string_append_c (str, '\\');
327 g_string_append_c (str, *s);
328 break;
329 default:
330 g_string_append_c (str, *s);
331 break;
334 return str;
337 static void
338 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
339 MonoTypeNameFormat format)
341 MonoClass *klass;
343 switch (type->type) {
344 case MONO_TYPE_ARRAY: {
345 int i, rank = type->data.array->rank;
346 MonoTypeNameFormat nested_format;
348 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
349 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
351 mono_type_get_name_recurse (
352 m_class_get_byval_arg (type->data.array->eklass), str, FALSE, nested_format);
353 g_string_append_c (str, '[');
354 if (rank == 1)
355 g_string_append_c (str, '*');
356 for (i = 1; i < rank; i++)
357 g_string_append_c (str, ',');
358 g_string_append_c (str, ']');
360 mono_type_name_check_byref (type, str);
362 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
363 _mono_type_get_assembly_name (type->data.array->eklass, str);
364 break;
366 case MONO_TYPE_SZARRAY: {
367 MonoTypeNameFormat nested_format;
369 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
370 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
372 mono_type_get_name_recurse (
373 m_class_get_byval_arg (type->data.klass), str, FALSE, nested_format);
374 g_string_append (str, "[]");
376 mono_type_name_check_byref (type, str);
378 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
379 _mono_type_get_assembly_name (type->data.klass, str);
380 break;
382 case MONO_TYPE_PTR: {
383 MonoTypeNameFormat nested_format;
385 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
386 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
388 mono_type_get_name_recurse (
389 type->data.type, str, FALSE, nested_format);
390 g_string_append_c (str, '*');
392 mono_type_name_check_byref (type, str);
394 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
395 _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type->data.type), str);
396 break;
398 case MONO_TYPE_VAR:
399 case MONO_TYPE_MVAR:
400 if (!mono_generic_param_name (type->data.generic_param))
401 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
402 else
403 g_string_append (str, mono_generic_param_name (type->data.generic_param));
405 mono_type_name_check_byref (type, str);
407 break;
408 default:
409 klass = mono_class_from_mono_type_internal (type);
410 if (m_class_get_nested_in (klass)) {
411 mono_type_get_name_recurse (
412 m_class_get_byval_arg (m_class_get_nested_in (klass)), str, TRUE, format);
413 if (format == MONO_TYPE_NAME_FORMAT_IL)
414 g_string_append_c (str, '.');
415 else
416 g_string_append_c (str, '+');
417 } else if (*m_class_get_name_space (klass)) {
418 const char *klass_name_space = m_class_get_name_space (klass);
419 if (format == MONO_TYPE_NAME_FORMAT_IL)
420 g_string_append (str, klass_name_space);
421 else
422 mono_identifier_escape_type_name_chars (str, klass_name_space);
423 g_string_append_c (str, '.');
425 const char *klass_name = m_class_get_name (klass);
426 if (format == MONO_TYPE_NAME_FORMAT_IL) {
427 const char *s = strchr (klass_name, '`');
428 gssize len = s ? (s - klass_name) : (gssize)strlen (klass_name);
429 g_string_append_len (str, klass_name, len);
430 } else {
431 mono_identifier_escape_type_name_chars (str, klass_name);
433 if (is_recursed)
434 break;
435 if (mono_class_is_ginst (klass)) {
436 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
437 MonoGenericInst *inst = gclass->context.class_inst;
438 MonoTypeNameFormat nested_format;
439 int i;
441 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
442 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
444 if (format == MONO_TYPE_NAME_FORMAT_IL)
445 g_string_append_c (str, '<');
446 else
447 g_string_append_c (str, '[');
448 for (i = 0; i < inst->type_argc; i++) {
449 MonoType *t = inst->type_argv [i];
451 if (i)
452 g_string_append_c (str, ',');
453 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
454 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
455 g_string_append_c (str, '[');
456 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
457 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
458 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
459 g_string_append_c (str, ']');
461 if (format == MONO_TYPE_NAME_FORMAT_IL)
462 g_string_append_c (str, '>');
463 else
464 g_string_append_c (str, ']');
465 } else if (mono_class_is_gtd (klass) &&
466 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
467 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
468 int i;
470 if (format == MONO_TYPE_NAME_FORMAT_IL)
471 g_string_append_c (str, '<');
472 else
473 g_string_append_c (str, '[');
474 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
475 if (i)
476 g_string_append_c (str, ',');
477 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
479 if (format == MONO_TYPE_NAME_FORMAT_IL)
480 g_string_append_c (str, '>');
481 else
482 g_string_append_c (str, ']');
485 mono_type_name_check_byref (type, str);
487 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
488 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
489 _mono_type_get_assembly_name (klass, str);
490 break;
495 * mono_type_get_name_full:
496 * \param type a type
497 * \param format the format for the return string.
500 * \returns The string representation in a number of formats:
502 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
503 * returned in the format required by \c System.Reflection, this is the
504 * inverse of mono_reflection_parse_type().
506 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
507 * be used by the IL assembler.
509 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
511 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
513 char*
514 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
516 GString* result;
518 result = g_string_new ("");
520 mono_type_get_name_recurse (type, result, FALSE, format);
522 return g_string_free (result, FALSE);
526 * mono_type_get_full_name:
527 * \param class a class
529 * \returns The string representation for type as required by System.Reflection.
530 * The inverse of mono_reflection_parse_type().
532 char *
533 mono_type_get_full_name (MonoClass *klass)
535 return mono_type_get_name_full (m_class_get_byval_arg (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
539 * mono_type_get_name:
540 * \param type a type
541 * \returns The string representation for type as it would be represented in IL code.
543 char*
544 mono_type_get_name (MonoType *type)
546 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
550 * mono_type_get_underlying_type:
551 * \param type a type
552 * \returns The \c MonoType for the underlying integer type if \p type
553 * is an enum and byref is false, otherwise the type itself.
555 MonoType*
556 mono_type_get_underlying_type (MonoType *type)
558 if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass) && !type->byref)
559 return mono_class_enum_basetype_internal (type->data.klass);
560 if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class) && !type->byref)
561 return mono_class_enum_basetype_internal (type->data.generic_class->container_class);
562 return type;
566 * mono_class_is_open_constructed_type:
567 * \param type a type
569 * \returns TRUE if type represents a generics open constructed type.
570 * IOW, not all type parameters required for the instantiation have
571 * been provided or it's a generic type definition.
573 * An open constructed type means it's a non realizable type. Not to
574 * be mixed up with an abstract type - we can't cast or dispatch to
575 * an open type, for example.
577 gboolean
578 mono_class_is_open_constructed_type (MonoType *t)
580 switch (t->type) {
581 case MONO_TYPE_VAR:
582 case MONO_TYPE_MVAR:
583 return TRUE;
584 case MONO_TYPE_SZARRAY:
585 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t->data.klass));
586 case MONO_TYPE_ARRAY:
587 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t->data.array->eklass));
588 case MONO_TYPE_PTR:
589 return mono_class_is_open_constructed_type (t->data.type);
590 case MONO_TYPE_GENERICINST:
591 return t->data.generic_class->context.class_inst->is_open;
592 case MONO_TYPE_CLASS:
593 case MONO_TYPE_VALUETYPE:
594 return mono_class_is_gtd (t->data.klass);
595 default:
596 return FALSE;
601 This is a simple function to catch the most common bad instances of generic types.
602 Specially those that might lead to further failures in the runtime.
604 gboolean
605 mono_type_is_valid_generic_argument (MonoType *type)
607 switch (type->type) {
608 case MONO_TYPE_VOID:
609 case MONO_TYPE_TYPEDBYREF:
610 return FALSE;
611 case MONO_TYPE_VALUETYPE:
612 return !m_class_is_byreflike (type->data.klass);
613 default:
614 return TRUE;
618 static gboolean
619 can_inflate_gparam_with (MonoGenericParam *gparam, MonoType *type)
621 if (!mono_type_is_valid_generic_argument (type))
622 return FALSE;
623 /* Avoid inflating gparams with valuetype constraints with ref types during gsharing */
624 MonoGenericParamInfo *info = mono_generic_param_info (gparam);
625 if (info && (info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)) {
626 if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
627 MonoGenericParam *inst_gparam = type->data.generic_param;
628 if (inst_gparam->gshared_constraint && inst_gparam->gshared_constraint->type == MONO_TYPE_OBJECT)
629 return FALSE;
632 return TRUE;
635 static MonoType*
636 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
638 error_init (error);
640 switch (type->type) {
641 case MONO_TYPE_MVAR: {
642 MonoType *nt;
643 int num = mono_type_get_generic_param_num (type);
644 MonoGenericInst *inst = context->method_inst;
645 if (!inst)
646 return NULL;
647 MonoGenericParam *gparam = type->data.generic_param;
648 if (num >= inst->type_argc) {
649 const char *pname = mono_generic_param_name (gparam);
650 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
651 num, pname ? pname : "", inst->type_argc);
652 return NULL;
655 if (!can_inflate_gparam_with (gparam, inst->type_argv [num])) {
656 const char *pname = mono_generic_param_name (gparam);
657 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
658 num, pname ? pname : "", inst->type_argv [num]->type);
659 return NULL;
662 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
663 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
664 * ->byref and ->attrs from @type are propagated to the returned type.
666 nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type);
667 nt->byref = type->byref;
668 nt->attrs = type->attrs;
669 return nt;
671 case MONO_TYPE_VAR: {
672 MonoType *nt;
673 int num = mono_type_get_generic_param_num (type);
674 MonoGenericInst *inst = context->class_inst;
675 if (!inst)
676 return NULL;
677 MonoGenericParam *gparam = type->data.generic_param;
678 if (num >= inst->type_argc) {
679 const char *pname = mono_generic_param_name (gparam);
680 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
681 num, pname ? pname : "", inst->type_argc);
682 return NULL;
684 if (!can_inflate_gparam_with (gparam, inst->type_argv [num])) {
685 const char *pname = mono_generic_param_name (gparam);
686 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
687 num, pname ? pname : "", inst->type_argv [num]->type);
688 return NULL;
691 nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type);
692 nt->byref = type->byref;
693 nt->attrs = type->attrs;
694 return nt;
696 case MONO_TYPE_SZARRAY: {
697 MonoClass *eclass = type->data.klass;
698 MonoType *nt, *inflated = inflate_generic_type (NULL, m_class_get_byval_arg (eclass), context, error);
699 if (!inflated || !mono_error_ok (error))
700 return NULL;
701 nt = mono_metadata_type_dup (image, type);
702 nt->data.klass = mono_class_from_mono_type_internal (inflated);
703 mono_metadata_free_type (inflated);
704 return nt;
706 case MONO_TYPE_ARRAY: {
707 MonoClass *eclass = type->data.array->eklass;
708 MonoType *nt, *inflated = inflate_generic_type (NULL, m_class_get_byval_arg (eclass), context, error);
709 if (!inflated || !mono_error_ok (error))
710 return NULL;
711 nt = mono_metadata_type_dup (image, type);
712 nt->data.array->eklass = mono_class_from_mono_type_internal (inflated);
713 mono_metadata_free_type (inflated);
714 return nt;
716 case MONO_TYPE_GENERICINST: {
717 MonoGenericClass *gclass = type->data.generic_class;
718 MonoGenericInst *inst;
719 MonoType *nt;
720 if (!gclass->context.class_inst->is_open)
721 return NULL;
723 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
724 return_val_if_nok (error, NULL);
726 if (inst != gclass->context.class_inst)
727 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
729 if (gclass == type->data.generic_class)
730 return NULL;
732 nt = mono_metadata_type_dup (image, type);
733 nt->data.generic_class = gclass;
734 return nt;
736 case MONO_TYPE_CLASS:
737 case MONO_TYPE_VALUETYPE: {
738 MonoClass *klass = type->data.klass;
739 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
740 MonoGenericInst *inst;
741 MonoGenericClass *gclass = NULL;
742 MonoType *nt;
744 if (!container)
745 return NULL;
747 /* We can't use context->class_inst directly, since it can have more elements */
748 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
749 return_val_if_nok (error, NULL);
751 if (inst == container->context.class_inst)
752 return NULL;
754 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (m_class_get_image (klass)));
756 nt = mono_metadata_type_dup (image, type);
757 nt->type = MONO_TYPE_GENERICINST;
758 nt->data.generic_class = gclass;
759 return nt;
761 case MONO_TYPE_PTR: {
762 MonoType *nt, *inflated = inflate_generic_type (image, type->data.type, context, error);
763 if (!inflated || !mono_error_ok (error))
764 return NULL;
765 nt = mono_metadata_type_dup (image, type);
766 nt->data.type = inflated;
767 return nt;
769 default:
770 return NULL;
772 return NULL;
775 MonoGenericContext *
776 mono_generic_class_get_context (MonoGenericClass *gclass)
778 return &gclass->context;
781 MonoGenericContext *
782 mono_class_get_context (MonoClass *klass)
784 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
785 return gklass ? mono_generic_class_get_context (gklass) : NULL;
789 * mono_class_inflate_generic_type_with_mempool:
790 * @mempool: a mempool
791 * @type: a type
792 * @context: a generics context
793 * @error: error context
795 * The same as mono_class_inflate_generic_type, but allocates the MonoType
796 * from mempool if it is non-NULL. If it is NULL, the MonoType is
797 * allocated on the heap and is owned by the caller.
798 * The returned type can potentially be the same as TYPE, so it should not be
799 * modified by the caller, and it should be freed using mono_metadata_free_type ().
801 MonoType*
802 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
804 MonoType *inflated = NULL;
805 error_init (error);
807 if (context)
808 inflated = inflate_generic_type (image, type, context, error);
809 return_val_if_nok (error, NULL);
811 if (!inflated) {
812 MonoType *shared = mono_metadata_get_shared_type (type);
814 if (shared && !type->has_cmods) {
815 return shared;
816 } else {
817 return mono_metadata_type_dup (image, type);
821 UnlockedIncrement (&mono_stats.inflated_type_count);
822 return inflated;
826 * mono_class_inflate_generic_type:
827 * \param type a type
828 * \param context a generics context
829 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
831 * If \p type is a generic type and \p context is not NULL, instantiate it using the
832 * generics context \p context.
834 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
835 * on the heap and is owned by the caller. Returns NULL on error.
837 MonoType*
838 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
840 ERROR_DECL (error);
841 MonoType *result;
842 result = mono_class_inflate_generic_type_checked (type, context, error);
843 mono_error_cleanup (error);
844 return result;
848 * mono_class_inflate_generic_type:
849 * @type: a type
850 * @context: a generics context
851 * @error: error context to use
853 * If @type is a generic type and @context is not NULL, instantiate it using the
854 * generics context @context.
856 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
857 * on the heap and is owned by the caller.
859 MonoType*
860 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
862 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
866 * mono_class_inflate_generic_type_no_copy:
868 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
869 * was done.
871 static MonoType*
872 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
874 MonoType *inflated = NULL;
876 error_init (error);
877 if (context) {
878 inflated = inflate_generic_type (image, type, context, error);
879 return_val_if_nok (error, NULL);
882 if (!inflated)
883 return type;
885 UnlockedIncrement (&mono_stats.inflated_type_count);
886 return inflated;
890 * mono_class_inflate_generic_class:
892 * Inflate the class @gklass with @context. Set @error on failure.
894 MonoClass*
895 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
897 MonoClass *res;
898 MonoType *inflated;
900 inflated = mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass), context, error);
901 return_val_if_nok (error, NULL);
903 res = mono_class_from_mono_type_internal (inflated);
904 mono_metadata_free_type (inflated);
906 return res;
909 static MonoGenericContext
910 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
912 MonoGenericInst *class_inst = NULL;
913 MonoGenericInst *method_inst = NULL;
914 MonoGenericContext res = { NULL, NULL };
916 error_init (error);
918 if (context->class_inst) {
919 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
920 if (!mono_error_ok (error))
921 goto fail;
924 if (context->method_inst) {
925 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
926 if (!mono_error_ok (error))
927 goto fail;
930 res.class_inst = class_inst;
931 res.method_inst = method_inst;
932 fail:
933 return res;
937 * mono_class_inflate_generic_method:
938 * \param method a generic method
939 * \param context a generics context
941 * Instantiate the generic method \p method using the generics context \p context.
943 * \returns The new instantiated method
945 MonoMethod *
946 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
948 ERROR_DECL (error);
949 error_init (error);
950 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
951 mono_error_assert_msg_ok (error, "Could not inflate generic method");
952 return res;
955 MonoMethod *
956 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
958 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
962 * mono_class_inflate_generic_method_full_checked:
963 * Instantiate method \p method with the generic context \p context.
964 * On failure returns NULL and sets \p error.
966 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
967 * Use mono_method_signature_internal () and mono_method_get_header () to get the correct values.
969 MonoMethod*
970 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
972 MonoMethod *result;
973 MonoMethodInflated *iresult, *cached;
974 MonoMethodSignature *sig;
975 MonoGenericContext tmp_context;
977 error_init (error);
979 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
980 while (method->is_inflated) {
981 MonoGenericContext *method_context = mono_method_get_context (method);
982 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
984 tmp_context = inflate_generic_context (method_context, context, error);
985 return_val_if_nok (error, NULL);
987 context = &tmp_context;
989 if (mono_metadata_generic_context_equal (method_context, context))
990 return method;
992 method = imethod->declaring;
996 * A method only needs to be inflated if the context has argument for which it is
997 * parametric. Eg:
999 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1000 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1003 if (!((method->is_generic && context->method_inst) ||
1004 (mono_class_is_gtd (method->klass) && context->class_inst)))
1005 return method;
1007 iresult = g_new0 (MonoMethodInflated, 1);
1008 iresult->context = *context;
1009 iresult->declaring = method;
1011 if (!context->method_inst && method->is_generic)
1012 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1014 if (!context->class_inst) {
1015 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1016 if (mono_class_is_gtd (iresult->declaring->klass))
1017 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1019 /* This can happen with some callers like mono_object_get_virtual_method_internal () */
1020 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1021 iresult->context.class_inst = NULL;
1023 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1025 // check cache
1026 mono_image_set_lock (set);
1027 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1028 mono_image_set_unlock (set);
1030 if (cached) {
1031 g_free (iresult);
1032 return (MonoMethod*)cached;
1035 UnlockedIncrement (&mono_stats.inflated_method_count);
1037 UnlockedAdd (&mono_inflated_methods_size, sizeof (MonoMethodInflated));
1039 sig = mono_method_signature_internal (method);
1040 if (!sig) {
1041 char *name = mono_type_get_full_name (method->klass);
1042 mono_error_set_bad_image (error, mono_method_get_image (method), "Could not resolve signature of method %s:%s", name, method->name);
1043 g_free (name);
1044 goto fail;
1047 if (sig->pinvoke) {
1048 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1049 } else {
1050 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1053 result = (MonoMethod *) iresult;
1054 result->is_inflated = TRUE;
1055 result->is_generic = FALSE;
1056 result->sre_method = FALSE;
1057 result->signature = NULL;
1059 if (method->wrapper_type) {
1060 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1061 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1062 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1064 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1065 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1068 if (iresult->context.method_inst) {
1069 MonoGenericInst *method_inst = iresult->context.method_inst;
1070 /* Set the generic_container of the result to the generic_container of method */
1071 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1073 if (generic_container && method_inst == generic_container->context.method_inst) {
1074 result->is_generic = 1;
1075 mono_method_set_generic_container (result, generic_container);
1078 /* Check that the method is not instantiated with any invalid types */
1079 for (int i = 0; i < method_inst->type_argc; i++) {
1080 if (!mono_type_is_valid_generic_argument (method_inst->type_argv [i])) {
1081 mono_error_set_bad_image (error, mono_method_get_image (method), "MVAR %d cannot be expanded with type 0x%x",
1082 i, method_inst->type_argv [i]->type);
1083 goto fail;
1088 if (klass_hint) {
1089 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1090 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1091 klass_hint = NULL;
1094 if (mono_class_is_gtd (method->klass))
1095 result->klass = klass_hint;
1097 if (!result->klass) {
1098 MonoType *inflated = inflate_generic_type (NULL, m_class_get_byval_arg (method->klass), context, error);
1099 if (!mono_error_ok (error))
1100 goto fail;
1102 result->klass = inflated ? mono_class_from_mono_type_internal (inflated) : method->klass;
1103 if (inflated)
1104 mono_metadata_free_type (inflated);
1108 * FIXME: This should hold, but it doesn't:
1110 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1111 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1112 * g_assert (result->is_generic);
1115 * Fixing this here causes other things to break, hence a very
1116 * ugly hack in mini-trampolines.c - see
1117 * is_generic_method_definition().
1120 // check cache
1121 mono_image_set_lock (set);
1122 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1123 if (!cached) {
1124 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1125 iresult->owner = set;
1126 cached = iresult;
1128 mono_image_set_unlock (set);
1130 return (MonoMethod*)cached;
1132 fail:
1133 g_free (iresult);
1134 return NULL;
1138 * mono_get_inflated_method:
1140 * Obsolete. We keep it around since it's mentioned in the public API.
1142 MonoMethod*
1143 mono_get_inflated_method (MonoMethod *method)
1145 return method;
1149 * mono_method_get_context_general:
1150 * @method: a method
1151 * @uninflated: handle uninflated methods?
1153 * Returns the generic context of a method or NULL if it doesn't have
1154 * one. For an inflated method that's the context stored in the
1155 * method. Otherwise it's in the method's generic container or in the
1156 * generic container of the method's class.
1158 MonoGenericContext*
1159 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1161 if (method->is_inflated) {
1162 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1163 return &imethod->context;
1165 if (!uninflated)
1166 return NULL;
1167 if (method->is_generic)
1168 return &(mono_method_get_generic_container (method)->context);
1169 if (mono_class_is_gtd (method->klass))
1170 return &mono_class_get_generic_container (method->klass)->context;
1171 return NULL;
1175 * mono_method_get_context:
1176 * @method: a method
1178 * Returns the generic context for method if it's inflated, otherwise
1179 * NULL.
1181 MonoGenericContext*
1182 mono_method_get_context (MonoMethod *method)
1184 return mono_method_get_context_general (method, FALSE);
1188 * mono_method_get_generic_container:
1190 * Returns the generic container of METHOD, which should be a generic method definition.
1191 * Returns NULL if METHOD is not a generic method definition.
1192 * LOCKING: Acquires the loader lock.
1194 MonoGenericContainer*
1195 mono_method_get_generic_container (MonoMethod *method)
1197 MonoGenericContainer *container;
1199 if (!method->is_generic)
1200 return NULL;
1202 container = (MonoGenericContainer *)mono_image_property_lookup (mono_method_get_image (method), method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1203 g_assert (container);
1205 return container;
1209 * mono_method_set_generic_container:
1211 * Sets the generic container of METHOD to CONTAINER.
1212 * LOCKING: Acquires the image lock.
1214 void
1215 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1217 g_assert (method->is_generic);
1219 mono_image_property_insert (mono_method_get_image (method), method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1222 /**
1223 * mono_class_find_enum_basetype:
1224 * \param class The enum class
1226 * Determine the basetype of an enum by iterating through its fields. We do this
1227 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1229 MonoType*
1230 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1232 MonoGenericContainer *container = NULL;
1233 MonoImage *image = m_class_get_image (klass);
1234 const int top = mono_class_get_field_count (klass);
1235 int i, first_field_idx;
1237 g_assert (m_class_is_enumtype (klass));
1239 error_init (error);
1241 container = mono_class_try_get_generic_container (klass);
1242 if (mono_class_is_ginst (klass)) {
1243 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1245 container = mono_class_get_generic_container (gklass);
1246 g_assert (container);
1250 * Fetch all the field information.
1252 first_field_idx = mono_class_get_first_field_idx (klass);
1253 for (i = 0; i < top; i++){
1254 const char *sig;
1255 guint32 cols [MONO_FIELD_SIZE];
1256 int idx = first_field_idx + i;
1257 MonoType *ftype;
1259 /* first_field_idx and idx points into the fieldptr table */
1260 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1262 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1263 continue;
1265 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], error))
1266 goto fail;
1268 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
1269 mono_metadata_decode_value (sig, &sig);
1270 /* FIELD signature == 0x06 */
1271 if (*sig != 0x06) {
1272 mono_error_set_bad_image (error, image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1273 goto fail;
1276 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1277 if (!ftype)
1278 goto fail;
1280 if (mono_class_is_ginst (klass)) {
1281 //FIXME do we leak here?
1282 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1283 if (!mono_error_ok (error))
1284 goto fail;
1285 ftype->attrs = cols [MONO_FIELD_FLAGS];
1288 return ftype;
1290 mono_error_set_type_load_class (error, klass, "Could not find base type");
1292 fail:
1293 return NULL;
1297 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1299 gboolean
1300 mono_type_has_exceptions (MonoType *type)
1302 switch (type->type) {
1303 case MONO_TYPE_CLASS:
1304 case MONO_TYPE_VALUETYPE:
1305 case MONO_TYPE_SZARRAY:
1306 return mono_class_has_failure (type->data.klass);
1307 case MONO_TYPE_ARRAY:
1308 return mono_class_has_failure (type->data.array->eklass);
1309 case MONO_TYPE_GENERICINST:
1310 return mono_class_has_failure (mono_class_create_generic_inst (type->data.generic_class));
1311 default:
1312 return FALSE;
1316 void
1317 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1319 g_assert (mono_class_has_failure (klass));
1320 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1321 mono_error_set_from_boxed (oerror, box);
1325 * mono_class_alloc:
1327 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1328 * or from the heap.
1330 gpointer
1331 mono_class_alloc (MonoClass *klass, int size)
1333 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1334 if (gklass)
1335 return mono_image_set_alloc (gklass->owner, size);
1336 else
1337 return mono_image_alloc (m_class_get_image (klass), size);
1340 gpointer
1341 (mono_class_alloc0) (MonoClass *klass, int size)
1343 gpointer res;
1345 res = mono_class_alloc (klass, size);
1346 memset (res, 0, size);
1347 return res;
1350 #define mono_class_new0(klass,struct_type, n_structs) \
1351 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1354 * mono_class_set_failure_causedby_class:
1355 * \param klass the class that is failing
1356 * \param caused_by the class that caused the failure
1357 * \param msg Why \p klass is failing.
1359 * If \p caused_by has a failure, sets a TypeLoadException failure on
1360 * \p klass with message "\p msg, due to: {\p caused_by message}".
1362 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1364 gboolean
1365 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1367 if (mono_class_has_failure (caused_by)) {
1368 ERROR_DECL (cause_error);
1369 mono_error_set_for_class_failure (cause_error, caused_by);
1370 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (cause_error));
1371 mono_error_cleanup (cause_error);
1372 return TRUE;
1373 } else {
1374 return FALSE;
1380 * mono_type_get_basic_type_from_generic:
1381 * @type: a type
1383 * Returns a closed type corresponding to the possibly open type
1384 * passed to it.
1386 MonoType*
1387 mono_type_get_basic_type_from_generic (MonoType *type)
1389 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1390 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1391 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1392 return mono_get_object_type ();
1393 return type;
1397 * mono_class_get_method_by_index:
1399 * Returns klass->methods [index], initializing klass->methods if neccesary.
1401 * LOCKING: Acquires the loader lock.
1403 MonoMethod*
1404 mono_class_get_method_by_index (MonoClass *klass, int index)
1406 ERROR_DECL (error);
1408 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1409 /* Avoid calling setup_methods () if possible */
1410 if (gklass && !m_class_get_methods (klass)) {
1411 MonoMethod *m;
1413 m = mono_class_inflate_generic_method_full_checked (
1414 m_class_get_methods (gklass->container_class) [index], klass, mono_class_get_context (klass), error);
1415 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
1417 * If setup_methods () is called later for this class, no duplicates are created,
1418 * since inflate_generic_method guarantees that only one instance of a method
1419 * is created for each context.
1422 mono_class_setup_methods (klass);
1423 g_assert (m == klass->methods [index]);
1425 return m;
1426 } else {
1427 mono_class_setup_methods (klass);
1428 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
1429 return NULL;
1430 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
1431 return m_class_get_methods (klass) [index];
1436 * mono_class_get_inflated_method:
1437 * \param klass an inflated class
1438 * \param method a method of \p klass's generic definition
1439 * \param error set on error
1441 * Given an inflated class \p klass and a method \p method which should be a
1442 * method of \p klass's generic definition, return the inflated method
1443 * corresponding to \p method.
1445 * On failure sets \p error and returns NULL.
1447 MonoMethod*
1448 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method, MonoError *error)
1450 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1451 int i, mcount;
1453 g_assert (method->klass == gklass);
1455 mono_class_setup_methods (gklass);
1456 if (mono_class_has_failure (gklass)) {
1457 mono_error_set_for_class_failure (error, gklass);
1458 return NULL;
1461 MonoMethod **gklass_methods = m_class_get_methods (gklass);
1462 mcount = mono_class_get_method_count (gklass);
1463 for (i = 0; i < mcount; ++i) {
1464 if (gklass_methods [i] == method) {
1465 MonoMethod *inflated_method = NULL;
1466 MonoMethod **klass_methods = m_class_get_methods (klass);
1467 if (klass_methods) {
1468 inflated_method = klass_methods [i];
1469 } else {
1470 inflated_method = mono_class_inflate_generic_method_full_checked (gklass_methods [i], klass, mono_class_get_context (klass), error);
1471 return_val_if_nok (error, NULL);
1473 g_assert (inflated_method);
1474 return inflated_method;
1478 g_assert_not_reached ();
1482 * mono_class_get_vtable_entry:
1484 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
1485 * LOCKING: Acquires the loader lock.
1487 MonoMethod*
1488 mono_class_get_vtable_entry (MonoClass *klass, int offset)
1490 MonoMethod *m;
1492 if (m_class_get_rank (klass) == 1) {
1493 MonoClass *klass_parent = m_class_get_parent (klass);
1495 * szarrays do not overwrite any methods of Array, so we can avoid
1496 * initializing their vtables in some cases.
1498 mono_class_setup_vtable (klass_parent);
1499 if (offset < m_class_get_vtable_size (klass_parent))
1500 return m_class_get_vtable (klass_parent) [offset];
1503 if (mono_class_is_ginst (klass)) {
1504 ERROR_DECL (error);
1505 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1506 mono_class_setup_vtable (gklass);
1507 m = m_class_get_vtable (gklass) [offset];
1509 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), error);
1510 g_assert (mono_error_ok (error)); /* FIXME don't swallow this error */
1511 } else {
1512 mono_class_setup_vtable (klass);
1513 if (mono_class_has_failure (klass))
1514 return NULL;
1515 m = m_class_get_vtable (klass) [offset];
1518 return m;
1522 * mono_class_get_vtable_size:
1524 * Return the vtable size for KLASS.
1527 mono_class_get_vtable_size (MonoClass *klass)
1529 mono_class_setup_vtable (klass);
1531 return m_class_get_vtable_size (klass);
1534 static void
1535 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
1537 int i;
1538 MonoClass *ic;
1540 mono_class_setup_interfaces (klass, error);
1541 return_if_nok (error);
1543 MonoClass **klass_interfaces = m_class_get_interfaces (klass);
1544 for (i = 0; i < m_class_get_interface_count (klass); i++) {
1545 ic = klass_interfaces [i];
1547 if (*res == NULL)
1548 *res = g_ptr_array_new ();
1549 if (*ifaces == NULL)
1550 *ifaces = g_hash_table_new (NULL, NULL);
1551 if (g_hash_table_lookup (*ifaces, ic))
1552 continue;
1553 /* A gparam is not an implemented interface for the purposes of
1554 * mono_class_get_implemented_interfaces */
1555 if (mono_class_is_gparam (ic))
1556 continue;
1557 g_ptr_array_add (*res, ic);
1558 g_hash_table_insert (*ifaces, ic, ic);
1559 mono_class_init_internal (ic);
1560 if (mono_class_has_failure (ic)) {
1561 mono_error_set_type_load_class (error, ic, "Error Loading class");
1562 return;
1565 collect_implemented_interfaces_aux (ic, res, ifaces, error);
1566 return_if_nok (error);
1570 GPtrArray*
1571 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
1573 GPtrArray *res = NULL;
1574 GHashTable *ifaces = NULL;
1576 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
1577 if (ifaces)
1578 g_hash_table_destroy (ifaces);
1579 if (!mono_error_ok (error)) {
1580 if (res)
1581 g_ptr_array_free (res, TRUE);
1582 return NULL;
1584 return res;
1587 static int
1588 compare_interface_ids (const void *p_key, const void *p_element)
1590 MonoClass *key = (MonoClass *)p_key;
1591 MonoClass *element = *(MonoClass **)p_element;
1593 return (m_class_get_interface_id (key) - m_class_get_interface_id (element));
1596 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
1598 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
1600 MonoClass **klass_interfaces_packed = m_class_get_interfaces_packed (klass);
1601 MonoClass **result = (MonoClass **)mono_binary_search (
1602 itf,
1603 klass_interfaces_packed,
1604 m_class_get_interface_offsets_count (klass),
1605 sizeof (MonoClass *),
1606 compare_interface_ids);
1607 if (result) {
1608 return m_class_get_interface_offsets_packed (klass) [result - klass_interfaces_packed];
1609 } else {
1610 return -1;
1615 * mono_class_interface_offset_with_variance:
1617 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
1618 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
1620 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
1622 * FIXME figure out MS disambiguation rules and fix this function.
1625 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
1627 int i = mono_class_interface_offset (klass, itf);
1628 *non_exact_match = FALSE;
1629 if (i >= 0)
1630 return i;
1632 int klass_interface_offsets_count = m_class_get_interface_offsets_count (klass);
1634 if (m_class_is_array_special_interface (itf) && m_class_get_rank (klass) < 2) {
1635 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
1636 int found = -1;
1638 for (i = 0; i < klass_interface_offsets_count; i++) {
1639 if (mono_class_is_variant_compatible (itf, m_class_get_interfaces_packed (klass) [i], FALSE)) {
1640 found = i;
1641 *non_exact_match = TRUE;
1642 break;
1646 if (found != -1)
1647 return m_class_get_interface_offsets_packed (klass) [found];
1649 for (i = 0; i < klass_interface_offsets_count; i++) {
1650 if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass) [i]) == gtd) {
1651 found = i;
1652 *non_exact_match = TRUE;
1653 break;
1657 if (found == -1)
1658 return -1;
1660 return m_class_get_interface_offsets_packed (klass) [found];
1663 if (!mono_class_has_variant_generic_params (itf))
1664 return -1;
1666 for (i = 0; i < klass_interface_offsets_count; i++) {
1667 if (mono_class_is_variant_compatible (itf, m_class_get_interfaces_packed (klass) [i], FALSE)) {
1668 *non_exact_match = TRUE;
1669 return m_class_get_interface_offsets_packed (klass) [i];
1673 return -1;
1678 * mono_method_get_vtable_slot:
1680 * Returns method->slot, computing it if neccesary. Return -1 on failure.
1681 * LOCKING: Acquires the loader lock.
1683 * FIXME Use proper MonoError machinery here.
1686 mono_method_get_vtable_slot (MonoMethod *method)
1688 if (method->slot == -1) {
1689 mono_class_setup_vtable (method->klass);
1690 if (mono_class_has_failure (method->klass))
1691 return -1;
1692 if (method->slot == -1) {
1693 MonoClass *gklass;
1694 int i, mcount;
1696 if (!mono_class_is_ginst (method->klass)) {
1697 g_assert (method->is_inflated);
1698 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
1701 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
1702 g_assert (mono_class_is_ginst (method->klass));
1703 gklass = mono_class_get_generic_class (method->klass)->container_class;
1704 mono_class_setup_methods (method->klass);
1705 MonoMethod **klass_methods = m_class_get_methods (method->klass);
1706 g_assert (klass_methods);
1707 mcount = mono_class_get_method_count (method->klass);
1708 for (i = 0; i < mcount; ++i) {
1709 if (klass_methods [i] == method)
1710 break;
1712 g_assert (i < mcount);
1713 g_assert (m_class_get_methods (gklass));
1714 method->slot = m_class_get_methods (gklass) [i]->slot;
1716 g_assert (method->slot != -1);
1718 return method->slot;
1722 * mono_method_get_vtable_index:
1723 * \param method a method
1725 * Returns the index into the runtime vtable to access the method or,
1726 * in the case of a virtual generic method, the virtual generic method
1727 * thunk. Returns -1 on failure.
1729 * FIXME Use proper MonoError machinery here.
1732 mono_method_get_vtable_index (MonoMethod *method)
1734 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
1735 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
1736 if (imethod->declaring->is_generic)
1737 return mono_method_get_vtable_slot (imethod->declaring);
1739 return mono_method_get_vtable_slot (method);
1743 * mono_class_has_finalizer:
1745 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
1746 * process.
1748 * LOCKING: Acquires the loader lock;
1750 gboolean
1751 mono_class_has_finalizer (MonoClass *klass)
1753 if (!m_class_is_has_finalize_inited (klass))
1754 mono_class_setup_has_finalizer (klass);
1756 return m_class_has_finalize (klass);
1759 gboolean
1760 mono_is_corlib_image (MonoImage *image)
1762 return image == mono_defaults.corlib;
1766 /** Is klass a Nullable<T> ginst? */
1767 gboolean
1768 mono_class_is_nullable (MonoClass *klass)
1770 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1771 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
1775 /** if klass is T? return T */
1776 MonoClass*
1777 mono_class_get_nullable_param (MonoClass *klass)
1779 g_assert (mono_class_is_nullable (klass));
1780 return mono_class_from_mono_type_internal (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
1783 gboolean
1784 mono_type_is_primitive (MonoType *type)
1786 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1787 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1790 static MonoImage *
1791 get_image_for_container (MonoGenericContainer *container)
1793 MonoImage *result;
1794 if (container->is_anonymous) {
1795 result = container->owner.image;
1796 } else {
1797 MonoClass *klass;
1798 if (container->is_method) {
1799 MonoMethod *method = container->owner.method;
1800 g_assert_checked (method);
1801 klass = method->klass;
1802 } else {
1803 klass = container->owner.klass;
1805 g_assert_checked (klass);
1806 result = m_class_get_image (klass);
1808 g_assert (result);
1809 return result;
1812 MonoImage *
1813 mono_get_image_for_generic_param (MonoGenericParam *param)
1815 MonoGenericContainer *container = mono_generic_param_owner (param);
1816 g_assert_checked (container);
1817 return get_image_for_container (container);
1820 // Make a string in the designated image consisting of a single integer.
1821 #define INT_STRING_SIZE 16
1822 char *
1823 mono_make_generic_name_string (MonoImage *image, int num)
1825 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
1826 g_snprintf (name, INT_STRING_SIZE, "%d", num);
1827 return name;
1831 * mono_class_from_generic_parameter:
1832 * \param param Parameter to find/construct a class for.
1833 * \param arg2 Is ignored.
1834 * \param arg3 Is ignored.
1836 MonoClass *
1837 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
1839 return mono_class_create_generic_parameter (param);
1843 * mono_ptr_class_get:
1845 MonoClass *
1846 mono_ptr_class_get (MonoType *type)
1848 return mono_class_create_ptr (type);
1852 * mono_class_from_mono_type:
1853 * \param type describes the type to return
1854 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
1856 MonoClass *
1857 mono_class_from_mono_type (MonoType *type)
1859 MonoClass *result;
1860 MONO_ENTER_GC_UNSAFE;
1861 result = mono_class_from_mono_type_internal (type);
1862 MONO_EXIT_GC_UNSAFE;
1863 return result;
1866 MonoClass *
1867 mono_class_from_mono_type_internal (MonoType *type)
1869 switch (type->type) {
1870 case MONO_TYPE_OBJECT:
1871 return type->data.klass? type->data.klass: mono_defaults.object_class;
1872 case MONO_TYPE_VOID:
1873 return type->data.klass? type->data.klass: mono_defaults.void_class;
1874 case MONO_TYPE_BOOLEAN:
1875 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
1876 case MONO_TYPE_CHAR:
1877 return type->data.klass? type->data.klass: mono_defaults.char_class;
1878 case MONO_TYPE_I1:
1879 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
1880 case MONO_TYPE_U1:
1881 return type->data.klass? type->data.klass: mono_defaults.byte_class;
1882 case MONO_TYPE_I2:
1883 return type->data.klass? type->data.klass: mono_defaults.int16_class;
1884 case MONO_TYPE_U2:
1885 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
1886 case MONO_TYPE_I4:
1887 return type->data.klass? type->data.klass: mono_defaults.int32_class;
1888 case MONO_TYPE_U4:
1889 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
1890 case MONO_TYPE_I:
1891 return type->data.klass? type->data.klass: mono_defaults.int_class;
1892 case MONO_TYPE_U:
1893 return type->data.klass? type->data.klass: mono_defaults.uint_class;
1894 case MONO_TYPE_I8:
1895 return type->data.klass? type->data.klass: mono_defaults.int64_class;
1896 case MONO_TYPE_U8:
1897 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
1898 case MONO_TYPE_R4:
1899 return type->data.klass? type->data.klass: mono_defaults.single_class;
1900 case MONO_TYPE_R8:
1901 return type->data.klass? type->data.klass: mono_defaults.double_class;
1902 case MONO_TYPE_STRING:
1903 return type->data.klass? type->data.klass: mono_defaults.string_class;
1904 case MONO_TYPE_TYPEDBYREF:
1905 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
1906 case MONO_TYPE_ARRAY:
1907 return mono_class_create_bounded_array (type->data.array->eklass, type->data.array->rank, TRUE);
1908 case MONO_TYPE_PTR:
1909 return mono_class_create_ptr (type->data.type);
1910 case MONO_TYPE_FNPTR:
1911 return mono_class_create_fnptr (type->data.method);
1912 case MONO_TYPE_SZARRAY:
1913 return mono_class_create_array (type->data.klass, 1);
1914 case MONO_TYPE_CLASS:
1915 case MONO_TYPE_VALUETYPE:
1916 return type->data.klass;
1917 case MONO_TYPE_GENERICINST:
1918 return mono_class_create_generic_inst (type->data.generic_class);
1919 case MONO_TYPE_MVAR:
1920 case MONO_TYPE_VAR:
1921 return mono_class_create_generic_parameter (type->data.generic_param);
1922 default:
1923 g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type->type);
1924 g_assert_not_reached ();
1927 // Yes, this returns NULL, even if it is documented as not doing so, but there
1928 // is no way for the code to make it this far, due to the assert above.
1929 return NULL;
1933 * mono_type_retrieve_from_typespec
1934 * \param image context where the image is created
1935 * \param type_spec typespec token
1936 * \param context the generic context used to evaluate generic instantiations in
1938 static MonoType *
1939 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
1941 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
1943 *did_inflate = FALSE;
1945 if (!t)
1946 return NULL;
1948 if (context && (context->class_inst || context->method_inst)) {
1949 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
1951 if (!mono_error_ok (error)) {
1952 return NULL;
1955 if (inflated) {
1956 t = inflated;
1957 *did_inflate = TRUE;
1960 return t;
1964 * mono_class_create_from_typespec
1965 * \param image context where the image is created
1966 * \param type_spec typespec token
1967 * \param context the generic context used to evaluate generic instantiations in
1969 static MonoClass *
1970 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
1972 MonoClass *ret;
1973 gboolean inflated = FALSE;
1974 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
1975 return_val_if_nok (error, NULL);
1976 ret = mono_class_from_mono_type_internal (t);
1977 if (inflated)
1978 mono_metadata_free_type (t);
1979 return ret;
1983 * mono_bounded_array_class_get:
1984 * \param element_class element class
1985 * \param rank the dimension of the array class
1986 * \param bounded whenever the array has non-zero bounds
1987 * \returns A class object describing the array with element type \p element_type and
1988 * dimension \p rank.
1990 MonoClass *
1991 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
1993 return mono_class_create_bounded_array (eclass, rank, bounded);
1997 * mono_array_class_get:
1998 * \param element_class element class
1999 * \param rank the dimension of the array class
2000 * \returns A class object describing the array with element type \p element_type and
2001 * dimension \p rank.
2003 MonoClass *
2004 mono_array_class_get (MonoClass *eclass, guint32 rank)
2006 return mono_class_create_array (eclass, rank);
2010 * mono_class_instance_size:
2011 * \param klass a class
2013 * Use to get the size of a class in bytes.
2015 * \returns The size of an object instance
2017 gint32
2018 mono_class_instance_size (MonoClass *klass)
2020 if (!m_class_is_size_inited (klass))
2021 mono_class_init_internal (klass);
2023 return m_class_get_instance_size (klass);
2027 * mono_class_min_align:
2028 * \param klass a class
2030 * Use to get the computed minimum alignment requirements for the specified class.
2032 * Returns: minimum alignment requirements
2034 gint32
2035 mono_class_min_align (MonoClass *klass)
2037 if (!m_class_is_size_inited (klass))
2038 mono_class_init_internal (klass);
2040 return m_class_get_min_align (klass);
2044 * mono_class_data_size:
2045 * \param klass a class
2047 * \returns The size of the static class data
2049 gint32
2050 mono_class_data_size (MonoClass *klass)
2052 if (!m_class_is_inited (klass))
2053 mono_class_init_internal (klass);
2054 /* This can happen with dynamically created types */
2055 if (!m_class_is_fields_inited (klass))
2056 mono_class_setup_fields (klass);
2058 /* in arrays, sizes.class_size is unioned with element_size
2059 * and arrays have no static fields
2061 if (m_class_get_rank (klass))
2062 return 0;
2063 return m_class_get_sizes (klass).class_size;
2067 * Auxiliary routine to mono_class_get_field
2069 * Takes a field index instead of a field token.
2071 static MonoClassField *
2072 mono_class_get_field_idx (MonoClass *klass, int idx)
2074 mono_class_setup_fields (klass);
2075 if (mono_class_has_failure (klass))
2076 return NULL;
2078 while (klass) {
2079 int first_field_idx = mono_class_get_first_field_idx (klass);
2080 int fcount = mono_class_get_field_count (klass);
2081 MonoImage *klass_image = m_class_get_image (klass);
2082 MonoClassField *klass_fields = m_class_get_fields (klass);
2083 if (klass_image->uncompressed_metadata) {
2085 * first_field_idx points to the FieldPtr table, while idx points into the
2086 * Field table, so we have to do a search.
2088 /*FIXME this is broken for types with multiple fields with the same name.*/
2089 const char *name = mono_metadata_string_heap (klass_image, mono_metadata_decode_row_col (&klass_image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
2090 int i;
2092 for (i = 0; i < fcount; ++i)
2093 if (mono_field_get_name (&klass_fields [i]) == name)
2094 return &klass_fields [i];
2095 g_assert_not_reached ();
2096 } else {
2097 if (fcount) {
2098 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
2099 return &klass_fields [idx - first_field_idx];
2103 klass = m_class_get_parent (klass);
2105 return NULL;
2109 * mono_class_get_field:
2110 * \param class the class to lookup the field.
2111 * \param field_token the field token
2113 * \returns A \c MonoClassField representing the type and offset of
2114 * the field, or a NULL value if the field does not belong to this
2115 * class.
2117 MonoClassField *
2118 mono_class_get_field (MonoClass *klass, guint32 field_token)
2120 int idx = mono_metadata_token_index (field_token);
2122 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
2124 return mono_class_get_field_idx (klass, idx - 1);
2128 * mono_class_get_field_from_name:
2129 * \param klass the class to lookup the field.
2130 * \param name the field name
2132 * Search the class \p klass and its parents for a field with the name \p name.
2134 * \returns The \c MonoClassField pointer of the named field or NULL
2136 MonoClassField *
2137 mono_class_get_field_from_name (MonoClass *klass, const char *name)
2139 MonoClassField *result;
2140 MONO_ENTER_GC_UNSAFE;
2141 result = mono_class_get_field_from_name_full (klass, name, NULL);
2142 MONO_EXIT_GC_UNSAFE;
2143 return result;
2147 * mono_class_get_field_from_name_full:
2148 * \param klass the class to lookup the field.
2149 * \param name the field name
2150 * \param type the type of the fields. This optional.
2152 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
2154 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
2155 * of its generic type definition.
2157 * \returns The MonoClassField pointer of the named field or NULL
2159 MonoClassField *
2160 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
2162 MONO_REQ_GC_UNSAFE_MODE;
2164 int i;
2166 mono_class_setup_fields (klass);
2167 if (mono_class_has_failure (klass))
2168 return NULL;
2170 while (klass) {
2171 int fcount = mono_class_get_field_count (klass);
2172 for (i = 0; i < fcount; ++i) {
2173 MonoClassField *field = &m_class_get_fields (klass) [i];
2175 if (strcmp (name, mono_field_get_name (field)) != 0)
2176 continue;
2178 if (type) {
2179 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
2180 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
2181 continue;
2183 return field;
2185 klass = m_class_get_parent (klass);
2187 return NULL;
2191 * mono_class_get_field_token:
2192 * \param field the field we need the token of
2194 * Get the token of a field. Note that the tokesn is only valid for the image
2195 * the field was loaded from. Don't use this function for fields in dynamic types.
2197 * \returns The token representing the field in the image it was loaded from.
2199 guint32
2200 mono_class_get_field_token (MonoClassField *field)
2202 MonoClass *klass = field->parent;
2203 int i;
2205 mono_class_setup_fields (klass);
2207 while (klass) {
2208 MonoClassField *klass_fields = m_class_get_fields (klass);
2209 if (!klass_fields)
2210 return 0;
2211 int first_field_idx = mono_class_get_first_field_idx (klass);
2212 int fcount = mono_class_get_field_count (klass);
2213 for (i = 0; i < fcount; ++i) {
2214 if (&klass_fields [i] == field) {
2215 int idx = first_field_idx + i + 1;
2217 if (m_class_get_image (klass)->uncompressed_metadata)
2218 idx = mono_metadata_translate_token_index (m_class_get_image (klass), MONO_TABLE_FIELD, idx);
2219 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
2222 klass = m_class_get_parent (klass);
2225 g_assert_not_reached ();
2226 return 0;
2229 static int
2230 mono_field_get_index (MonoClassField *field)
2232 int index = field - m_class_get_fields (field->parent);
2233 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
2235 return index;
2239 * mono_class_get_field_default_value:
2241 * Return the default value of the field as a pointer into the metadata blob.
2243 const char*
2244 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
2246 guint32 cindex;
2247 guint32 constant_cols [MONO_CONSTANT_SIZE];
2248 int field_index;
2249 MonoClass *klass = field->parent;
2250 MonoFieldDefaultValue *def_values;
2252 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
2254 def_values = mono_class_get_field_def_values (klass);
2255 if (!def_values) {
2256 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
2258 mono_class_set_field_def_values (klass, def_values);
2261 field_index = mono_field_get_index (field);
2263 if (!def_values [field_index].data) {
2264 MonoImage *field_parent_image = m_class_get_image (field->parent);
2265 cindex = mono_metadata_get_constant_index (field_parent_image, mono_class_get_field_token (field), 0);
2266 if (!cindex)
2267 return NULL;
2269 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
2271 mono_metadata_decode_row (&field_parent_image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
2272 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
2273 mono_memory_barrier ();
2274 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field_parent_image, constant_cols [MONO_CONSTANT_VALUE]);
2277 *def_type = def_values [field_index].def_type;
2278 return def_values [field_index].data;
2281 static int
2282 mono_property_get_index (MonoProperty *prop)
2284 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
2285 int index = prop - info->properties;
2287 g_assert (index >= 0 && index < info->count);
2289 return index;
2293 * mono_class_get_property_default_value:
2295 * Return the default value of the field as a pointer into the metadata blob.
2297 const char*
2298 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
2300 guint32 cindex;
2301 guint32 constant_cols [MONO_CONSTANT_SIZE];
2302 MonoClass *klass = property->parent;
2303 MonoImage *klass_image = m_class_get_image (klass);
2305 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
2307 * We don't cache here because it is not used by C# so it's quite rare, but
2308 * we still do the lookup in klass->ext because that is where the data
2309 * is stored for dynamic assemblies.
2312 if (image_is_dynamic (klass_image)) {
2313 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
2314 int prop_index = mono_property_get_index (property);
2315 if (info->def_values && info->def_values [prop_index].data) {
2316 *def_type = info->def_values [prop_index].def_type;
2317 return info->def_values [prop_index].data;
2319 return NULL;
2321 cindex = mono_metadata_get_constant_index (klass_image, mono_class_get_property_token (property), 0);
2322 if (!cindex)
2323 return NULL;
2325 mono_metadata_decode_row (&klass_image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
2326 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
2327 return (const char *)mono_metadata_blob_heap (klass_image, constant_cols [MONO_CONSTANT_VALUE]);
2331 * mono_class_get_event_token:
2333 guint32
2334 mono_class_get_event_token (MonoEvent *event)
2336 MonoClass *klass = event->parent;
2337 int i;
2339 while (klass) {
2340 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2341 if (info) {
2342 for (i = 0; i < info->count; ++i) {
2343 if (&info->events [i] == event)
2344 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
2347 klass = m_class_get_parent (klass);
2350 g_assert_not_reached ();
2351 return 0;
2355 * mono_class_get_property_from_name:
2356 * \param klass a class
2357 * \param name name of the property to lookup in the specified class
2359 * Use this method to lookup a property in a class
2360 * \returns the \c MonoProperty with the given name, or NULL if the property
2361 * does not exist on the \p klass.
2363 MonoProperty*
2364 mono_class_get_property_from_name (MonoClass *klass, const char *name)
2366 MonoProperty *result = NULL;
2367 MONO_ENTER_GC_UNSAFE;
2368 result = mono_class_get_property_from_name_internal (klass, name);
2369 MONO_EXIT_GC_UNSAFE;
2370 return result;
2373 MonoProperty*
2374 mono_class_get_property_from_name_internal (MonoClass *klass, const char *name)
2376 MONO_REQ_GC_UNSAFE_MODE;
2377 while (klass) {
2378 MonoProperty* p;
2379 gpointer iter = NULL;
2380 while ((p = mono_class_get_properties (klass, &iter))) {
2381 if (! strcmp (name, p->name))
2382 return p;
2384 klass = m_class_get_parent (klass);
2386 return NULL;
2390 * mono_class_get_property_token:
2391 * \param prop MonoProperty to query
2393 * \returns The ECMA token for the specified property.
2395 guint32
2396 mono_class_get_property_token (MonoProperty *prop)
2398 MonoClass *klass = prop->parent;
2399 while (klass) {
2400 MonoProperty* p;
2401 int i = 0;
2402 gpointer iter = NULL;
2403 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
2404 while ((p = mono_class_get_properties (klass, &iter))) {
2405 if (&info->properties [i] == prop)
2406 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
2408 i ++;
2410 klass = m_class_get_parent (klass);
2413 g_assert_not_reached ();
2414 return 0;
2418 * mono_class_name_from_token:
2420 char *
2421 mono_class_name_from_token (MonoImage *image, guint32 type_token)
2423 const char *name, *nspace;
2424 if (image_is_dynamic (image))
2425 return g_strdup_printf ("DynamicType 0x%08x", type_token);
2427 switch (type_token & 0xff000000){
2428 case MONO_TOKEN_TYPE_DEF: {
2429 guint32 cols [MONO_TYPEDEF_SIZE];
2430 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
2431 guint tidx = mono_metadata_token_index (type_token);
2433 if (tidx > tt->rows)
2434 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
2436 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
2437 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2438 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2439 if (strlen (nspace) == 0)
2440 return g_strdup_printf ("%s", name);
2441 else
2442 return g_strdup_printf ("%s.%s", nspace, name);
2445 case MONO_TOKEN_TYPE_REF: {
2446 ERROR_DECL (error);
2447 guint32 cols [MONO_TYPEREF_SIZE];
2448 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
2449 guint tidx = mono_metadata_token_index (type_token);
2451 if (tidx > t->rows)
2452 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
2454 if (!mono_verifier_verify_typeref_row (image, tidx - 1, error)) {
2455 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (error));
2456 mono_error_cleanup (error);
2457 return msg;
2460 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
2461 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
2462 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
2463 if (strlen (nspace) == 0)
2464 return g_strdup_printf ("%s", name);
2465 else
2466 return g_strdup_printf ("%s.%s", nspace, name);
2469 case MONO_TOKEN_TYPE_SPEC:
2470 return g_strdup_printf ("Typespec 0x%08x", type_token);
2471 default:
2472 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
2476 static char *
2477 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
2479 if (image_is_dynamic (image))
2480 return g_strdup_printf ("DynamicAssembly %s", image->name);
2482 switch (type_token & 0xff000000){
2483 case MONO_TOKEN_TYPE_DEF:
2484 if (image->assembly)
2485 return mono_stringify_assembly_name (&image->assembly->aname);
2486 else if (image->assembly_name)
2487 return g_strdup (image->assembly_name);
2488 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
2489 case MONO_TOKEN_TYPE_REF: {
2490 ERROR_DECL (error);
2491 MonoAssemblyName aname;
2492 guint32 cols [MONO_TYPEREF_SIZE];
2493 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
2494 guint32 idx = mono_metadata_token_index (type_token);
2496 if (idx > t->rows)
2497 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
2499 if (!mono_verifier_verify_typeref_row (image, idx - 1, error)) {
2500 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (error));
2501 mono_error_cleanup (error);
2502 return msg;
2504 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
2506 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
2507 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
2508 case MONO_RESOLUTION_SCOPE_MODULE:
2509 /* FIXME: */
2510 return g_strdup ("");
2511 case MONO_RESOLUTION_SCOPE_MODULEREF:
2512 /* FIXME: */
2513 return g_strdup ("");
2514 case MONO_RESOLUTION_SCOPE_TYPEREF:
2515 /* FIXME: */
2516 return g_strdup ("");
2517 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
2518 mono_assembly_get_assemblyref (image, idx - 1, &aname);
2519 return mono_stringify_assembly_name (&aname);
2520 default:
2521 g_assert_not_reached ();
2523 break;
2525 case MONO_TOKEN_TYPE_SPEC:
2526 /* FIXME: */
2527 return g_strdup ("");
2528 default:
2529 g_assert_not_reached ();
2532 return NULL;
2536 * mono_class_get_full:
2537 * \param image the image where the class resides
2538 * \param type_token the token for the class
2539 * \param context the generic context used to evaluate generic instantiations in
2540 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
2541 * \returns The \c MonoClass that represents \p type_token in \p image
2543 MonoClass *
2544 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
2546 ERROR_DECL (error);
2547 MonoClass *klass;
2548 klass = mono_class_get_checked (image, type_token, error);
2550 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
2551 klass = mono_class_inflate_generic_class_checked (klass, context, error);
2553 mono_error_assert_ok (error);
2554 return klass;
2558 MonoClass *
2559 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
2561 MonoClass *klass;
2563 error_init (error);
2564 klass = mono_class_get_checked (image, type_token, error);
2566 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
2567 klass = mono_class_inflate_generic_class_checked (klass, context, error);
2569 return klass;
2572 * mono_class_get_checked:
2573 * \param image the image where the class resides
2574 * \param type_token the token for the class
2575 * \param error error object to return any error
2577 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
2579 MonoClass *
2580 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
2582 MonoClass *klass = NULL;
2584 error_init (error);
2586 if (image_is_dynamic (image)) {
2587 int table = mono_metadata_token_table (type_token);
2589 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
2590 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
2591 return NULL;
2593 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
2594 goto done;
2597 switch (type_token & 0xff000000){
2598 case MONO_TOKEN_TYPE_DEF:
2599 klass = mono_class_create_from_typedef (image, type_token, error);
2600 break;
2601 case MONO_TOKEN_TYPE_REF:
2602 klass = mono_class_from_typeref_checked (image, type_token, error);
2603 break;
2604 case MONO_TOKEN_TYPE_SPEC:
2605 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
2606 break;
2607 default:
2608 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
2611 done:
2612 /* Generic case, should be avoided for when a better error is possible. */
2613 if (!klass && mono_error_ok (error)) {
2614 char *name = mono_class_name_from_token (image, type_token);
2615 char *assembly = mono_assembly_name_from_token (image, type_token);
2616 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (expected class '%s' in assembly '%s')", type_token, name, assembly);
2619 return klass;
2624 * mono_type_get_checked:
2625 * \param image the image where the type resides
2626 * \param type_token the token for the type
2627 * \param context the generic context used to evaluate generic instantiations in
2628 * \param error Error handling context
2630 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
2632 * \returns The MonoType that represents \p type_token in \p image
2634 MonoType *
2635 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
2637 MonoType *type = NULL;
2638 gboolean inflated = FALSE;
2640 error_init (error);
2642 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
2643 if (image_is_dynamic (image)) {
2644 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
2645 return_val_if_nok (error, NULL);
2646 return m_class_get_byval_arg (klass);
2649 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
2650 MonoClass *klass = mono_class_get_checked (image, type_token, error);
2652 if (!klass)
2653 return NULL;
2654 if (m_class_has_failure (klass)) {
2655 mono_error_set_for_class_failure (error, klass);
2656 return NULL;
2658 return m_class_get_byval_arg (klass);
2661 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
2663 if (!type) {
2664 return NULL;
2667 if (inflated) {
2668 MonoType *tmp = type;
2669 type = m_class_get_byval_arg (mono_class_from_mono_type_internal (type));
2670 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
2671 * A MonoClass::_byval_arg of a generic type definion has type CLASS.
2672 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with _byval_arg.
2674 * The long term solution is to chaise this places and make then set MonoType::type correctly.
2675 * */
2676 if (type->type != tmp->type)
2677 type = tmp;
2678 else
2679 mono_metadata_free_type (tmp);
2681 return type;
2685 * mono_class_get:
2686 * \param image image where the class token will be looked up.
2687 * \param type_token a type token from the image
2688 * \returns the \c MonoClass with the given \p type_token on the \p image
2690 MonoClass *
2691 mono_class_get (MonoImage *image, guint32 type_token)
2693 ERROR_DECL (error);
2694 error_init (error);
2695 MonoClass *result = mono_class_get_checked (image, type_token, error);
2696 mono_error_assert_ok (error);
2697 return result;
2701 * mono_image_init_name_cache:
2703 * Initializes the class name cache stored in image->name_cache.
2705 * LOCKING: Acquires the corresponding image lock.
2707 void
2708 mono_image_init_name_cache (MonoImage *image)
2710 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
2711 guint32 cols [MONO_TYPEDEF_SIZE];
2712 const char *name;
2713 const char *nspace;
2714 guint32 i, visib, nspace_index;
2715 GHashTable *name_cache2, *nspace_table, *the_name_cache;
2717 if (image->name_cache)
2718 return;
2720 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
2722 if (image_is_dynamic (image)) {
2723 mono_image_lock (image);
2724 if (image->name_cache) {
2725 /* Somebody initialized it before us */
2726 g_hash_table_destroy (the_name_cache);
2727 } else {
2728 mono_atomic_store_release (&image->name_cache, the_name_cache);
2730 mono_image_unlock (image);
2731 return;
2734 /* Temporary hash table to avoid lookups in the nspace_table */
2735 name_cache2 = g_hash_table_new (NULL, NULL);
2737 for (i = 1; i <= t->rows; ++i) {
2738 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
2739 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2741 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2742 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2744 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
2745 continue;
2746 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2747 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2749 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
2750 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
2751 if (!nspace_table) {
2752 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
2753 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
2754 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
2755 nspace_table);
2757 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
2760 /* Load type names from EXPORTEDTYPES table */
2762 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
2763 guint32 cols [MONO_EXP_TYPE_SIZE];
2764 int i;
2766 for (i = 0; i < t->rows; ++i) {
2767 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
2769 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
2770 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
2771 /* Nested type */
2772 continue;
2774 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
2775 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
2777 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
2778 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
2779 if (!nspace_table) {
2780 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
2781 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
2782 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
2783 nspace_table);
2785 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
2789 g_hash_table_destroy (name_cache2);
2791 mono_image_lock (image);
2792 if (image->name_cache) {
2793 /* Somebody initialized it before us */
2794 g_hash_table_destroy (the_name_cache);
2795 } else {
2796 mono_atomic_store_release (&image->name_cache, the_name_cache);
2798 mono_image_unlock (image);
2801 /*FIXME Only dynamic assemblies should allow this operation.*/
2803 * mono_image_add_to_name_cache:
2805 void
2806 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
2807 const char *name, guint32 index)
2809 GHashTable *nspace_table;
2810 GHashTable *name_cache;
2811 guint32 old_index;
2813 mono_image_init_name_cache (image);
2814 mono_image_lock (image);
2816 name_cache = image->name_cache;
2817 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
2818 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
2819 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
2822 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
2823 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
2825 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
2827 mono_image_unlock (image);
2830 typedef struct {
2831 gconstpointer key;
2832 gpointer value;
2833 } FindUserData;
2835 static void
2836 find_nocase (gpointer key, gpointer value, gpointer user_data)
2838 char *name = (char*)key;
2839 FindUserData *data = (FindUserData*)user_data;
2841 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
2842 data->value = value;
2846 * mono_class_from_name_case:
2847 * \param image The MonoImage where the type is looked up in
2848 * \param name_space the type namespace
2849 * \param name the type short name.
2850 * \deprecated use the mono_class_from_name_case_checked variant instead.
2852 * Obtains a \c MonoClass with a given namespace and a given name which
2853 * is located in the given \c MonoImage. The namespace and name
2854 * lookups are case insensitive.
2856 MonoClass *
2857 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
2859 ERROR_DECL (error);
2860 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, error);
2861 mono_error_cleanup (error);
2863 return res;
2867 * mono_class_from_name_case_checked:
2868 * \param image The MonoImage where the type is looked up in
2869 * \param name_space the type namespace
2870 * \param name the type short name.
2871 * \param error if
2873 * Obtains a MonoClass with a given namespace and a given name which
2874 * is located in the given MonoImage. The namespace and name
2875 * lookups are case insensitive.
2877 * \returns The MonoClass if the given namespace and name were found, or NULL if it
2878 * was not found. The \p error object will contain information about the problem
2879 * in that case.
2881 MonoClass *
2882 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
2884 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
2885 guint32 cols [MONO_TYPEDEF_SIZE];
2886 const char *n;
2887 const char *nspace;
2888 guint32 i, visib;
2890 error_init (error);
2892 if (image_is_dynamic (image)) {
2893 guint32 token = 0;
2894 FindUserData user_data;
2896 mono_image_init_name_cache (image);
2897 mono_image_lock (image);
2899 user_data.key = name_space;
2900 user_data.value = NULL;
2901 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
2903 if (user_data.value) {
2904 GHashTable *nspace_table = (GHashTable*)user_data.value;
2906 user_data.key = name;
2907 user_data.value = NULL;
2909 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
2911 if (user_data.value)
2912 token = GPOINTER_TO_UINT (user_data.value);
2915 mono_image_unlock (image);
2917 if (token)
2918 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
2919 else
2920 return NULL;
2924 /* add a cache if needed */
2925 for (i = 1; i <= t->rows; ++i) {
2926 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
2927 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2929 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2930 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2932 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
2933 continue;
2934 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2935 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2936 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
2937 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
2939 return NULL;
2942 static MonoClass*
2943 return_nested_in (MonoClass *klass, char *nested)
2945 MonoClass *found;
2946 char *s = strchr (nested, '/');
2947 gpointer iter = NULL;
2949 if (s) {
2950 *s = 0;
2951 s++;
2954 while ((found = mono_class_get_nested_types (klass, &iter))) {
2955 if (strcmp (m_class_get_name (found), nested) == 0) {
2956 if (s)
2957 return return_nested_in (found, s);
2958 return found;
2961 return NULL;
2964 static MonoClass*
2965 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
2967 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
2968 MonoImage *file_image;
2969 MonoClass *klass;
2970 int i;
2972 error_init (error);
2975 * The EXPORTEDTYPES table only contains public types, so have to search the
2976 * modules as well.
2977 * Note: image->modules contains the contents of the MODULEREF table, while
2978 * the real module list is in the FILE table.
2980 for (i = 0; i < file_table->rows; i++) {
2981 guint32 cols [MONO_FILE_SIZE];
2982 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
2983 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
2984 continue;
2986 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
2987 if (file_image) {
2988 klass = mono_class_from_name_checked (file_image, name_space, name, error);
2989 if (klass || !is_ok (error))
2990 return klass;
2994 return NULL;
2997 static MonoClass *
2998 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
3000 GHashTable *nspace_table;
3001 MonoImage *loaded_image;
3002 guint32 token = 0;
3003 int i;
3004 MonoClass *klass;
3005 char *nested;
3006 char buf [1024];
3008 error_init (error);
3010 // Checking visited images avoids stack overflows when cyclic references exist.
3011 if (g_hash_table_lookup (visited_images, image))
3012 return NULL;
3014 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
3016 if ((nested = (char*)strchr (name, '/'))) {
3017 int pos = nested - name;
3018 int len = strlen (name);
3019 if (len > 1023)
3020 return NULL;
3021 memcpy (buf, name, len + 1);
3022 buf [pos] = 0;
3023 nested = buf + pos + 1;
3024 name = buf;
3027 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
3028 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
3029 gboolean res = get_class_from_name (image, name_space, name, &klass);
3030 if (res) {
3031 if (!klass) {
3032 klass = search_modules (image, name_space, name, error);
3033 if (!is_ok (error))
3034 return NULL;
3036 if (nested)
3037 return klass ? return_nested_in (klass, nested) : NULL;
3038 else
3039 return klass;
3043 mono_image_init_name_cache (image);
3044 mono_image_lock (image);
3046 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
3048 if (nspace_table)
3049 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
3051 mono_image_unlock (image);
3053 if (!token && image_is_dynamic (image) && image->modules) {
3054 /* Search modules as well */
3055 for (i = 0; i < image->module_count; ++i) {
3056 MonoImage *module = image->modules [i];
3058 klass = mono_class_from_name_checked (module, name_space, name, error);
3059 if (klass || !is_ok (error))
3060 return klass;
3064 if (!token) {
3065 klass = search_modules (image, name_space, name, error);
3066 if (klass || !is_ok (error))
3067 return klass;
3068 return NULL;
3071 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
3072 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
3073 guint32 cols [MONO_EXP_TYPE_SIZE];
3074 guint32 idx, impl;
3076 idx = mono_metadata_token_index (token);
3078 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
3080 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
3081 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
3082 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
3083 if (!loaded_image)
3084 return NULL;
3085 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
3086 if (nested)
3087 return klass ? return_nested_in (klass, nested) : NULL;
3088 return klass;
3089 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
3090 guint32 assembly_idx;
3092 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
3094 mono_assembly_load_reference (image, assembly_idx - 1);
3095 g_assert (image->references [assembly_idx - 1]);
3096 if (image->references [assembly_idx - 1] == (gpointer)-1)
3097 return NULL;
3098 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
3099 if (nested)
3100 return klass ? return_nested_in (klass, nested) : NULL;
3101 return klass;
3102 } else {
3103 g_assert_not_reached ();
3107 token = MONO_TOKEN_TYPE_DEF | token;
3109 klass = mono_class_get_checked (image, token, error);
3110 if (nested)
3111 return return_nested_in (klass, nested);
3112 return klass;
3116 * mono_class_from_name_checked:
3117 * \param image The MonoImage where the type is looked up in
3118 * \param name_space the type namespace
3119 * \param name the type short name.
3121 * Obtains a MonoClass with a given namespace and a given name which
3122 * is located in the given MonoImage.
3124 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
3125 * set if the class was not found or it will return NULL and set the error if there was a loading error.
3127 MonoClass *
3128 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
3130 MonoClass *klass;
3131 GHashTable *visited_images;
3133 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
3135 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
3137 g_hash_table_destroy (visited_images);
3139 return klass;
3143 * mono_class_from_name:
3144 * \param image The \c MonoImage where the type is looked up in
3145 * \param name_space the type namespace
3146 * \param name the type short name.
3148 * Obtains a \c MonoClass with a given namespace and a given name which
3149 * is located in the given \c MonoImage.
3151 * To reference nested classes, use the "/" character as a separator.
3152 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
3153 * inside \c Foo, like this: "class Foo { class Bar {} }".
3155 MonoClass *
3156 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
3158 MonoClass *klass;
3159 MONO_ENTER_GC_UNSAFE;
3160 ERROR_DECL (error);
3162 klass = mono_class_from_name_checked (image, name_space, name, error);
3163 mono_error_cleanup (error); /* FIXME Don't swallow the error */
3164 MONO_EXIT_GC_UNSAFE;
3165 return klass;
3169 * mono_class_load_from_name:
3170 * \param image The MonoImage where the type is looked up in
3171 * \param name_space the type namespace
3172 * \param name the type short name.
3174 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
3175 * This function should be used by the runtime for critical types to which there's no way to recover but crash
3176 * If they are missing. Thing of System.Object or System.String.
3178 MonoClass *
3179 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
3181 ERROR_DECL (error);
3182 MonoClass *klass;
3184 klass = mono_class_from_name_checked (image, name_space, name, error);
3185 if (!klass)
3186 g_error ("Runtime critical type %s.%s not found", name_space, name);
3187 mono_error_assertf_ok (error, "Could not load runtime critical type %s.%s", name_space, name);
3188 return klass;
3192 * mono_class_try_load_from_name:
3193 * \param image The MonoImage where the type is looked up in
3194 * \param name_space the type namespace
3195 * \param name the type short name.
3197 * This function tries to load a type, returning the class was found or NULL otherwise.
3198 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
3200 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
3201 * a type that we would otherwise assume to be available but was not due some error.
3204 MonoClass*
3205 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
3207 ERROR_DECL (error);
3208 MonoClass *klass;
3210 klass = mono_class_from_name_checked (image, name_space, name, error);
3211 mono_error_assertf_ok (error, "Could not load runtime critical type %s.%s", name_space, name);
3212 return klass;
3217 * mono_class_is_subclass_of:
3218 * \param klass class to probe if it is a subclass of another one
3219 * \param klassc the class we suspect is the base class
3220 * \param check_interfaces whether we should perform interface checks
3222 * This method determines whether \p klass is a subclass of \p klassc.
3224 * If the \p check_interfaces flag is set, then if \p klassc is an interface
3225 * this method return TRUE if the \p klass implements the interface or
3226 * if \p klass is an interface, if one of its base classes is \p klass.
3228 * If \p check_interfaces is false, then if \p klass is not an interface,
3229 * it returns TRUE if the \p klass is a subclass of \p klassc.
3231 * if \p klass is an interface and \p klassc is \c System.Object, then this function
3232 * returns TRUE.
3235 gboolean
3236 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
3237 gboolean check_interfaces)
3239 gboolean result;
3240 MONO_ENTER_GC_UNSAFE;
3241 result = mono_class_is_subclass_of_internal (klass, klassc, check_interfaces);
3242 MONO_EXIT_GC_UNSAFE;
3243 return result;
3246 gboolean
3247 mono_class_is_subclass_of_internal (MonoClass *klass, MonoClass *klassc,
3248 gboolean check_interfaces)
3250 /* FIXME test for interfaces with variant generic arguments */
3251 mono_class_init_internal (klass);
3252 mono_class_init_internal (klassc);
3254 if (check_interfaces && MONO_CLASS_IS_INTERFACE_INTERNAL (klassc) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass)) {
3255 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, m_class_get_interface_id (klassc)))
3256 return TRUE;
3257 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE_INTERNAL (klassc) && MONO_CLASS_IS_INTERFACE_INTERNAL (klass)) {
3258 int i;
3260 MonoClass **klass_interfaces = m_class_get_interfaces (klass);
3261 for (i = 0; i < m_class_get_interface_count (klass); i ++) {
3262 MonoClass *ic = klass_interfaces [i];
3263 if (ic == klassc)
3264 return TRUE;
3266 } else {
3267 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass) && mono_class_has_parent (klass, klassc))
3268 return TRUE;
3272 * MS.NET thinks interfaces are a subclass of Object, so we think it as
3273 * well.
3275 if (klassc == mono_defaults.object_class)
3276 return TRUE;
3278 return FALSE;
3281 static gboolean
3282 mono_type_is_generic_argument (MonoType *type)
3284 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
3287 gboolean
3288 mono_class_has_variant_generic_params (MonoClass *klass)
3290 int i;
3291 MonoGenericContainer *container;
3293 if (!mono_class_is_ginst (klass))
3294 return FALSE;
3296 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
3298 for (i = 0; i < container->type_argc; ++i)
3299 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
3300 return TRUE;
3302 return FALSE;
3305 static gboolean
3306 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
3308 if (target == candidate)
3309 return TRUE;
3311 if (check_for_reference_conv &&
3312 mono_type_is_generic_argument (m_class_get_byval_arg (target)) &&
3313 mono_type_is_generic_argument (m_class_get_byval_arg (candidate))) {
3314 MonoGenericParam *gparam = m_class_get_byval_arg (candidate)->data.generic_param;
3315 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
3317 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
3318 return FALSE;
3320 if (!mono_class_is_assignable_from_internal (target, candidate))
3321 return FALSE;
3322 return TRUE;
3326 * @container the generic container from the GTD
3327 * @klass: the class to be assigned to
3328 * @oklass: the source class
3330 * Both @klass and @oklass must be instances of the same generic interface.
3332 * Returns: TRUE if @klass can be assigned to a @klass variable
3334 gboolean
3335 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
3337 int j;
3338 MonoType **klass_argv, **oklass_argv;
3339 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
3340 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
3342 if (klass == oklass)
3343 return TRUE;
3345 /*Viable candidates are instances of the same generic interface*/
3346 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
3347 return FALSE;
3349 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
3350 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
3352 for (j = 0; j < container->type_argc; ++j) {
3353 MonoClass *param1_class = mono_class_from_mono_type_internal (klass_argv [j]);
3354 MonoClass *param2_class = mono_class_from_mono_type_internal (oklass_argv [j]);
3356 if (m_class_is_valuetype (param1_class) != m_class_is_valuetype (param2_class) || (m_class_is_valuetype (param1_class) && param1_class != param2_class))
3357 return FALSE;
3360 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3361 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3363 if (param1_class != param2_class) {
3364 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
3365 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
3366 return FALSE;
3367 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
3368 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
3369 return FALSE;
3370 } else
3371 return FALSE;
3374 return TRUE;
3377 static gboolean
3378 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
3380 MonoGenericParam *gparam, *ogparam;
3381 MonoGenericParamInfo *tinfo, *cinfo;
3382 MonoClass **candidate_class;
3383 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
3384 int tmask, cmask;
3386 if (target == candidate)
3387 return TRUE;
3388 MonoType *target_byval_arg = m_class_get_byval_arg (target);
3389 MonoType *candidate_byval_arg = m_class_get_byval_arg (candidate);
3390 if (target_byval_arg->type != candidate_byval_arg->type)
3391 return FALSE;
3393 gparam = target_byval_arg->data.generic_param;
3394 ogparam = candidate_byval_arg->data.generic_param;
3395 tinfo = mono_generic_param_info (gparam);
3396 cinfo = mono_generic_param_info (ogparam);
3398 class_constraint_satisfied = FALSE;
3399 valuetype_constraint_satisfied = FALSE;
3401 /*candidate must have a super set of target's special constraints*/
3402 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
3403 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
3405 if (cinfo->constraints) {
3406 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
3407 MonoClass *cc = *candidate_class;
3408 MonoType *cc_byval_arg = m_class_get_byval_arg (cc);
3410 if (mono_type_is_reference (cc_byval_arg) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc))
3411 class_constraint_satisfied = TRUE;
3412 else if (!mono_type_is_reference (cc_byval_arg) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc))
3413 valuetype_constraint_satisfied = TRUE;
3416 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
3417 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
3419 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
3420 return FALSE;
3421 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
3422 return FALSE;
3423 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
3424 valuetype_constraint_satisfied)) {
3425 return FALSE;
3429 /*candidate type constraints must be a superset of target's*/
3430 if (tinfo->constraints) {
3431 MonoClass **target_class;
3432 for (target_class = tinfo->constraints; *target_class; ++target_class) {
3433 MonoClass *tc = *target_class;
3434 MonoType *tc_byval_arg = m_class_get_byval_arg (tc);
3437 * A constraint from @target might inflate into @candidate itself and in that case we don't need
3438 * check it's constraints since it satisfy the constraint by itself.
3440 if (mono_metadata_type_equal (tc_byval_arg, candidate_byval_arg))
3441 continue;
3443 if (!cinfo->constraints)
3444 return FALSE;
3446 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
3447 MonoClass *cc = *candidate_class;
3449 if (mono_class_is_assignable_from_internal (tc, cc))
3450 break;
3453 * This happens when we have the following:
3455 * Bar<K> where K : IFace
3456 * Foo<T, U> where T : U where U : IFace
3457 * ...
3458 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
3461 if (mono_type_is_generic_argument (m_class_get_byval_arg (cc))) {
3462 if (mono_gparam_is_assignable_from (target, cc))
3463 break;
3466 if (!*candidate_class)
3467 return FALSE;
3471 /*candidate itself must have a constraint that satisfy target*/
3472 if (cinfo->constraints) {
3473 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
3474 MonoClass *cc = *candidate_class;
3475 if (mono_class_is_assignable_from_internal (target, cc))
3476 return TRUE;
3479 return FALSE;
3483 * mono_class_is_assignable_from_internal:
3484 * \param klass the class to be assigned to
3485 * \param oklass the source class
3487 * \returns TRUE if an instance of class \p oklass can be assigned to an
3488 * instance of class \p klass
3490 gboolean
3491 mono_class_is_assignable_from_internal (MonoClass *klass, MonoClass *oklass)
3493 gboolean result = FALSE;
3494 ERROR_DECL (error);
3495 mono_class_is_assignable_from_checked (klass, oklass, &result, error);
3496 mono_error_cleanup (error);
3497 return result;
3501 * mono_class_is_assignable_from:
3502 * \param klass the class to be assigned to
3503 * \param oklass the source class
3505 * \returns TRUE if an instance of class \p oklass can be assigned to an
3506 * instance of class \p klass
3508 mono_bool
3509 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
3511 gboolean result;
3512 MONO_ENTER_GC_UNSAFE;
3513 result = mono_class_is_assignable_from_internal (klass, oklass);
3514 MONO_EXIT_GC_UNSAFE;
3515 return result;
3519 * mono_class_is_assignable_from_checked:
3520 * \param klass the class to be assigned to
3521 * \param oklass the source class
3522 * \param result set if there was no error
3523 * \param error set if there was an error
3525 * Sets \p result to TRUE if an instance of class \p oklass can be assigned to
3526 * an instance of class \p klass or FALSE if it cannot. On error, no \p error
3527 * is set and \p result is not valid.
3529 void
3530 mono_class_is_assignable_from_checked (MonoClass *klass, MonoClass *oklass, gboolean *result, MonoError *error)
3532 MONO_REQ_GC_UNSAFE_MODE;
3533 g_assert (result);
3534 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
3535 if (!m_class_is_inited (klass))
3536 mono_class_init_internal (klass);
3538 if (!m_class_is_inited (oklass))
3539 mono_class_init_internal (oklass);
3541 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass)) {
3542 *result = FALSE;
3543 return;
3546 MonoType *klass_byval_arg = m_class_get_byval_arg (klass);
3547 MonoType *oklass_byval_arg = m_class_get_byval_arg (oklass);
3549 if (mono_type_is_generic_argument (klass_byval_arg)) {
3550 if (!mono_type_is_generic_argument (oklass_byval_arg)) {
3551 *result = FALSE;
3552 return;
3554 *result = mono_gparam_is_assignable_from (klass, oklass);
3555 return;
3558 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
3559 * has a constraint which is a class type:
3561 * class Foo { }
3562 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
3564 * In this case, Foo is assignable from T1.
3566 if (mono_type_is_generic_argument (oklass_byval_arg)) {
3567 MonoGenericParam *gparam = oklass_byval_arg->data.generic_param;
3568 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
3569 int i;
3571 if (constraints) {
3572 for (i = 0; constraints [i]; ++i) {
3573 if (mono_class_is_assignable_from_internal (klass, constraints [i])) {
3574 *result = TRUE;
3575 return;
3580 *result = mono_class_has_parent (oklass, klass);
3581 return;
3584 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass)) {
3586 /* interface_offsets might not be set for dynamic classes */
3587 if (mono_class_get_ref_info_handle (oklass) && !m_class_get_interface_bitmap (oklass)) {
3589 * oklass might be a generic type parameter but they have
3590 * interface_offsets set.
3592 gboolean assign_result = mono_reflection_call_is_assignable_to (oklass, klass, error);
3593 return_if_nok (error);
3594 *result = assign_result;
3595 return;
3597 if (!m_class_get_interface_bitmap (oklass)) {
3598 /* Happens with generic instances of not-yet created dynamic types */
3599 *result = FALSE;
3600 return;
3602 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, m_class_get_interface_id (klass))) {
3603 *result = TRUE;
3604 return;
3607 if (m_class_is_array_special_interface (klass) && m_class_get_rank (oklass) == 1) {
3608 if (mono_class_is_gtd (klass)) {
3609 /* klass is an array special gtd like
3610 * IList`1<>, and oklass is X[] for some X.
3611 * Moreover we know that X isn't !0 (the gparam
3612 * of IList`1) because in that case we would
3613 * have returned TRUE for
3614 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
3616 *result = FALSE;
3617 return;
3619 // FIXME: IEnumerator`1 should not be an array special interface.
3620 // The correct fix is to make
3621 // ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
3622 // return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
3623 // and to stop marking IEnumerable`1 as an array_special_interface.
3624 if (mono_class_get_generic_type_definition (klass) == mono_defaults.generic_ienumerator_class) {
3625 *result = FALSE;
3626 return;
3629 //XXX we could offset this by having the cast target computed at JIT time
3630 //XXX we could go even further and emit a wrapper that would do the extra type check
3631 MonoClass *iface_klass = mono_class_from_mono_type_internal (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
3632 MonoClass *obj_klass = m_class_get_cast_class (oklass); //This gets us the cast class of element type of the array
3634 // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
3635 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
3636 if (!mono_class_is_nullable (iface_klass)) {
3637 if (m_class_is_valuetype (iface_klass))
3638 iface_klass = m_class_get_cast_class (iface_klass);
3640 //array covariant casts only operates on scalar to scalar
3641 //This is so int[] can't be casted to IComparable<int>[]
3642 if (!(m_class_is_valuetype (obj_klass) && !m_class_is_valuetype (iface_klass)) && mono_class_is_assignable_from_internal (iface_klass, obj_klass)) {
3643 *result = TRUE;
3644 return;
3649 if (mono_class_has_variant_generic_params (klass)) {
3650 int i;
3651 mono_class_setup_interfaces (oklass, error);
3652 return_if_nok (error);
3654 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
3655 for (i = 0; i < m_class_get_interface_offsets_count (oklass); ++i) {
3656 MonoClass *iface = m_class_get_interfaces_packed (oklass) [i];
3658 if (mono_class_is_variant_compatible (klass, iface, FALSE)) {
3659 *result = TRUE;
3660 return;
3664 *result = FALSE;
3665 return;
3666 } else if (m_class_is_delegate (klass)) {
3667 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE)) {
3668 *result = TRUE;
3669 return;
3671 }else if (m_class_get_rank (klass)) {
3672 MonoClass *eclass, *eoclass;
3674 if (m_class_get_rank (oklass) != m_class_get_rank (klass)) {
3675 *result = FALSE;
3676 return;
3679 /* vectors vs. one dimensional arrays */
3680 if (oklass_byval_arg->type != klass_byval_arg->type) {
3681 *result = FALSE;
3682 return;
3685 eclass = m_class_get_cast_class (klass);
3686 eoclass = m_class_get_cast_class (oklass);
3689 * a is b does not imply a[] is b[] when a is a valuetype, and
3690 * b is a reference type.
3693 if (m_class_is_valuetype (eoclass)) {
3694 if ((eclass == mono_defaults.enum_class) ||
3695 (eclass == m_class_get_parent (mono_defaults.enum_class)) ||
3696 (eclass == mono_defaults.object_class)) {
3697 *result = FALSE;
3698 return;
3702 mono_class_is_assignable_from_checked (eclass, eoclass, result, error);
3703 return;
3704 } else if (mono_class_is_nullable (klass)) {
3705 if (mono_class_is_nullable (oklass))
3706 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass), m_class_get_cast_class (oklass), result, error);
3707 else
3708 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass), oklass, result, error);
3709 return;
3710 } else if (klass == mono_defaults.object_class) {
3711 *result = TRUE;
3712 return;
3715 *result = mono_class_has_parent (oklass, klass);
3718 /*Check if @oklass is variant compatible with @klass.*/
3719 static gboolean
3720 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
3722 int j;
3723 MonoType **klass_argv, **oklass_argv;
3724 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
3725 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
3727 /*Viable candidates are instances of the same generic interface*/
3728 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
3729 return FALSE;
3731 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
3732 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
3734 for (j = 0; j < container->type_argc; ++j) {
3735 MonoClass *param1_class = mono_class_from_mono_type_internal (klass_argv [j]);
3736 MonoClass *param2_class = mono_class_from_mono_type_internal (oklass_argv [j]);
3738 if (m_class_is_valuetype (param1_class) != m_class_is_valuetype (param2_class))
3739 return FALSE;
3742 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3743 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3745 if (param1_class != param2_class) {
3746 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
3747 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
3748 return FALSE;
3749 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
3750 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
3751 return FALSE;
3752 } else
3753 return FALSE;
3756 return TRUE;
3758 /*Check if @candidate implements the interface @target*/
3759 static gboolean
3760 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
3762 ERROR_DECL (error);
3763 int i;
3764 gboolean is_variant = mono_class_has_variant_generic_params (target);
3766 if (is_variant && MONO_CLASS_IS_INTERFACE_INTERNAL (candidate)) {
3767 if (mono_class_is_variant_compatible_slow (target, candidate))
3768 return TRUE;
3771 do {
3772 if (candidate == target)
3773 return TRUE;
3775 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3776 if (image_is_dynamic (m_class_get_image (candidate)) && !m_class_was_typebuilder (candidate)) {
3777 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
3778 int j;
3779 if (tb && tb->interfaces) {
3780 for (j = mono_array_length_internal (tb->interfaces) - 1; j >= 0; --j) {
3781 MonoReflectionType *iface = mono_array_get_internal (tb->interfaces, MonoReflectionType*, j);
3782 MonoClass *iface_class;
3784 /* we can't realize the type here since it can do pretty much anything. */
3785 if (!iface->type)
3786 continue;
3787 iface_class = mono_class_from_mono_type_internal (iface->type);
3788 if (iface_class == target)
3789 return TRUE;
3790 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
3791 return TRUE;
3792 if (mono_class_implement_interface_slow (target, iface_class))
3793 return TRUE;
3796 } else {
3797 /*setup_interfaces don't mono_class_init_internal anything*/
3798 /*FIXME this doesn't handle primitive type arrays.
3799 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3800 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3802 mono_class_setup_interfaces (candidate, error);
3803 if (!mono_error_ok (error)) {
3804 mono_error_cleanup (error);
3805 return FALSE;
3808 int candidate_interface_count = m_class_get_interface_count (candidate);
3809 MonoClass **candidate_interfaces = m_class_get_interfaces (candidate);
3810 for (i = 0; i < candidate_interface_count; ++i) {
3811 if (candidate_interfaces [i] == target)
3812 return TRUE;
3814 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate_interfaces [i]))
3815 return TRUE;
3817 if (mono_class_implement_interface_slow (target, candidate_interfaces [i]))
3818 return TRUE;
3821 candidate = m_class_get_parent (candidate);
3822 } while (candidate);
3824 return FALSE;
3828 * Check if @oklass can be assigned to @klass.
3829 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
3831 gboolean
3832 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
3834 if (candidate == target)
3835 return TRUE;
3836 if (target == mono_defaults.object_class)
3837 return TRUE;
3839 if (mono_class_has_parent (candidate, target))
3840 return TRUE;
3842 /*If target is not an interface there is no need to check them.*/
3843 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target))
3844 return mono_class_implement_interface_slow (target, candidate);
3846 if (m_class_is_delegate (target) && mono_class_has_variant_generic_params (target))
3847 return mono_class_is_variant_compatible (target, candidate, FALSE);
3849 if (m_class_get_rank (target)) {
3850 MonoClass *eclass, *eoclass;
3852 if (m_class_get_rank (target) != m_class_get_rank (candidate))
3853 return FALSE;
3855 /* vectors vs. one dimensional arrays */
3856 if (m_class_get_byval_arg (target)->type != m_class_get_byval_arg (candidate)->type)
3857 return FALSE;
3859 eclass = m_class_get_cast_class (target);
3860 eoclass = m_class_get_cast_class (candidate);
3863 * a is b does not imply a[] is b[] when a is a valuetype, and
3864 * b is a reference type.
3867 if (m_class_is_valuetype (eoclass)) {
3868 if ((eclass == mono_defaults.enum_class) ||
3869 (eclass == m_class_get_parent (mono_defaults.enum_class)) ||
3870 (eclass == mono_defaults.object_class))
3871 return FALSE;
3874 return mono_class_is_assignable_from_slow (eclass, eoclass);
3876 /*FIXME properly handle nullables */
3877 /*FIXME properly handle (M)VAR */
3878 return FALSE;
3882 * mono_generic_param_get_base_type:
3884 * Return the base type of the given generic parameter from its constraints.
3886 * Could be another generic parameter, or it could be Object or ValueType.
3888 MonoClass*
3889 mono_generic_param_get_base_type (MonoClass *klass)
3891 MonoType *type = m_class_get_byval_arg (klass);
3892 g_assert (mono_type_is_generic_argument (type));
3894 MonoGenericParam *gparam = type->data.generic_param;
3896 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
3898 MonoClass *base_class = mono_defaults.object_class;
3900 if (constraints) {
3901 int i;
3902 for (i = 0; constraints [i]; ++i) {
3903 MonoClass *constraint = constraints[i];
3905 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint))
3906 continue;
3908 MonoType *constraint_type = m_class_get_byval_arg (constraint);
3909 if (mono_type_is_generic_argument (constraint_type)) {
3910 MonoGenericParam *constraint_param = constraint_type->data.generic_param;
3911 MonoGenericParamInfo *constraint_info = mono_generic_param_info (constraint_param);
3912 if ((constraint_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0 &&
3913 (constraint_info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) == 0)
3914 continue;
3917 base_class = constraint;
3922 if (base_class == mono_defaults.object_class)
3924 MonoGenericParamInfo *gparam_info = mono_generic_param_info (gparam);
3925 if ((gparam_info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0) {
3926 base_class = mono_class_get_valuetype_class ();
3930 return base_class;
3934 * mono_class_get_cctor:
3935 * \param klass A MonoClass pointer
3937 * \returns The static constructor of \p klass if it exists, NULL otherwise.
3939 MonoMethod*
3940 mono_class_get_cctor (MonoClass *klass)
3942 MonoMethod *result = NULL;
3943 ERROR_DECL (error);
3944 MonoCachedClassInfo cached_info;
3946 if (image_is_dynamic (m_class_get_image (klass))) {
3948 * has_cctor is not set for these classes because mono_class_init_internal () is
3949 * not run for them.
3951 result = mono_class_get_method_from_name_checked (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME, error);
3952 mono_error_assert_msg_ok (error, "Could not lookup class cctor in dynamic image");
3953 return result;
3956 mono_class_init_internal (klass);
3958 if (!m_class_has_cctor (klass))
3959 return result;
3961 if (mono_class_is_ginst (klass) && !m_class_get_methods (klass)) {
3962 result = mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class), error);
3963 mono_error_assert_msg_ok (error, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
3964 return result;
3967 if (mono_class_get_cached_class_info (klass, &cached_info)) {
3968 result = mono_get_method_checked (m_class_get_image (klass), cached_info.cctor_token, klass, NULL, error);
3969 mono_error_assert_msg_ok (error, "Could not lookup class cctor from cached metadata");
3970 return result;
3973 result = mono_class_get_method_from_name_checked (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME, error);
3974 mono_error_assert_msg_ok (error, "Could not lookup class cctor");
3975 return result;
3979 * mono_class_get_finalizer:
3980 * \param klass: The MonoClass pointer
3982 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
3984 MonoMethod*
3985 mono_class_get_finalizer (MonoClass *klass)
3987 MonoCachedClassInfo cached_info;
3989 if (!m_class_is_inited (klass))
3990 mono_class_init_internal (klass);
3991 if (!mono_class_has_finalizer (klass))
3992 return NULL;
3994 if (mono_class_get_cached_class_info (klass, &cached_info)) {
3995 ERROR_DECL (error);
3996 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, error);
3997 mono_error_assert_msg_ok (error, "Could not lookup finalizer from cached metadata");
3998 return result;
3999 }else {
4000 mono_class_setup_vtable (klass);
4001 return m_class_get_vtable (klass) [mono_class_get_object_finalize_slot ()];
4006 * mono_class_needs_cctor_run:
4007 * \param klass the MonoClass pointer
4008 * \param caller a MonoMethod describing the caller
4010 * Determines whenever the class has a static constructor and whenever it
4011 * needs to be called when executing CALLER.
4013 gboolean
4014 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
4016 MonoMethod *method;
4018 method = mono_class_get_cctor (klass);
4019 if (method)
4020 return (method == caller) ? FALSE : TRUE;
4021 else
4022 return FALSE;
4026 * mono_class_array_element_size:
4027 * \param klass
4029 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4031 gint32
4032 mono_class_array_element_size (MonoClass *klass)
4034 MonoType *type = m_class_get_byval_arg (klass);
4036 handle_enum:
4037 switch (type->type) {
4038 case MONO_TYPE_I1:
4039 case MONO_TYPE_U1:
4040 case MONO_TYPE_BOOLEAN:
4041 return 1;
4042 case MONO_TYPE_I2:
4043 case MONO_TYPE_U2:
4044 case MONO_TYPE_CHAR:
4045 return 2;
4046 case MONO_TYPE_I4:
4047 case MONO_TYPE_U4:
4048 case MONO_TYPE_R4:
4049 return 4;
4050 case MONO_TYPE_I:
4051 case MONO_TYPE_U:
4052 case MONO_TYPE_PTR:
4053 case MONO_TYPE_CLASS:
4054 case MONO_TYPE_STRING:
4055 case MONO_TYPE_OBJECT:
4056 case MONO_TYPE_SZARRAY:
4057 case MONO_TYPE_ARRAY:
4058 return TARGET_SIZEOF_VOID_P;
4059 case MONO_TYPE_I8:
4060 case MONO_TYPE_U8:
4061 case MONO_TYPE_R8:
4062 return 8;
4063 case MONO_TYPE_VALUETYPE:
4064 if (m_class_is_enumtype (type->data.klass)) {
4065 type = mono_class_enum_basetype_internal (type->data.klass);
4066 klass = m_class_get_element_class (klass);
4067 goto handle_enum;
4069 return mono_class_value_size (klass, NULL);
4070 case MONO_TYPE_GENERICINST:
4071 type = m_class_get_byval_arg (type->data.generic_class->container_class);
4072 goto handle_enum;
4073 case MONO_TYPE_VAR:
4074 case MONO_TYPE_MVAR: {
4075 int align;
4077 return mono_type_size (type, &align);
4079 case MONO_TYPE_VOID:
4080 return 0;
4082 default:
4083 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
4085 return -1;
4089 * mono_array_element_size:
4090 * \param ac pointer to a \c MonoArrayClass
4092 * \returns The size of single array element.
4094 * LOCKING: Acquires the loader lock.
4096 gint32
4097 mono_array_element_size (MonoClass *ac)
4099 g_assert (m_class_get_rank (ac));
4100 if (G_UNLIKELY (!m_class_is_size_inited (ac))) {
4101 mono_class_setup_fields (ac);
4103 return m_class_get_sizes (ac).element_size;
4107 * mono_ldtoken:
4109 gpointer
4110 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
4111 MonoGenericContext *context)
4113 ERROR_DECL (error);
4114 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, error);
4115 mono_error_assert_ok (error);
4116 return res;
4119 gpointer
4120 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
4121 MonoGenericContext *context, MonoError *error)
4123 error_init (error);
4125 if (image_is_dynamic (image)) {
4126 MonoClass *tmp_handle_class;
4127 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
4129 mono_error_assert_ok (error);
4130 g_assert (tmp_handle_class);
4131 if (handle_class)
4132 *handle_class = tmp_handle_class;
4134 if (tmp_handle_class == mono_defaults.typehandle_class)
4135 return m_class_get_byval_arg ((MonoClass*)obj);
4136 else
4137 return obj;
4140 switch (token & 0xff000000) {
4141 case MONO_TOKEN_TYPE_DEF:
4142 case MONO_TOKEN_TYPE_REF:
4143 case MONO_TOKEN_TYPE_SPEC: {
4144 MonoType *type;
4145 if (handle_class)
4146 *handle_class = mono_defaults.typehandle_class;
4147 type = mono_type_get_checked (image, token, context, error);
4148 if (!type)
4149 return NULL;
4151 mono_class_init_internal (mono_class_from_mono_type_internal (type));
4152 /* We return a MonoType* as handle */
4153 return type;
4155 case MONO_TOKEN_FIELD_DEF: {
4156 MonoClass *klass;
4157 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
4158 if (!type) {
4159 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
4160 return NULL;
4162 if (handle_class)
4163 *handle_class = mono_defaults.fieldhandle_class;
4164 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
4165 if (!klass)
4166 return NULL;
4168 mono_class_init_internal (klass);
4169 return mono_class_get_field (klass, token);
4171 case MONO_TOKEN_METHOD_DEF:
4172 case MONO_TOKEN_METHOD_SPEC: {
4173 MonoMethod *meth;
4174 meth = mono_get_method_checked (image, token, NULL, context, error);
4175 if (handle_class)
4176 *handle_class = mono_defaults.methodhandle_class;
4177 if (!meth)
4178 return NULL;
4180 return meth;
4182 case MONO_TOKEN_MEMBER_REF: {
4183 guint32 cols [MONO_MEMBERREF_SIZE];
4184 const char *sig;
4185 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4186 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4187 mono_metadata_decode_blob_size (sig, &sig);
4188 if (*sig == 0x6) { /* it's a field */
4189 MonoClass *klass;
4190 MonoClassField *field;
4191 field = mono_field_from_token_checked (image, token, &klass, context, error);
4192 if (handle_class)
4193 *handle_class = mono_defaults.fieldhandle_class;
4194 return field;
4195 } else {
4196 MonoMethod *meth;
4197 meth = mono_get_method_checked (image, token, NULL, context, error);
4198 if (handle_class)
4199 *handle_class = mono_defaults.methodhandle_class;
4200 return meth;
4203 default:
4204 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
4206 return NULL;
4209 gpointer
4210 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
4212 MonoClass *handle_class;
4213 error_init (error);
4214 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
4217 gpointer
4218 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4220 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
4223 static MonoGetCachedClassInfo get_cached_class_info = NULL;
4225 void
4226 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
4228 get_cached_class_info = func;
4231 gboolean
4232 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
4234 if (!get_cached_class_info)
4235 return FALSE;
4236 else
4237 return get_cached_class_info (klass, res);
4240 void
4241 mono_install_get_class_from_name (MonoGetClassFromName func)
4243 get_class_from_name = func;
4247 * mono_class_get_image:
4249 * Use this method to get the \c MonoImage* where this class came from.
4251 * \returns The image where this class is defined.
4253 MonoImage*
4254 mono_class_get_image (MonoClass *klass)
4256 return m_class_get_image (klass);
4260 * mono_class_get_element_class:
4261 * \param klass the \c MonoClass to act on
4263 * Use this function to get the element class of an array.
4265 * \returns The element class of an array.
4267 MonoClass*
4268 mono_class_get_element_class (MonoClass *klass)
4270 MonoClass *result;
4271 MONO_ENTER_GC_UNSAFE;
4272 result = m_class_get_element_class (klass);
4273 MONO_EXIT_GC_UNSAFE;
4274 return result;
4278 * mono_class_is_valuetype:
4279 * \param klass the \c MonoClass to act on
4281 * Use this method to determine if the provided \c MonoClass* represents a value type,
4282 * or a reference type.
4284 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4286 gboolean
4287 mono_class_is_valuetype (MonoClass *klass)
4289 gboolean result;
4290 MONO_ENTER_GC_UNSAFE;
4291 result = m_class_is_valuetype (klass);
4292 MONO_EXIT_GC_UNSAFE;
4293 return result;
4297 * mono_class_is_enum:
4298 * \param klass the \c MonoClass to act on
4300 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4302 * \returns TRUE if the \c MonoClass represents an enumeration.
4304 gboolean
4305 mono_class_is_enum (MonoClass *klass)
4307 gboolean result;
4308 MONO_ENTER_GC_UNSAFE;
4309 result = m_class_is_enumtype (klass);
4310 MONO_EXIT_GC_UNSAFE;
4311 return result;
4315 * mono_class_enum_basetype_internal:
4316 * \param klass the \c MonoClass to act on
4318 * Use this function to get the underlying type for an enumeration value.
4320 * \returns The underlying type representation for an enumeration.
4322 MonoType*
4323 mono_class_enum_basetype_internal (MonoClass *klass)
4325 if (m_class_get_element_class (klass) == klass)
4326 /* SRE or broken types */
4327 return NULL;
4328 return m_class_get_byval_arg (m_class_get_element_class (klass));
4332 * mono_class_enum_basetype:
4333 * \param klass the \c MonoClass to act on
4335 * Use this function to get the underlying type for an enumeration value.
4337 * \returns The underlying type representation for an enumeration.
4339 MonoType*
4340 mono_class_enum_basetype (MonoClass *klass)
4342 MonoType *res;
4343 MONO_ENTER_GC_UNSAFE;
4344 res = mono_class_enum_basetype_internal (klass);
4345 MONO_EXIT_GC_UNSAFE;
4346 return res;
4350 * mono_class_get_parent
4351 * \param klass the \c MonoClass to act on
4353 * \returns The parent class for this class.
4355 MonoClass*
4356 mono_class_get_parent (MonoClass *klass)
4358 MonoClass *result;
4359 MONO_ENTER_GC_UNSAFE;
4360 result = m_class_get_parent (klass);
4361 MONO_EXIT_GC_UNSAFE;
4362 return result;
4366 * mono_class_get_nesting_type:
4367 * \param klass the \c MonoClass to act on
4369 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4371 * If the return is NULL, this indicates that this class is not nested.
4373 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4375 MonoClass*
4376 mono_class_get_nesting_type (MonoClass *klass)
4378 return m_class_get_nested_in (klass);
4382 * mono_class_get_rank:
4383 * \param klass the MonoClass to act on
4385 * \returns The rank for the array (the number of dimensions).
4388 mono_class_get_rank (MonoClass *klass)
4390 return m_class_get_rank (klass);
4394 * mono_class_get_name
4395 * \param klass the \c MonoClass to act on
4397 * \returns The name of the class.
4399 const char*
4400 mono_class_get_name (MonoClass *klass)
4402 const char *result;
4403 MONO_ENTER_GC_UNSAFE;
4404 result = m_class_get_name (klass);
4405 MONO_EXIT_GC_UNSAFE;
4406 return result;
4410 * mono_class_get_namespace:
4411 * \param klass the \c MonoClass to act on
4413 * \returns The namespace of the class.
4415 const char*
4416 mono_class_get_namespace (MonoClass *klass)
4418 const char *result;
4419 MONO_ENTER_GC_UNSAFE;
4420 result = m_class_get_name_space (klass);
4421 MONO_EXIT_GC_UNSAFE;
4422 return result;
4426 * mono_class_get_type:
4427 * \param klass the \c MonoClass to act on
4429 * This method returns the internal \c MonoType representation for the class.
4431 * \returns The \c MonoType from the class.
4433 MonoType*
4434 mono_class_get_type (MonoClass *klass)
4436 return m_class_get_byval_arg (klass);
4440 * mono_class_get_type_token:
4441 * \param klass the \c MonoClass to act on
4443 * This method returns type token for the class.
4445 * \returns The type token for the class.
4447 guint32
4448 mono_class_get_type_token (MonoClass *klass)
4450 return m_class_get_type_token (klass);
4454 * mono_class_get_byref_type:
4455 * \param klass the \c MonoClass to act on
4459 MonoType*
4460 mono_class_get_byref_type (MonoClass *klass)
4462 return m_class_get_this_arg (klass);
4466 * mono_class_num_fields:
4467 * \param klass the \c MonoClass to act on
4469 * \returns The number of static and instance fields in the class.
4472 mono_class_num_fields (MonoClass *klass)
4474 return mono_class_get_field_count (klass);
4478 * mono_class_num_methods:
4479 * \param klass the \c MonoClass to act on
4481 * \returns The number of methods in the class.
4484 mono_class_num_methods (MonoClass *klass)
4486 return mono_class_get_method_count (klass);
4490 * mono_class_num_properties
4491 * \param klass the \c MonoClass to act on
4493 * \returns The number of properties in the class.
4496 mono_class_num_properties (MonoClass *klass)
4498 mono_class_setup_properties (klass);
4500 return mono_class_get_property_info (klass)->count;
4504 * mono_class_num_events:
4505 * \param klass the \c MonoClass to act on
4507 * \returns The number of events in the class.
4510 mono_class_num_events (MonoClass *klass)
4512 mono_class_setup_events (klass);
4514 return mono_class_get_event_info (klass)->count;
4518 * mono_class_get_fields:
4519 * \param klass the \c MonoClass to act on
4521 * This routine is an iterator routine for retrieving the fields in a class.
4523 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4524 * iterate over all of the elements. When no more values are
4525 * available, the return value is NULL.
4527 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4529 MonoClassField*
4530 mono_class_get_fields (MonoClass* klass, gpointer *iter)
4532 MonoClassField *result;
4533 MONO_ENTER_GC_UNSAFE;
4534 result = mono_class_get_fields_internal (klass, iter);
4535 MONO_EXIT_GC_UNSAFE;
4536 return result;
4539 MonoClassField*
4540 mono_class_get_fields_internal (MonoClass *klass, gpointer *iter)
4542 MonoClassField* field;
4543 if (!iter)
4544 return NULL;
4545 if (!*iter) {
4546 mono_class_setup_fields (klass);
4547 if (mono_class_has_failure (klass))
4548 return NULL;
4549 /* start from the first */
4550 if (mono_class_get_field_count (klass)) {
4551 MonoClassField *klass_fields = m_class_get_fields (klass);
4552 *iter = &klass_fields [0];
4553 return &klass_fields [0];
4554 } else {
4555 /* no fields */
4556 return NULL;
4559 field = (MonoClassField *)*iter;
4560 field++;
4561 if (field < &m_class_get_fields (klass) [mono_class_get_field_count (klass)]) {
4562 *iter = field;
4563 return field;
4565 return NULL;
4569 * mono_class_get_methods:
4570 * \param klass the \c MonoClass to act on
4572 * This routine is an iterator routine for retrieving the fields in a class.
4574 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4575 * iterate over all of the elements. When no more values are
4576 * available, the return value is NULL.
4578 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4580 MonoMethod*
4581 mono_class_get_methods (MonoClass* klass, gpointer *iter)
4583 MonoMethod** method;
4584 if (!iter)
4585 return NULL;
4586 if (!*iter) {
4587 mono_class_setup_methods (klass);
4589 MonoMethod **klass_methods = m_class_get_methods (klass);
4591 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4592 * FIXME we should better report this error to the caller
4594 if (!klass_methods)
4595 return NULL;
4596 /* start from the first */
4597 if (mono_class_get_method_count (klass)) {
4598 *iter = &klass_methods [0];
4599 return klass_methods [0];
4600 } else {
4601 /* no method */
4602 return NULL;
4605 method = (MonoMethod **)*iter;
4606 method++;
4607 if (method < &m_class_get_methods (klass) [mono_class_get_method_count (klass)]) {
4608 *iter = method;
4609 return *method;
4611 return NULL;
4615 * mono_class_get_properties:
4616 * \param klass the \c MonoClass to act on
4618 * This routine is an iterator routine for retrieving the properties in a class.
4620 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4621 * iterate over all of the elements. When no more values are
4622 * available, the return value is NULL.
4624 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4626 MonoProperty*
4627 mono_class_get_properties (MonoClass* klass, gpointer *iter)
4629 MonoProperty* property;
4630 if (!iter)
4631 return NULL;
4632 if (!*iter) {
4633 mono_class_setup_properties (klass);
4634 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
4635 /* start from the first */
4636 if (info->count) {
4637 *iter = &info->properties [0];
4638 return (MonoProperty *)*iter;
4639 } else {
4640 /* no fields */
4641 return NULL;
4644 property = (MonoProperty *)*iter;
4645 property++;
4646 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
4647 if (property < &info->properties [info->count]) {
4648 *iter = property;
4649 return (MonoProperty *)*iter;
4651 return NULL;
4655 * mono_class_get_events:
4656 * \param klass the \c MonoClass to act on
4658 * This routine is an iterator routine for retrieving the properties in a class.
4660 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4661 * iterate over all of the elements. When no more values are
4662 * available, the return value is NULL.
4664 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4666 MonoEvent*
4667 mono_class_get_events (MonoClass* klass, gpointer *iter)
4669 MonoEvent* event;
4670 if (!iter)
4671 return NULL;
4672 if (!*iter) {
4673 mono_class_setup_events (klass);
4674 MonoClassEventInfo *info = mono_class_get_event_info (klass);
4675 /* start from the first */
4676 if (info->count) {
4677 *iter = &info->events [0];
4678 return (MonoEvent *)*iter;
4679 } else {
4680 /* no fields */
4681 return NULL;
4684 event = (MonoEvent *)*iter;
4685 event++;
4686 MonoClassEventInfo *info = mono_class_get_event_info (klass);
4687 if (event < &info->events [info->count]) {
4688 *iter = event;
4689 return (MonoEvent *)*iter;
4691 return NULL;
4695 * mono_class_get_interfaces
4696 * \param klass the \c MonoClass to act on
4698 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4700 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4701 * iterate over all of the elements. When no more values are
4702 * available, the return value is NULL.
4704 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4706 MonoClass*
4707 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
4709 ERROR_DECL (error);
4710 MonoClass** iface;
4711 if (!iter)
4712 return NULL;
4713 if (!*iter) {
4714 if (!m_class_is_inited (klass))
4715 mono_class_init_internal (klass);
4716 if (!m_class_is_interfaces_inited (klass)) {
4717 mono_class_setup_interfaces (klass, error);
4718 if (!mono_error_ok (error)) {
4719 mono_error_cleanup (error);
4720 return NULL;
4723 /* start from the first */
4724 if (m_class_get_interface_count (klass)) {
4725 *iter = &m_class_get_interfaces (klass) [0];
4726 return m_class_get_interfaces (klass) [0];
4727 } else {
4728 /* no interface */
4729 return NULL;
4732 iface = (MonoClass **)*iter;
4733 iface++;
4734 if (iface < &m_class_get_interfaces (klass) [m_class_get_interface_count (klass)]) {
4735 *iter = iface;
4736 return *iface;
4738 return NULL;
4742 * mono_class_get_nested_types
4743 * \param klass the \c MonoClass to act on
4745 * This routine is an iterator routine for retrieving the nested types of a class.
4746 * This works only if \p klass is non-generic, or a generic type definition.
4748 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4749 * iterate over all of the elements. When no more values are
4750 * available, the return value is NULL.
4752 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4754 MonoClass*
4755 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
4757 GList *item;
4759 if (!iter)
4760 return NULL;
4761 if (!m_class_is_nested_classes_inited (klass))
4762 mono_class_setup_nested_types (klass);
4764 if (!*iter) {
4765 GList *nested_classes = mono_class_get_nested_classes_property (klass);
4766 /* start from the first */
4767 if (nested_classes) {
4768 *iter = nested_classes;
4769 return (MonoClass *)nested_classes->data;
4770 } else {
4771 /* no nested types */
4772 return NULL;
4775 item = (GList *)*iter;
4776 item = item->next;
4777 if (item) {
4778 *iter = item;
4779 return (MonoClass *)item->data;
4781 return NULL;
4786 * mono_class_is_delegate
4787 * \param klass the \c MonoClass to act on
4789 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4791 mono_bool
4792 mono_class_is_delegate (MonoClass *klass)
4794 mono_bool result;
4795 MONO_ENTER_GC_UNSAFE;
4796 result = m_class_is_delegate (klass);
4797 MONO_EXIT_GC_UNSAFE;
4798 return result;
4802 * mono_class_implements_interface
4803 * \param klass The MonoClass to act on
4804 * \param interface The interface to check if \p klass implements.
4806 * \returns TRUE if \p klass implements \p interface.
4808 mono_bool
4809 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
4811 return mono_class_is_assignable_from_internal (iface, klass);
4815 * mono_field_get_name:
4816 * \param field the \c MonoClassField to act on
4818 * \returns The name of the field.
4820 const char*
4821 mono_field_get_name (MonoClassField *field)
4823 return field->name;
4827 * mono_field_get_type_internal:
4828 * \param field the \c MonoClassField to act on
4829 * \returns \c MonoType of the field.
4831 MonoType*
4832 mono_field_get_type_internal (MonoClassField *field)
4834 MonoType *type = field->type;
4835 if (type)
4836 return type;
4838 ERROR_DECL (error);
4839 type = mono_field_get_type_checked (field, error);
4840 if (!mono_error_ok (error)) {
4841 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (error));
4842 mono_error_cleanup (error);
4844 return type;
4848 * mono_field_get_type:
4849 * \param field the \c MonoClassField to act on
4850 * \returns \c MonoType of the field.
4852 MonoType*
4853 mono_field_get_type (MonoClassField *field)
4855 MonoType *type = field->type;
4856 if (type)
4857 return type;
4859 MONO_ENTER_GC_UNSAFE;
4860 type = mono_field_get_type_internal (field);
4861 MONO_EXIT_GC_UNSAFE;
4862 return type;
4866 * mono_field_get_type_checked:
4867 * \param field the \c MonoClassField to act on
4868 * \param error used to return any error found while retrieving \p field type
4870 * \returns \c MonoType of the field.
4872 MonoType*
4873 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
4875 error_init (error);
4876 MonoType *type = field->type;
4877 if (type)
4878 return type;
4879 mono_field_resolve_type (field, error);
4880 return field->type;
4884 * mono_field_get_parent:
4885 * \param field the \c MonoClassField to act on
4887 * \returns \c MonoClass where the field was defined.
4889 MonoClass*
4890 mono_field_get_parent (MonoClassField *field)
4892 return field->parent;
4896 * mono_field_get_flags;
4897 * \param field the \c MonoClassField to act on
4899 * The metadata flags for a field are encoded using the
4900 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
4902 * \returns The flags for the field.
4904 guint32
4905 mono_field_get_flags (MonoClassField *field)
4907 if (!field->type)
4908 return mono_field_resolve_flags (field);
4909 return field->type->attrs;
4913 * mono_field_get_offset:
4914 * \param field the \c MonoClassField to act on
4916 * \returns The field offset.
4918 guint32
4919 mono_field_get_offset (MonoClassField *field)
4921 mono_class_setup_fields(field->parent);
4922 return field->offset;
4925 static const char *
4926 mono_field_get_rva (MonoClassField *field)
4928 guint32 rva;
4929 int field_index;
4930 MonoClass *klass = field->parent;
4931 MonoFieldDefaultValue *def_values;
4933 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
4935 def_values = mono_class_get_field_def_values (klass);
4936 if (!def_values) {
4937 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
4939 mono_class_set_field_def_values (klass, def_values);
4942 field_index = mono_field_get_index (field);
4944 if (!def_values [field_index].data && !image_is_dynamic (m_class_get_image (klass))) {
4945 int first_field_idx = mono_class_get_first_field_idx (klass);
4946 mono_metadata_field_info (m_class_get_image (field->parent), first_field_idx + field_index, NULL, &rva, NULL);
4947 if (!rva)
4948 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), m_class_get_name (field->parent));
4949 def_values [field_index].data = mono_image_rva_map (m_class_get_image (field->parent), rva);
4952 return def_values [field_index].data;
4956 * mono_field_get_data:
4957 * \param field the \c MonoClassField to act on
4959 * \returns A pointer to the metadata constant value or to the field
4960 * data if it has an RVA flag.
4962 const char *
4963 mono_field_get_data (MonoClassField *field)
4965 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
4966 MonoTypeEnum def_type;
4968 return mono_class_get_field_default_value (field, &def_type);
4969 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
4970 return mono_field_get_rva (field);
4971 } else {
4972 return NULL;
4977 * mono_property_get_name:
4978 * \param prop the \c MonoProperty to act on
4979 * \returns The name of the property
4981 const char*
4982 mono_property_get_name (MonoProperty *prop)
4984 return prop->name;
4988 * mono_property_get_set_method
4989 * \param prop the \c MonoProperty to act on.
4990 * \returns The setter method of the property, a \c MonoMethod.
4992 MonoMethod*
4993 mono_property_get_set_method (MonoProperty *prop)
4995 return prop->set;
4999 * mono_property_get_get_method
5000 * \param prop the MonoProperty to act on.
5001 * \returns The getter method of the property (A \c MonoMethod)
5003 MonoMethod*
5004 mono_property_get_get_method (MonoProperty *prop)
5006 return prop->get;
5010 * mono_property_get_parent:
5011 * \param prop the \c MonoProperty to act on.
5012 * \returns The \c MonoClass where the property was defined.
5014 MonoClass*
5015 mono_property_get_parent (MonoProperty *prop)
5017 return prop->parent;
5021 * mono_property_get_flags:
5022 * \param prop the \c MonoProperty to act on.
5024 * The metadata flags for a property are encoded using the
5025 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5027 * \returns The flags for the property.
5029 guint32
5030 mono_property_get_flags (MonoProperty *prop)
5032 return prop->attrs;
5036 * mono_event_get_name:
5037 * \param event the MonoEvent to act on
5038 * \returns The name of the event.
5040 const char*
5041 mono_event_get_name (MonoEvent *event)
5043 return event->name;
5047 * mono_event_get_add_method:
5048 * \param event The \c MonoEvent to act on.
5049 * \returns The \c add method for the event, a \c MonoMethod.
5051 MonoMethod*
5052 mono_event_get_add_method (MonoEvent *event)
5054 return event->add;
5058 * mono_event_get_remove_method:
5059 * \param event The \c MonoEvent to act on.
5060 * \returns The \c remove method for the event, a \c MonoMethod.
5062 MonoMethod*
5063 mono_event_get_remove_method (MonoEvent *event)
5065 return event->remove;
5069 * mono_event_get_raise_method:
5070 * \param event The \c MonoEvent to act on.
5071 * \returns The \c raise method for the event, a \c MonoMethod.
5073 MonoMethod*
5074 mono_event_get_raise_method (MonoEvent *event)
5076 return event->raise;
5080 * mono_event_get_parent:
5081 * \param event the MonoEvent to act on.
5082 * \returns The \c MonoClass where the event is defined.
5084 MonoClass*
5085 mono_event_get_parent (MonoEvent *event)
5087 return event->parent;
5091 * mono_event_get_flags
5092 * \param event the \c MonoEvent to act on.
5094 * The metadata flags for an event are encoded using the
5095 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5097 * \returns The flags for the event.
5099 guint32
5100 mono_event_get_flags (MonoEvent *event)
5102 return event->attrs;
5106 * mono_class_get_method_from_name:
5107 * \param klass where to look for the method
5108 * \param name name of the method
5109 * \param param_count number of parameters. -1 for any number.
5111 * Obtains a \c MonoMethod with a given name and number of parameters.
5112 * It only works if there are no multiple signatures for any given method name.
5114 MonoMethod *
5115 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
5117 MonoMethod *result;
5118 MONO_ENTER_GC_UNSAFE;
5119 ERROR_DECL (error);
5120 result = mono_class_get_method_from_name_checked (klass, name, param_count, 0, error);
5121 mono_error_cleanup (error);
5122 MONO_EXIT_GC_UNSAFE;
5123 return result;
5126 MonoMethod*
5127 mono_find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
5129 MonoImage *klass_image = m_class_get_image (klass);
5130 MonoMethod *res = NULL;
5131 int i;
5133 /* Search directly in the metadata to avoid calling setup_methods () */
5134 int first_idx = mono_class_get_first_method_idx (klass);
5135 int mcount = mono_class_get_method_count (klass);
5136 for (i = 0; i < mcount; ++i) {
5137 ERROR_DECL (error);
5138 guint32 cols [MONO_METHOD_SIZE];
5139 MonoMethod *method;
5140 MonoMethodSignature *sig;
5142 /* first_idx points into the methodptr table */
5143 mono_metadata_decode_table_row (klass_image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
5145 if (!strcmp (mono_metadata_string_heap (klass_image, cols [MONO_METHOD_NAME]), name)) {
5146 method = mono_get_method_checked (klass_image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, error);
5147 if (!method) {
5148 mono_error_cleanup (error); /* FIXME don't swallow the error */
5149 continue;
5151 if (param_count == -1) {
5152 res = method;
5153 break;
5155 sig = mono_method_signature_checked (method, error);
5156 if (!sig) {
5157 mono_error_cleanup (error); /* FIXME don't swallow the error */
5158 continue;
5160 if (sig->param_count == param_count) {
5161 res = method;
5162 break;
5167 return res;
5171 * mono_class_get_method_from_name_flags:
5172 * \param klass where to look for the method
5173 * \param name_space name of the method
5174 * \param param_count number of parameters. -1 for any number.
5175 * \param flags flags which must be set in the method
5177 * Obtains a \c MonoMethod with a given name and number of parameters.
5178 * It only works if there are no multiple signatures for any given method name.
5180 MonoMethod *
5181 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
5183 MonoMethod *method;
5184 MONO_ENTER_GC_UNSAFE;
5185 ERROR_DECL (error);
5186 method = mono_class_get_method_from_name_checked (klass, name, param_count, flags, error);
5187 mono_error_cleanup (error);
5188 MONO_EXIT_GC_UNSAFE;
5189 return method;
5193 * mono_class_get_method_from_name_checked:
5194 * \param klass where to look for the method
5195 * \param name_space name of the method
5196 * \param param_count number of parameters. -1 for any number.
5197 * \param flags flags which must be set in the method
5198 * \param error
5200 * Obtains a \c MonoMethod with a given name and number of parameters.
5201 * It only works if there are no multiple signatures for any given method name.
5203 MonoMethod *
5204 mono_class_get_method_from_name_checked (MonoClass *klass, const char *name,
5205 int param_count, int flags, MonoError *error)
5207 MonoMethod *res = NULL;
5208 int i;
5210 mono_class_init_internal (klass);
5212 if (mono_class_is_ginst (klass) && !m_class_get_methods (klass)) {
5213 res = mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass)->container_class, name, param_count, flags, error);
5215 if (res)
5216 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), error);
5218 return res;
5221 if (m_class_get_methods (klass) || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
5222 mono_class_setup_methods (klass);
5224 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5225 See mono/tests/array_load_exception.il
5226 FIXME we should better report this error to the caller
5228 MonoMethod **klass_methods = m_class_get_methods (klass);
5229 if (!klass_methods)
5230 return NULL;
5231 int mcount = mono_class_get_method_count (klass);
5232 for (i = 0; i < mcount; ++i) {
5233 MonoMethod *method = klass_methods [i];
5235 if (method->name[0] == name [0] &&
5236 !strcmp (name, method->name) &&
5237 (param_count == -1 || mono_method_signature_internal (method)->param_count == param_count) &&
5238 ((method->flags & flags) == flags)) {
5239 res = method;
5240 break;
5244 else {
5245 res = mono_find_method_in_metadata (klass, name, param_count, flags);
5248 return res;
5251 gboolean
5252 mono_class_has_failure (const MonoClass *klass)
5254 g_assert (klass != NULL);
5255 return m_class_has_failure ((MonoClass*)klass) != 0;
5260 * mono_class_set_type_load_failure:
5261 * \param klass class in which the failure was detected
5262 * \param fmt \c printf -style error message string.
5264 * Collect detected failure informaion in the class for later processing.
5265 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5266 * Note that only the first failure is kept.
5268 * LOCKING: Acquires the loader lock.
5270 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5272 gboolean
5273 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
5275 ERROR_DECL (prepare_error);
5276 va_list args;
5278 if (mono_class_has_failure (klass))
5279 return FALSE;
5281 va_start (args, fmt);
5282 mono_error_vset_type_load_class (prepare_error, klass, fmt, args);
5283 va_end (args);
5285 MonoErrorBoxed *box = mono_error_box (prepare_error, m_class_get_image (klass));
5286 mono_error_cleanup (prepare_error);
5287 return mono_class_set_failure (klass, box);
5291 * mono_class_get_exception_for_failure:
5292 * \param klass class in which the failure was detected
5294 * \returns a constructed MonoException than the caller can then throw
5295 * using mono_raise_exception - or NULL if no failure is present (or
5296 * doesn't result in an exception).
5298 MonoException*
5299 mono_class_get_exception_for_failure (MonoClass *klass)
5301 if (!mono_class_has_failure (klass))
5302 return NULL;
5303 ERROR_DECL (unboxed_error);
5304 mono_error_set_for_class_failure (unboxed_error, klass);
5305 return mono_error_convert_to_exception (unboxed_error);
5308 static gboolean
5309 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
5311 outer_klass = mono_class_get_generic_type_definition (outer_klass);
5312 inner_klass = mono_class_get_generic_type_definition (inner_klass);
5313 do {
5314 if (outer_klass == inner_klass)
5315 return TRUE;
5316 inner_klass = m_class_get_nested_in (inner_klass);
5317 } while (inner_klass);
5318 return FALSE;
5321 MonoClass *
5322 mono_class_get_generic_type_definition (MonoClass *klass)
5324 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5325 return gklass ? gklass->container_class : klass;
5329 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5331 * Generic instantiations are ignored for all super types of @klass.
5333 * Visibility checks ignoring generic instantiations.
5335 gboolean
5336 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
5338 int i;
5339 klass = mono_class_get_generic_type_definition (klass);
5340 parent = mono_class_get_generic_type_definition (parent);
5341 mono_class_setup_supertypes (klass);
5343 for (i = 0; i < m_class_get_idepth (klass); ++i) {
5344 if (parent == mono_class_get_generic_type_definition (m_class_get_supertypes (klass) [i]))
5345 return TRUE;
5347 return FALSE;
5350 * Subtype can only access parent members with family protection if the site object
5351 * is subclass of Subtype. For example:
5352 * class A { protected int x; }
5353 * class B : A {
5354 * void valid_access () {
5355 * B b;
5356 * b.x = 0;
5358 * void invalid_access () {
5359 * A a;
5360 * a.x = 0;
5363 * */
5364 static gboolean
5365 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
5367 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass)) {
5368 /* Can happen with default interface methods */
5369 if (!mono_class_implements_interface (access_klass, member_klass))
5370 return FALSE;
5371 } else {
5372 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
5373 return FALSE;
5376 if (context_klass == NULL)
5377 return TRUE;
5378 /*if access_klass is not member_klass context_klass must be type compat*/
5379 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
5380 return FALSE;
5381 return TRUE;
5384 static gboolean
5385 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
5387 GSList *tmp;
5388 if (accessing == accessed)
5389 return TRUE;
5390 if (!accessed || !accessing)
5391 return FALSE;
5393 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5394 * anywhere so untrusted friends are not safe to access platform's code internals */
5395 if (mono_security_core_clr_enabled ()) {
5396 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
5397 return FALSE;
5400 mono_assembly_load_friends (accessed);
5401 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
5402 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
5403 /* Be conservative with checks */
5404 if (!friend_->name)
5405 continue;
5406 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
5407 continue;
5408 if (friend_->public_key_token [0]) {
5409 if (!accessing->aname.public_key_token [0])
5410 continue;
5411 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
5412 continue;
5414 return TRUE;
5416 return FALSE;
5420 * If klass is a generic type or if it is derived from a generic type, return the
5421 * MonoClass of the generic definition
5422 * Returns NULL if not found
5424 static MonoClass*
5425 get_generic_definition_class (MonoClass *klass)
5427 while (klass) {
5428 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5429 if (gklass && gklass->container_class)
5430 return gklass->container_class;
5431 klass = m_class_get_parent (klass);
5433 return NULL;
5436 static gboolean
5437 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
5439 int i;
5440 for (i = 0; i < ginst->type_argc; ++i) {
5441 MonoType *type = ginst->type_argv[i];
5442 switch (type->type) {
5443 case MONO_TYPE_SZARRAY:
5444 if (!can_access_type (access_klass, type->data.klass))
5445 return FALSE;
5446 break;
5447 case MONO_TYPE_ARRAY:
5448 if (!can_access_type (access_klass, type->data.array->eklass))
5449 return FALSE;
5450 break;
5451 case MONO_TYPE_PTR:
5452 if (!can_access_type (access_klass, mono_class_from_mono_type_internal (type->data.type)))
5453 return FALSE;
5454 break;
5455 case MONO_TYPE_CLASS:
5456 case MONO_TYPE_VALUETYPE:
5457 case MONO_TYPE_GENERICINST:
5458 if (!can_access_type (access_klass, mono_class_from_mono_type_internal (type)))
5459 return FALSE;
5460 default:
5461 break;
5464 return TRUE;
5467 static gboolean
5468 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
5470 int access_level;
5472 if (access_klass == member_klass)
5473 return TRUE;
5475 MonoAssembly *access_klass_assembly = m_class_get_image (access_klass)->assembly;
5476 MonoAssembly *member_klass_assembly = m_class_get_image (member_klass)->assembly;
5478 if (access_klass_assembly && m_class_get_image (access_klass)->assembly->corlib_internal)
5479 return TRUE;
5481 if (m_class_get_element_class (access_klass) && !m_class_is_enumtype (access_klass)) {
5482 access_klass = m_class_get_element_class (access_klass);
5483 access_klass_assembly = m_class_get_image (access_klass)->assembly;
5486 if (m_class_get_element_class (member_klass) && !m_class_is_enumtype (member_klass)) {
5487 member_klass = m_class_get_element_class (member_klass);
5488 member_klass_assembly = m_class_get_image (member_klass)->assembly;
5491 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5493 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass)))
5494 return TRUE;
5496 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
5497 return FALSE;
5499 if (is_nesting_type (access_klass, member_klass) || (m_class_get_nested_in (access_klass) && is_nesting_type (m_class_get_nested_in (access_klass), member_klass)))
5500 return TRUE;
5502 /*Non nested type with nested visibility. We just fail it.*/
5503 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && m_class_get_nested_in (member_klass) == NULL)
5504 return FALSE;
5506 MonoClass *member_klass_nested_in = m_class_get_nested_in (member_klass);
5507 switch (access_level) {
5508 case TYPE_ATTRIBUTE_NOT_PUBLIC:
5509 return can_access_internals (access_klass_assembly, member_klass_assembly);
5511 case TYPE_ATTRIBUTE_PUBLIC:
5512 return TRUE;
5514 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
5515 return member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
5517 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
5518 return is_nesting_type (member_klass, access_klass) && member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
5520 case TYPE_ATTRIBUTE_NESTED_FAMILY:
5521 return mono_class_has_parent_and_ignore_generics (access_klass, m_class_get_nested_in (member_klass));
5523 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
5524 return can_access_internals (access_klass_assembly, member_klass_assembly) && member_klass_nested_in && can_access_type (access_klass, member_klass_nested_in);
5526 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
5527 return can_access_internals (access_klass_assembly, m_class_get_image (member_klass_nested_in)->assembly) &&
5528 mono_class_has_parent_and_ignore_generics (access_klass, member_klass_nested_in);
5530 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
5531 return can_access_internals (access_klass_assembly, m_class_get_image (member_klass_nested_in)->assembly) ||
5532 mono_class_has_parent_and_ignore_generics (access_klass, member_klass_nested_in);
5534 return FALSE;
5537 /* FIXME: check visibility of type, too */
5538 static gboolean
5539 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
5541 MonoClass *member_generic_def;
5542 MonoAssembly *access_klass_assembly = m_class_get_image (access_klass)->assembly;
5543 if (access_klass_assembly && access_klass_assembly->corlib_internal)
5544 return TRUE;
5546 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
5547 if (((access_gklass && access_gklass->container_class) ||
5548 mono_class_is_gtd (access_klass)) &&
5549 (member_generic_def = get_generic_definition_class (member_klass))) {
5550 MonoClass *access_container;
5552 if (mono_class_is_gtd (access_klass))
5553 access_container = access_klass;
5554 else
5555 access_container = access_gklass->container_class;
5557 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
5558 return TRUE;
5561 MonoImage *member_klass_image = m_class_get_image (member_klass);
5562 /* Partition I 8.5.3.2 */
5563 /* the access level values are the same for fields and methods */
5564 switch (access_level) {
5565 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
5566 /* same compilation unit */
5567 return m_class_get_image (access_klass) == member_klass_image;
5568 case FIELD_ATTRIBUTE_PRIVATE:
5569 return access_klass == member_klass;
5570 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
5571 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
5572 can_access_internals (access_klass_assembly, member_klass_image->assembly))
5573 return TRUE;
5574 return FALSE;
5575 case FIELD_ATTRIBUTE_ASSEMBLY:
5576 return can_access_internals (access_klass_assembly, member_klass_image->assembly);
5577 case FIELD_ATTRIBUTE_FAMILY:
5578 if (is_valid_family_access (access_klass, member_klass, context_klass))
5579 return TRUE;
5580 return FALSE;
5581 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
5582 if (is_valid_family_access (access_klass, member_klass, context_klass))
5583 return TRUE;
5584 return can_access_internals (access_klass_assembly, member_klass_image->assembly);
5585 case FIELD_ATTRIBUTE_PUBLIC:
5586 return TRUE;
5588 return FALSE;
5592 * mono_method_can_access_field:
5593 * \param method Method that will attempt to access the field
5594 * \param field the field to access
5596 * Used to determine if a method is allowed to access the specified field.
5598 * \returns TRUE if the given \p method is allowed to access the \p field while following
5599 * the accessibility rules of the CLI.
5601 gboolean
5602 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
5604 /* FIXME: check all overlapping fields */
5605 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type_internal (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5606 if (!can) {
5607 MonoClass *nested = m_class_get_nested_in (method->klass);
5608 while (nested) {
5609 can = can_access_member (nested, field->parent, NULL, mono_field_get_type_internal (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5610 if (can)
5611 return TRUE;
5612 nested = m_class_get_nested_in (nested);
5615 return can;
5618 static MonoMethod*
5619 mono_method_get_method_definition (MonoMethod *method)
5621 while (method->is_inflated)
5622 method = ((MonoMethodInflated*)method)->declaring;
5623 return method;
5627 * mono_method_can_access_method:
5628 * \param method Method that will attempt to access the other method
5629 * \param called the method that we want to probe for accessibility.
5631 * Used to determine if the \p method is allowed to access the specified \p called method.
5633 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5634 * the accessibility rules of the CLI.
5636 gboolean
5637 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
5639 method = mono_method_get_method_definition (method);
5640 called = mono_method_get_method_definition (called);
5641 return mono_method_can_access_method_full (method, called, NULL);
5645 * mono_method_can_access_method_full:
5646 * @method: The caller method
5647 * @called: The called method
5648 * @context_klass: The static type on stack of the owner @called object used
5650 * This function must be used with instance calls, as they have more strict family accessibility.
5651 * It can be used with static methods, but context_klass should be NULL.
5653 * Returns: TRUE if caller have proper visibility and acessibility to @called
5655 gboolean
5656 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
5658 /* Wrappers are except from access checks */
5659 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
5660 return TRUE;
5662 MonoClass *access_class = method->klass;
5663 MonoClass *member_class = called->klass;
5664 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
5665 if (!can) {
5666 MonoClass *nested = m_class_get_nested_in (access_class);
5667 while (nested) {
5668 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
5669 if (can)
5670 break;
5671 nested = m_class_get_nested_in (nested);
5675 if (!can)
5676 return FALSE;
5678 can = can_access_type (access_class, member_class);
5679 if (!can) {
5680 MonoClass *nested = m_class_get_nested_in (access_class);
5681 while (nested) {
5682 can = can_access_type (nested, member_class);
5683 if (can)
5684 break;
5685 nested = m_class_get_nested_in (nested);
5689 if (!can)
5690 return FALSE;
5692 if (called->is_inflated) {
5693 MonoMethodInflated * infl = (MonoMethodInflated*)called;
5694 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
5695 return FALSE;
5698 return TRUE;
5703 * mono_method_can_access_field_full:
5704 * @method: The caller method
5705 * @field: The accessed field
5706 * @context_klass: The static type on stack of the owner @field object used
5708 * This function must be used with instance fields, as they have more strict family accessibility.
5709 * It can be used with static fields, but context_klass should be NULL.
5711 * Returns: TRUE if caller have proper visibility and acessibility to @field
5713 gboolean
5714 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
5716 MonoClass *access_class = method->klass;
5717 MonoClass *member_class = field->parent;
5718 /* FIXME: check all overlapping fields */
5719 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5720 if (!can) {
5721 MonoClass *nested = m_class_get_nested_in (access_class);
5722 while (nested) {
5723 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5724 if (can)
5725 break;
5726 nested = m_class_get_nested_in (nested);
5730 if (!can)
5731 return FALSE;
5733 can = can_access_type (access_class, member_class);
5734 if (!can) {
5735 MonoClass *nested = m_class_get_nested_in (access_class);
5736 while (nested) {
5737 can = can_access_type (nested, member_class);
5738 if (can)
5739 break;
5740 nested = m_class_get_nested_in (nested);
5744 if (!can)
5745 return FALSE;
5746 return TRUE;
5750 * mono_class_can_access_class:
5751 * @source_class: The source class
5752 * @target_class: The accessed class
5754 * This function returns is @target_class is visible to @source_class
5756 * Returns: TRUE if source have proper visibility and acessibility to target
5758 gboolean
5759 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
5761 return can_access_type (source_class, target_class);
5765 * mono_type_is_valid_enum_basetype:
5766 * \param type The MonoType to check
5767 * \returns TRUE if the type can be used as the basetype of an enum
5769 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
5770 switch (type->type) {
5771 case MONO_TYPE_I1:
5772 case MONO_TYPE_U1:
5773 case MONO_TYPE_BOOLEAN:
5774 case MONO_TYPE_I2:
5775 case MONO_TYPE_U2:
5776 case MONO_TYPE_CHAR:
5777 case MONO_TYPE_I4:
5778 case MONO_TYPE_U4:
5779 case MONO_TYPE_I8:
5780 case MONO_TYPE_U8:
5781 case MONO_TYPE_I:
5782 case MONO_TYPE_U:
5783 return TRUE;
5784 default:
5785 return FALSE;
5790 * mono_class_is_valid_enum:
5791 * \param klass An enum class to be validated
5793 * This method verify the required properties an enum should have.
5795 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
5796 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
5797 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
5799 * \returns TRUE if the informed enum class is valid
5801 gboolean
5802 mono_class_is_valid_enum (MonoClass *klass)
5804 MonoClassField * field;
5805 gpointer iter = NULL;
5806 gboolean found_base_field = FALSE;
5808 g_assert (m_class_is_enumtype (klass));
5809 MonoClass *klass_parent = m_class_get_parent (klass);
5810 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
5811 if (!klass_parent || strcmp (m_class_get_name (klass_parent), "Enum") || strcmp (m_class_get_name_space (klass_parent), "System") ) {
5812 return FALSE;
5815 if (!mono_class_is_auto_layout (klass))
5816 return FALSE;
5818 while ((field = mono_class_get_fields_internal (klass, &iter))) {
5819 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
5820 if (found_base_field)
5821 return FALSE;
5822 found_base_field = TRUE;
5823 if (!mono_type_is_valid_enum_basetype (field->type))
5824 return FALSE;
5828 if (!found_base_field)
5829 return FALSE;
5831 if (mono_class_get_method_count (klass) > 0)
5832 return FALSE;
5834 return TRUE;
5837 gboolean
5838 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
5840 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
5843 void
5844 mono_field_resolve_type (MonoClassField *field, MonoError *error)
5846 MonoClass *klass = field->parent;
5847 MonoImage *image = m_class_get_image (klass);
5848 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
5849 MonoType *ftype;
5850 int field_idx = field - m_class_get_fields (klass);
5852 error_init (error);
5854 if (gtd) {
5855 MonoClassField *gfield = &m_class_get_fields (gtd) [field_idx];
5856 MonoType *gtype = mono_field_get_type_checked (gfield, error);
5857 if (!mono_error_ok (error)) {
5858 char *full_name = mono_type_get_full_name (gtd);
5859 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
5860 g_free (full_name);
5863 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
5864 if (!mono_error_ok (error)) {
5865 char *full_name = mono_type_get_full_name (klass);
5866 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
5867 g_free (full_name);
5869 } else {
5870 const char *sig;
5871 guint32 cols [MONO_FIELD_SIZE];
5872 MonoGenericContainer *container = NULL;
5873 int idx = mono_class_get_first_field_idx (klass) + field_idx;
5875 /*FIXME, in theory we do not lazy load SRE fields*/
5876 g_assert (!image_is_dynamic (image));
5878 if (mono_class_is_gtd (klass)) {
5879 container = mono_class_get_generic_container (klass);
5880 } else if (gtd) {
5881 container = mono_class_get_generic_container (gtd);
5882 g_assert (container);
5885 /* first_field_idx and idx points into the fieldptr table */
5886 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
5888 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], error)) {
5889 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5890 return;
5893 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
5895 mono_metadata_decode_value (sig, &sig);
5896 /* FIELD signature == 0x06 */
5897 g_assert (*sig == 0x06);
5899 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
5900 if (!ftype) {
5901 char *full_name = mono_type_get_full_name (klass);
5902 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
5903 g_free (full_name);
5906 mono_memory_barrier ();
5907 field->type = ftype;
5910 static guint32
5911 mono_field_resolve_flags (MonoClassField *field)
5913 MonoClass *klass = field->parent;
5914 MonoImage *image = m_class_get_image (klass);
5915 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
5916 int field_idx = field - m_class_get_fields (klass);
5918 if (gtd) {
5919 MonoClassField *gfield = &m_class_get_fields (gtd) [field_idx];
5920 return mono_field_get_flags (gfield);
5921 } else {
5922 int idx = mono_class_get_first_field_idx (klass) + field_idx;
5924 /*FIXME, in theory we do not lazy load SRE fields*/
5925 g_assert (!image_is_dynamic (image));
5927 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
5932 * mono_class_get_fields_lazy:
5933 * \param klass the MonoClass to act on
5935 * This routine is an iterator routine for retrieving the fields in a class.
5936 * Only minimal information about fields are loaded. Accessors must be used
5937 * for all MonoClassField returned.
5939 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5940 * iterate over all of the elements. When no more values are
5941 * available, the return value is NULL.
5943 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
5945 MonoClassField*
5946 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
5948 MonoClassField* field;
5949 if (!iter)
5950 return NULL;
5951 if (!*iter) {
5952 mono_class_setup_basic_field_info (klass);
5953 MonoClassField *klass_fields = m_class_get_fields (klass);
5954 if (!klass_fields)
5955 return NULL;
5956 /* start from the first */
5957 if (mono_class_get_field_count (klass)) {
5958 *iter = &klass_fields [0];
5959 return (MonoClassField *)*iter;
5960 } else {
5961 /* no fields */
5962 return NULL;
5965 field = (MonoClassField *)*iter;
5966 field++;
5967 if (field < &m_class_get_fields (klass) [mono_class_get_field_count (klass)]) {
5968 *iter = field;
5969 return (MonoClassField *)*iter;
5971 return NULL;
5974 char*
5975 mono_class_full_name (MonoClass *klass)
5977 return mono_type_full_name (m_class_get_byval_arg (klass));
5980 /* Declare all shared lazy type lookup functions */
5981 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
5984 * mono_method_get_base_method:
5985 * \param method a method
5986 * \param definition if true, get the definition
5987 * \param error set on failure
5989 * Given a virtual method associated with a subclass, return the corresponding
5990 * method from an ancestor. If \p definition is FALSE, returns the method in the
5991 * superclass of the given method. If \p definition is TRUE, return the method
5992 * in the ancestor class where it was first declared. The type arguments will
5993 * be inflated in the ancestor classes. If the method is not associated with a
5994 * class, or isn't virtual, returns the method itself. On failure returns NULL
5995 * and sets \p error.
5997 MonoMethod*
5998 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
6000 MonoClass *klass, *parent;
6001 MonoGenericContext *generic_inst = NULL;
6002 MonoMethod *result = NULL;
6003 int slot;
6005 if (method->klass == NULL)
6006 return method;
6008 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6009 MONO_CLASS_IS_INTERFACE_INTERNAL (method->klass) ||
6010 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6011 return method;
6013 slot = mono_method_get_vtable_slot (method);
6014 if (slot == -1)
6015 return method;
6017 klass = method->klass;
6018 if (mono_class_is_ginst (klass)) {
6019 generic_inst = mono_class_get_context (klass);
6020 klass = mono_class_get_generic_class (klass)->container_class;
6023 retry:
6024 if (definition) {
6025 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6026 for (parent = m_class_get_parent (klass); parent != NULL; parent = m_class_get_parent (parent)) {
6027 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6028 or klass is the generic container class and generic_inst is the instantiation.
6030 when we go to the parent, if the parent is an open constructed type, we need to
6031 replace the type parameters by the definitions from the generic_inst, and then take it
6032 apart again into the klass and the generic_inst.
6034 For cases like this:
6035 class C<T> : B<T, int> {
6036 public override void Foo () { ... }
6038 class B<U,V> : A<HashMap<U,V>> {
6039 public override void Foo () { ... }
6041 class A<X> {
6042 public virtual void Foo () { ... }
6045 if at each iteration the parent isn't open, we can skip inflating it. if at some
6046 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6047 NULL;
6049 MonoGenericContext *parent_inst = NULL;
6050 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent))) {
6051 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
6052 return_val_if_nok (error, NULL);
6054 if (mono_class_is_ginst (parent)) {
6055 parent_inst = mono_class_get_context (parent);
6056 parent = mono_class_get_generic_class (parent)->container_class;
6059 mono_class_setup_vtable (parent);
6060 if (m_class_get_vtable_size (parent) <= slot)
6061 break;
6062 klass = parent;
6063 generic_inst = parent_inst;
6065 } else {
6066 klass = m_class_get_parent (klass);
6067 if (!klass)
6068 return method;
6069 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass))) {
6070 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
6071 return_val_if_nok (error, NULL);
6073 generic_inst = NULL;
6075 if (mono_class_is_ginst (klass)) {
6076 generic_inst = mono_class_get_context (klass);
6077 klass = mono_class_get_generic_class (klass)->container_class;
6082 if (generic_inst) {
6083 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
6084 return_val_if_nok (error, NULL);
6087 if (klass == method->klass)
6088 return method;
6090 /*This is possible if definition == FALSE.
6091 * Do it here to be really sure we don't read invalid memory.
6093 if (slot >= m_class_get_vtable_size (klass))
6094 return method;
6096 mono_class_setup_vtable (klass);
6098 result = m_class_get_vtable (klass) [slot];
6099 if (result == NULL) {
6100 /* It is an abstract method */
6101 gboolean found = FALSE;
6102 gpointer iter = NULL;
6103 while ((result = mono_class_get_methods (klass, &iter))) {
6104 if (result->slot == slot) {
6105 found = TRUE;
6106 break;
6109 /* found might be FALSE if we looked in an abstract class
6110 * that doesn't override an abstract method of its
6111 * parent:
6112 * abstract class Base {
6113 * public abstract void Foo ();
6115 * abstract class Derived : Base { }
6116 * class Child : Derived {
6117 * public override void Foo () { }
6120 * if m was Child.Foo and we ask for the base method,
6121 * then we get here with klass == Derived and found == FALSE
6123 /* but it shouldn't be the case that if we're looking
6124 * for the definition and didn't find a result; the
6125 * loop above should've taken us as far as we could
6126 * go! */
6127 g_assert (!(definition && !found));
6128 if (!found)
6129 goto retry;
6132 g_assert (result != NULL);
6133 return result;