3 * Class management for the Mono runtime
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.
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>
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
);
69 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, gboolean case_sensitive
, MonoError
*error
);
71 GENERATE_GET_CLASS_WITH_CACHE (valuetype
, "System", "ValueType")
72 GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref
, "System.Runtime.InteropServices", "HandleRef")
74 #define CTOR_REQUIRED_FLAGS (METHOD_ATTRIBUTE_SPECIAL_NAME | METHOD_ATTRIBUTE_RT_SPECIAL_NAME)
75 #define CTOR_INVALID_FLAGS (METHOD_ATTRIBUTE_STATIC)
77 // define to print types whenever custom modifiers are appended during inflation
78 #undef DEBUG_INFLATE_CMODS
82 mono_method_get_image (MonoMethod
*method
)
84 return m_class_get_image (method
->klass
);
88 * mono_class_from_typeref:
89 * \param image a MonoImage
90 * \param type_token a TypeRef token
92 * Creates the \c MonoClass* structure representing the type defined by
93 * the typeref token valid inside \p image.
94 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
98 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
101 MonoClass
*klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
102 g_assert (is_ok (error
)); /*FIXME proper error handling*/
107 * mono_class_from_typeref_checked:
108 * \param image a MonoImage
109 * \param type_token a TypeRef token
110 * \param error error return code, if any.
112 * Creates the \c MonoClass* structure representing the type defined by
113 * the typeref token valid inside \p image.
115 * \returns The \c MonoClass* representing the typeref token, NULL if it could
116 * not be loaded with the \p error value filled with the information about the
120 mono_class_from_typeref_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
122 guint32 cols
[MONO_TYPEREF_SIZE
];
123 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
125 const char *name
, *nspace
;
126 MonoClass
*res
= NULL
;
131 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, error
))
134 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
136 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
137 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
139 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
140 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
141 case MONO_RESOLUTION_SCOPE_MODULE
:
143 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
144 This is not the observed behavior of existing implementations.
145 The defacto behavior is that it's just a typedef in disguise.
147 /* a typedef in disguise */
148 res
= mono_class_from_name_checked (image
, nspace
, name
, error
);
151 case MONO_RESOLUTION_SCOPE_MODULEREF
:
152 module
= mono_image_load_module_checked (image
, idx
, error
);
154 res
= mono_class_from_name_checked (module
, nspace
, name
, error
);
157 case MONO_RESOLUTION_SCOPE_TYPEREF
: {
158 MonoClass
*enclosing
;
161 if (idx
== mono_metadata_token_index (type_token
)) {
162 mono_error_set_bad_image (error
, image
, "Image with self-referencing typeref token %08x.", type_token
);
166 enclosing
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| idx
, error
);
167 return_val_if_nok (error
, NULL
);
169 GList
*nested_classes
= mono_class_get_nested_classes_property (enclosing
);
170 if (m_class_is_nested_classes_inited (enclosing
) && nested_classes
) {
171 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
172 for (tmp
= nested_classes
; tmp
; tmp
= tmp
->next
) {
173 res
= (MonoClass
*)tmp
->data
;
174 if (strcmp (m_class_get_name (res
), name
) == 0)
178 MonoImage
*enclosing_image
= m_class_get_image (enclosing
);
179 guint32 enclosing_type_token
= m_class_get_type_token (enclosing
);
180 /* Don't call mono_class_init_internal as we might've been called by it recursively */
181 int i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, 1);
183 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
184 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
185 const char *nname
= mono_metadata_string_heap (enclosing_image
, string_offset
);
187 if (strcmp (nname
, name
) == 0)
188 return mono_class_create_from_typedef (enclosing_image
, MONO_TOKEN_TYPE_DEF
| class_nested
, error
);
190 i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, i
+ 1);
193 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
196 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
200 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
201 mono_error_set_bad_image (error
, image
, "Image with invalid assemblyref token %08x.", idx
);
205 if (!image
->references
|| !image
->references
[idx
- 1])
206 mono_assembly_load_reference (image
, idx
- 1);
207 g_assert (image
->references
[idx
- 1]);
209 /* If the assembly did not load, register this as a type load exception */
210 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
211 MonoAssemblyName aname
;
214 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
215 human_name
= mono_stringify_assembly_name (&aname
);
216 gboolean refonly
= FALSE
;
218 refonly
= mono_asmctx_get_kind (&image
->assembly
->context
) == MONO_ASMCTX_REFONLY
;
219 mono_error_set_simple_file_not_found (error
, human_name
, refonly
);
224 res
= mono_class_from_name_checked (image
->references
[idx
- 1]->image
, nspace
, name
, error
);
227 /* Generic case, should be avoided for when a better error is possible. */
228 if (!res
&& is_ok (error
)) {
229 char *name
= mono_class_name_from_token (image
, type_token
);
230 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
231 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
);
238 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
240 void *res
= mono_image_alloc (image
, size
);
241 memcpy (res
, data
, size
);
245 /* Copy everything mono_metadata_free_array free. */
247 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
250 a
= (MonoArrayType
*)mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
252 a
->sizes
= (int *)mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
254 a
->lobounds
= (int *)mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
256 a
= (MonoArrayType
*)g_memdup (a
, sizeof (MonoArrayType
));
258 a
->sizes
= (int *)g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
260 a
->lobounds
= (int *)g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
265 /* Copy everything mono_metadata_free_method_signature free. */
267 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
271 sig
= mono_metadata_signature_dup_full (image
, sig
);
273 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
274 for (i
= 0; i
< sig
->param_count
; ++i
)
275 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
281 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
283 MonoAssembly
*ta
= m_class_get_image (klass
)->assembly
;
286 name
= mono_stringify_assembly_name (&ta
->aname
);
287 g_string_append_printf (str
, ", %s", name
);
292 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
295 g_string_append_c (str
, '&');
299 escape_special_chars (const char* identifier
)
301 size_t id_len
= strlen (identifier
);
302 // Assume the worst case, and thus only allocate once
303 char *res
= g_malloc (id_len
* 2 + 1);
305 for (const char *s
= identifier
; *s
!= 0; s
++) {
324 * mono_identifier_escape_type_name_chars:
325 * \param identifier the display name of a mono type
327 * \returns The name in external form, that is with escaping backslashes.
329 * The displayed form of an identifier has the characters ,+&*[]\
330 * that have special meaning in type names escaped with a preceeding
331 * backslash (\) character.
334 mono_identifier_escape_type_name_chars (const char* identifier
)
339 // If the string has any special characters escape the whole thing, otherwise just return the input
340 for (const char *s
= identifier
; *s
!= 0; s
++) {
349 return escape_special_chars (identifier
);
353 return g_strdup (identifier
);
357 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
358 MonoTypeNameFormat format
)
362 switch (type
->type
) {
363 case MONO_TYPE_ARRAY
: {
364 int i
, rank
= type
->data
.array
->rank
;
365 MonoTypeNameFormat nested_format
;
367 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
368 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
370 mono_type_get_name_recurse (
371 m_class_get_byval_arg (type
->data
.array
->eklass
), str
, FALSE
, nested_format
);
372 g_string_append_c (str
, '[');
374 g_string_append_c (str
, '*');
375 for (i
= 1; i
< rank
; i
++)
376 g_string_append_c (str
, ',');
377 g_string_append_c (str
, ']');
379 mono_type_name_check_byref (type
, str
);
381 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
382 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
385 case MONO_TYPE_SZARRAY
: {
386 MonoTypeNameFormat nested_format
;
388 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
389 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
391 mono_type_get_name_recurse (
392 m_class_get_byval_arg (type
->data
.klass
), str
, FALSE
, nested_format
);
393 g_string_append (str
, "[]");
395 mono_type_name_check_byref (type
, str
);
397 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
398 _mono_type_get_assembly_name (type
->data
.klass
, str
);
401 case MONO_TYPE_PTR
: {
402 MonoTypeNameFormat nested_format
;
404 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
405 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
407 mono_type_get_name_recurse (
408 type
->data
.type
, str
, FALSE
, nested_format
);
409 g_string_append_c (str
, '*');
411 mono_type_name_check_byref (type
, str
);
413 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
414 _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type
->data
.type
), str
);
419 if (!mono_generic_param_name (type
->data
.generic_param
))
420 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
422 g_string_append (str
, mono_generic_param_name (type
->data
.generic_param
));
424 mono_type_name_check_byref (type
, str
);
428 klass
= mono_class_from_mono_type_internal (type
);
429 if (m_class_get_nested_in (klass
)) {
430 mono_type_get_name_recurse (
431 m_class_get_byval_arg (m_class_get_nested_in (klass
)), str
, TRUE
, format
);
432 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
433 g_string_append_c (str
, '.');
435 g_string_append_c (str
, '+');
436 } else if (*m_class_get_name_space (klass
)) {
437 const char *klass_name_space
= m_class_get_name_space (klass
);
438 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
439 g_string_append (str
, klass_name_space
);
441 char *escaped
= mono_identifier_escape_type_name_chars (klass_name_space
);
442 g_string_append (str
, escaped
);
445 g_string_append_c (str
, '.');
447 const char *klass_name
= m_class_get_name (klass
);
448 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
449 const char *s
= strchr (klass_name
, '`');
450 gssize len
= s
? (s
- klass_name
) : (gssize
)strlen (klass_name
);
451 g_string_append_len (str
, klass_name
, len
);
453 char *escaped
= mono_identifier_escape_type_name_chars (klass_name
);
454 g_string_append (str
, escaped
);
459 if (mono_class_is_ginst (klass
)) {
460 MonoGenericClass
*gclass
= mono_class_get_generic_class (klass
);
461 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
462 MonoTypeNameFormat nested_format
;
465 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
466 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
468 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
469 g_string_append_c (str
, '<');
471 g_string_append_c (str
, '[');
472 for (i
= 0; i
< inst
->type_argc
; i
++) {
473 MonoType
*t
= inst
->type_argv
[i
];
476 g_string_append_c (str
, ',');
477 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
478 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
479 g_string_append_c (str
, '[');
480 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
481 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
482 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
483 g_string_append_c (str
, ']');
485 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
486 g_string_append_c (str
, '>');
488 g_string_append_c (str
, ']');
489 } else if (mono_class_is_gtd (klass
) &&
490 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
491 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
494 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
495 g_string_append_c (str
, '<');
497 g_string_append_c (str
, '[');
498 for (i
= 0; i
< mono_class_get_generic_container (klass
)->type_argc
; i
++) {
500 g_string_append_c (str
, ',');
501 g_string_append (str
, mono_generic_container_get_param_info (mono_class_get_generic_container (klass
), i
)->name
);
503 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
504 g_string_append_c (str
, '>');
506 g_string_append_c (str
, ']');
509 mono_type_name_check_byref (type
, str
);
511 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
512 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
513 _mono_type_get_assembly_name (klass
, str
);
519 * mono_type_get_name_full:
521 * \param format the format for the return string.
524 * \returns The string representation in a number of formats:
526 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
527 * returned in the format required by \c System.Reflection, this is the
528 * inverse of mono_reflection_parse_type().
530 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
531 * be used by the IL assembler.
533 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
535 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
538 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
542 result
= g_string_new ("");
544 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
546 return g_string_free (result
, FALSE
);
550 * mono_type_get_full_name:
551 * \param class a class
553 * \returns The string representation for type as required by System.Reflection.
554 * The inverse of mono_reflection_parse_type().
557 mono_type_get_full_name (MonoClass
*klass
)
559 return mono_type_get_name_full (m_class_get_byval_arg (klass
), MONO_TYPE_NAME_FORMAT_REFLECTION
);
563 * mono_type_get_name:
565 * \returns The string representation for type as it would be represented in IL code.
568 mono_type_get_name (MonoType
*type
)
570 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
574 * mono_type_get_underlying_type:
576 * \returns The \c MonoType for the underlying integer type if \p type
577 * is an enum and byref is false, otherwise the type itself.
580 mono_type_get_underlying_type (MonoType
*type
)
582 if (type
->type
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (type
->data
.klass
) && !type
->byref
)
583 return mono_class_enum_basetype_internal (type
->data
.klass
);
584 if (type
->type
== MONO_TYPE_GENERICINST
&& m_class_is_enumtype (type
->data
.generic_class
->container_class
) && !type
->byref
)
585 return mono_class_enum_basetype_internal (type
->data
.generic_class
->container_class
);
590 * mono_class_is_open_constructed_type:
593 * \returns TRUE if type represents a generics open constructed type.
594 * IOW, not all type parameters required for the instantiation have
595 * been provided or it's a generic type definition.
597 * An open constructed type means it's a non realizable type. Not to
598 * be mixed up with an abstract type - we can't cast or dispatch to
599 * an open type, for example.
602 mono_class_is_open_constructed_type (MonoType
*t
)
608 case MONO_TYPE_SZARRAY
:
609 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.klass
));
610 case MONO_TYPE_ARRAY
:
611 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.array
->eklass
));
613 return mono_class_is_open_constructed_type (t
->data
.type
);
614 case MONO_TYPE_GENERICINST
:
615 return t
->data
.generic_class
->context
.class_inst
->is_open
;
616 case MONO_TYPE_CLASS
:
617 case MONO_TYPE_VALUETYPE
:
618 return mono_class_is_gtd (t
->data
.klass
);
625 This is a simple function to catch the most common bad instances of generic types.
626 Specially those that might lead to further failures in the runtime.
629 mono_type_is_valid_generic_argument (MonoType
*type
)
631 switch (type
->type
) {
633 case MONO_TYPE_TYPEDBYREF
:
635 case MONO_TYPE_VALUETYPE
:
636 return !m_class_is_byreflike (type
->data
.klass
);
643 can_inflate_gparam_with (MonoGenericParam
*gparam
, MonoType
*type
)
645 if (!mono_type_is_valid_generic_argument (type
))
648 /* Avoid inflating gparams with valuetype constraints with ref types during gsharing */
649 MonoGenericParamInfo
*info
= mono_generic_param_info (gparam
);
650 if (info
&& (info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)) {
651 if (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) {
652 MonoGenericParam
*inst_gparam
= type
->data
.generic_param
;
653 if (inst_gparam
->gshared_constraint
&& inst_gparam
->gshared_constraint
->type
== MONO_TYPE_OBJECT
)
662 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
);
665 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
667 gboolean changed
= FALSE
;
670 /* C++/CLI (and some Roslyn tests) constructs method signatures like:
671 * void .CL1`1.Test(!0 modopt(System.Nullable`1<!0>))
672 * where !0 has a custom modifier which itself mentions the type variable.
673 * So we need to potentially inflate the modifiers.
675 if (type
->has_cmods
) {
676 MonoType
*new_type
= inflate_generic_custom_modifiers (image
, type
, context
, error
);
677 return_val_if_nok (error
, NULL
);
678 if (new_type
!= NULL
) {
684 switch (type
->type
) {
685 case MONO_TYPE_MVAR
: {
687 int num
= mono_type_get_generic_param_num (type
);
688 MonoGenericInst
*inst
= context
->method_inst
;
695 MonoGenericParam
*gparam
= type
->data
.generic_param
;
696 if (num
>= inst
->type_argc
) {
697 const char *pname
= mono_generic_param_name (gparam
);
698 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
699 num
, pname
? pname
: "", inst
->type_argc
);
703 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
704 const char *pname
= mono_generic_param_name (gparam
);
705 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
706 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
710 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
711 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
712 * ->byref and ->attrs from @type are propagated to the returned type.
714 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
715 nt
->byref
= type
->byref
;
716 nt
->attrs
= type
->attrs
;
719 case MONO_TYPE_VAR
: {
721 int num
= mono_type_get_generic_param_num (type
);
722 MonoGenericInst
*inst
= context
->class_inst
;
729 MonoGenericParam
*gparam
= type
->data
.generic_param
;
730 if (num
>= inst
->type_argc
) {
731 const char *pname
= mono_generic_param_name (gparam
);
732 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
733 num
, pname
? pname
: "", inst
->type_argc
);
736 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
737 const char *pname
= mono_generic_param_name (gparam
);
738 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
739 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
743 #ifdef DEBUG_INFLATE_CMODS
744 gboolean append_cmods
;
745 append_cmods
= FALSE
;
746 if (type
->has_cmods
&& inst
->type_argv
[num
]->has_cmods
) {
747 char *tname
= mono_type_full_name (type
);
748 char *vname
= mono_type_full_name (inst
->type_argv
[num
]);
749 printf ("\n\n\tsubstitution for '%s' with '%s' yields...\n", tname
, vname
);
756 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
757 nt
->byref
= type
->byref
|| inst
->type_argv
[num
]->byref
;
758 nt
->attrs
= type
->attrs
;
759 #ifdef DEBUG_INFLATE_CMODS
761 char *ntname
= mono_type_full_name (nt
);
762 printf ("\tyields '%s'\n\n\n", ntname
);
768 case MONO_TYPE_SZARRAY
: {
769 MonoClass
*eclass
= type
->data
.klass
;
770 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
771 if ((!inflated
&& !changed
) || !is_ok (error
))
775 nt
= mono_metadata_type_dup (image
, type
);
776 nt
->data
.klass
= mono_class_from_mono_type_internal (inflated
);
777 mono_metadata_free_type (inflated
);
780 case MONO_TYPE_ARRAY
: {
781 MonoClass
*eclass
= type
->data
.array
->eklass
;
782 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
783 if ((!inflated
&& !changed
) || !is_ok (error
))
787 nt
= mono_metadata_type_dup (image
, type
);
788 nt
->data
.array
->eklass
= mono_class_from_mono_type_internal (inflated
);
789 mono_metadata_free_type (inflated
);
792 case MONO_TYPE_GENERICINST
: {
793 MonoGenericClass
*gclass
= type
->data
.generic_class
;
794 MonoGenericInst
*inst
;
796 if (!gclass
->context
.class_inst
->is_open
) {
803 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
804 return_val_if_nok (error
, NULL
);
806 if (inst
!= gclass
->context
.class_inst
)
807 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
809 if (gclass
== type
->data
.generic_class
) {
816 nt
= mono_metadata_type_dup (image
, type
);
817 nt
->data
.generic_class
= gclass
;
820 case MONO_TYPE_CLASS
:
821 case MONO_TYPE_VALUETYPE
: {
822 MonoClass
*klass
= type
->data
.klass
;
823 MonoGenericContainer
*container
= mono_class_try_get_generic_container (klass
);
824 MonoGenericInst
*inst
;
825 MonoGenericClass
*gclass
= NULL
;
835 /* We can't use context->class_inst directly, since it can have more elements */
836 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
837 return_val_if_nok (error
, NULL
);
839 if (inst
== container
->context
.class_inst
) {
846 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, image_is_dynamic (m_class_get_image (klass
)));
848 nt
= mono_metadata_type_dup (image
, type
);
849 nt
->type
= MONO_TYPE_GENERICINST
;
850 nt
->data
.generic_class
= gclass
;
853 case MONO_TYPE_PTR
: {
854 MonoType
*nt
, *inflated
= inflate_generic_type (image
, type
->data
.type
, context
, error
);
855 if ((!inflated
&& !changed
) || !is_ok (error
))
857 if (!inflated
&& changed
)
859 nt
= mono_metadata_type_dup (image
, type
);
860 nt
->data
.type
= inflated
;
873 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
875 MonoType
*result
= NULL
;
876 g_assert (type
->has_cmods
);
877 int count
= mono_type_custom_modifier_count (type
);
878 gboolean changed
= FALSE
;
880 /* Try not to blow up the stack. See comment on MONO_MAX_EXPECTED_CMODS. */
881 g_assert (count
< MONO_MAX_EXPECTED_CMODS
);
882 size_t aggregate_size
= mono_sizeof_aggregate_modifiers (count
);
883 MonoAggregateModContainer
*candidate_mods
= g_alloca (aggregate_size
);
884 memset (candidate_mods
, 0, aggregate_size
);
885 candidate_mods
->count
= count
;
887 for (int i
= 0; i
< count
; ++i
) {
889 MonoType
*cmod_old
= mono_type_get_custom_modifier (type
, i
, &required
, error
);
890 goto_if_nok (error
, leave
);
891 MonoType
*cmod_new
= inflate_generic_type (NULL
, cmod_old
, context
, error
);
892 goto_if_nok (error
, leave
);
895 candidate_mods
->modifiers
[i
].required
= required
;
896 candidate_mods
->modifiers
[i
].type
= cmod_new
;
900 /* if we're going to make a new type, fill in any modifiers that weren't affected by inflation with copies of the original values. */
901 for (int i
= 0; i
< count
; ++i
) {
902 if (candidate_mods
->modifiers
[i
].type
== NULL
) {
903 candidate_mods
->modifiers
[i
].type
= mono_metadata_type_dup (NULL
, mono_type_get_custom_modifier (type
, i
, NULL
, error
));
905 /* it didn't error in the first loop, so should be ok now, too */
906 mono_error_assert_ok (error
);
910 #ifdef DEBUG_INFLATE_CMODS
912 char *full_name
= mono_type_full_name ((MonoType
*)type
);
913 printf ("\n\n\tcustom modifier on '%s' affected by subsititution\n\n\n", full_name
);
918 MonoType
*new_type
= g_alloca (mono_sizeof_type_with_mods (count
, TRUE
));
919 /* first init just the non-modifier portion of new_type before populating the
921 memcpy (new_type
, type
, MONO_SIZEOF_TYPE
);
922 mono_type_with_mods_init (new_type
, count
, TRUE
);
923 mono_type_set_amods (new_type
, mono_metadata_get_canonical_aggregate_modifiers (candidate_mods
));
924 result
= mono_metadata_type_dup (image
, new_type
);
928 for (int i
= 0; i
< count
; ++i
) {
929 if (candidate_mods
->modifiers
[i
].type
)
930 mono_metadata_free_type (candidate_mods
->modifiers
[i
].type
);
937 mono_generic_class_get_context (MonoGenericClass
*gclass
)
939 return &gclass
->context
;
943 mono_class_get_context (MonoClass
*klass
)
945 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
946 return gklass
? mono_generic_class_get_context (gklass
) : NULL
;
950 * mono_class_inflate_generic_type_with_mempool:
951 * @mempool: a mempool
953 * @context: a generics context
954 * @error: error context
956 * The same as mono_class_inflate_generic_type, but allocates the MonoType
957 * from mempool if it is non-NULL. If it is NULL, the MonoType is
958 * allocated on the heap and is owned by the caller.
959 * The returned type can potentially be the same as TYPE, so it should not be
960 * modified by the caller, and it should be freed using mono_metadata_free_type ().
963 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
965 MonoType
*inflated
= NULL
;
969 inflated
= inflate_generic_type (image
, type
, context
, error
);
970 return_val_if_nok (error
, NULL
);
973 MonoType
*shared
= mono_metadata_get_shared_type (type
);
975 if (shared
&& !type
->has_cmods
) {
978 return mono_metadata_type_dup (image
, type
);
982 UnlockedIncrement (&mono_stats
.inflated_type_count
);
987 * mono_class_inflate_generic_type:
989 * \param context a generics context
990 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
992 * If \p type is a generic type and \p context is not NULL, instantiate it using the
993 * generics context \p context.
995 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
996 * on the heap and is owned by the caller. Returns NULL on error.
999 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
1003 result
= mono_class_inflate_generic_type_checked (type
, context
, error
);
1004 mono_error_cleanup (error
);
1009 * mono_class_inflate_generic_type:
1011 * @context: a generics context
1012 * @error: error context to use
1014 * If @type is a generic type and @context is not NULL, instantiate it using the
1015 * generics context @context.
1017 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
1018 * on the heap and is owned by the caller.
1021 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
1023 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
1027 * mono_class_inflate_generic_type_no_copy:
1029 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
1033 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
1035 MonoType
*inflated
= NULL
;
1039 inflated
= inflate_generic_type (image
, type
, context
, error
);
1040 return_val_if_nok (error
, NULL
);
1046 UnlockedIncrement (&mono_stats
.inflated_type_count
);
1051 * mono_class_inflate_generic_class:
1053 * Inflate the class @gklass with @context. Set @error on failure.
1056 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
1061 inflated
= mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass
), context
, error
);
1062 return_val_if_nok (error
, NULL
);
1064 res
= mono_class_from_mono_type_internal (inflated
);
1065 mono_metadata_free_type (inflated
);
1070 static MonoGenericContext
1071 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
1073 MonoGenericInst
*class_inst
= NULL
;
1074 MonoGenericInst
*method_inst
= NULL
;
1075 MonoGenericContext res
= { NULL
, NULL
};
1079 if (context
->class_inst
) {
1080 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
1085 if (context
->method_inst
) {
1086 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
1091 res
.class_inst
= class_inst
;
1092 res
.method_inst
= method_inst
;
1098 * mono_class_inflate_generic_method:
1099 * \param method a generic method
1100 * \param context a generics context
1102 * Instantiate the generic method \p method using the generics context \p context.
1104 * \returns The new instantiated method
1107 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
1110 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1111 mono_error_assert_msg_ok (error
, "Could not inflate generic method");
1116 mono_class_inflate_generic_method_checked (MonoMethod
*method
, MonoGenericContext
*context
, MonoError
*error
)
1118 return mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1122 * mono_class_inflate_generic_method_full_checked:
1123 * Instantiate method \p method with the generic context \p context.
1124 * On failure returns NULL and sets \p error.
1126 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1127 * Use mono_method_signature_internal () and mono_method_get_header () to get the correct values.
1130 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
1133 MonoMethodInflated
*iresult
, *cached
;
1134 MonoMethodSignature
*sig
;
1135 MonoGenericContext tmp_context
;
1139 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1140 while (method
->is_inflated
) {
1141 MonoGenericContext
*method_context
= mono_method_get_context (method
);
1142 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1144 tmp_context
= inflate_generic_context (method_context
, context
, error
);
1145 return_val_if_nok (error
, NULL
);
1147 context
= &tmp_context
;
1149 if (mono_metadata_generic_context_equal (method_context
, context
))
1152 method
= imethod
->declaring
;
1156 * A method only needs to be inflated if the context has argument for which it is
1159 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1160 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1163 if (!((method
->is_generic
&& context
->method_inst
) ||
1164 (mono_class_is_gtd (method
->klass
) && context
->class_inst
)))
1167 iresult
= g_new0 (MonoMethodInflated
, 1);
1168 iresult
->context
= *context
;
1169 iresult
->declaring
= method
;
1171 if (!context
->method_inst
&& method
->is_generic
)
1172 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1174 if (!context
->class_inst
) {
1175 g_assert (!mono_class_is_ginst (iresult
->declaring
->klass
));
1176 if (mono_class_is_gtd (iresult
->declaring
->klass
))
1177 iresult
->context
.class_inst
= mono_class_get_generic_container (iresult
->declaring
->klass
)->context
.class_inst
;
1179 /* This can happen with some callers like mono_object_get_virtual_method_internal () */
1180 if (!mono_class_is_gtd (iresult
->declaring
->klass
) && !mono_class_is_ginst (iresult
->declaring
->klass
))
1181 iresult
->context
.class_inst
= NULL
;
1183 MonoImageSet
*set
= mono_metadata_get_image_set_for_method (iresult
);
1186 mono_image_set_lock (set
);
1187 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1188 mono_image_set_unlock (set
);
1192 return (MonoMethod
*)cached
;
1195 UnlockedIncrement (&mono_stats
.inflated_method_count
);
1197 UnlockedAdd (&mono_inflated_methods_size
, sizeof (MonoMethodInflated
));
1199 sig
= mono_method_signature_internal (method
);
1201 char *name
= mono_type_get_full_name (method
->klass
);
1202 mono_error_set_bad_image (error
, mono_method_get_image (method
), "Could not resolve signature of method %s:%s", name
, method
->name
);
1208 memcpy (&iresult
->method
.pinvoke
, method
, sizeof (MonoMethodPInvoke
));
1210 memcpy (&iresult
->method
.method
, method
, sizeof (MonoMethod
));
1213 result
= (MonoMethod
*) iresult
;
1214 result
->is_inflated
= TRUE
;
1215 result
->is_generic
= FALSE
;
1216 result
->sre_method
= FALSE
;
1217 result
->signature
= NULL
;
1219 if (method
->wrapper_type
) {
1220 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)method
;
1221 MonoMethodWrapper
*resw
= (MonoMethodWrapper
*)result
;
1222 int len
= GPOINTER_TO_INT (((void**)mw
->method_data
) [0]);
1224 resw
->method_data
= (void **)g_malloc (sizeof (gpointer
) * (len
+ 1));
1225 memcpy (resw
->method_data
, mw
->method_data
, sizeof (gpointer
) * (len
+ 1));
1228 if (iresult
->context
.method_inst
) {
1229 MonoGenericInst
*method_inst
= iresult
->context
.method_inst
;
1230 /* Set the generic_container of the result to the generic_container of method */
1231 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
1233 if (generic_container
&& method_inst
== generic_container
->context
.method_inst
) {
1234 result
->is_generic
= 1;
1235 mono_method_set_generic_container (result
, generic_container
);
1238 /* Check that the method is not instantiated with any invalid types */
1239 for (int i
= 0; i
< method_inst
->type_argc
; i
++) {
1240 if (!mono_type_is_valid_generic_argument (method_inst
->type_argv
[i
])) {
1241 mono_error_set_bad_image (error
, mono_method_get_image (method
), "MVAR %d cannot be expanded with type 0x%x",
1242 i
, method_inst
->type_argv
[i
]->type
);
1249 MonoGenericClass
*gklass_hint
= mono_class_try_get_generic_class (klass_hint
);
1250 if (gklass_hint
&& (gklass_hint
->container_class
!= method
->klass
|| gklass_hint
->context
.class_inst
!= context
->class_inst
))
1254 if (mono_class_is_gtd (method
->klass
))
1255 result
->klass
= klass_hint
;
1257 if (!result
->klass
) {
1258 MonoType
*inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (method
->klass
), context
, error
);
1262 result
->klass
= inflated
? mono_class_from_mono_type_internal (inflated
) : method
->klass
;
1264 mono_metadata_free_type (inflated
);
1268 * FIXME: This should hold, but it doesn't:
1270 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1271 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1272 * g_assert (result->is_generic);
1275 * Fixing this here causes other things to break, hence a very
1276 * ugly hack in mini-trampolines.c - see
1277 * is_generic_method_definition().
1281 mono_image_set_lock (set
);
1282 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1284 g_hash_table_insert (set
->gmethod_cache
, iresult
, iresult
);
1285 iresult
->owner
= set
;
1288 mono_image_set_unlock (set
);
1290 return (MonoMethod
*)cached
;
1298 * mono_get_inflated_method:
1300 * Obsolete. We keep it around since it's mentioned in the public API.
1303 mono_get_inflated_method (MonoMethod
*method
)
1309 * mono_method_get_context_general:
1311 * @uninflated: handle uninflated methods?
1313 * Returns the generic context of a method or NULL if it doesn't have
1314 * one. For an inflated method that's the context stored in the
1315 * method. Otherwise it's in the method's generic container or in the
1316 * generic container of the method's class.
1319 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1321 if (method
->is_inflated
) {
1322 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1323 return &imethod
->context
;
1327 if (method
->is_generic
)
1328 return &(mono_method_get_generic_container (method
)->context
);
1329 if (mono_class_is_gtd (method
->klass
))
1330 return &mono_class_get_generic_container (method
->klass
)->context
;
1335 * mono_method_get_context:
1338 * Returns the generic context for method if it's inflated, otherwise
1342 mono_method_get_context (MonoMethod
*method
)
1344 return mono_method_get_context_general (method
, FALSE
);
1348 * mono_method_get_generic_container:
1350 * Returns the generic container of METHOD, which should be a generic method definition.
1351 * Returns NULL if METHOD is not a generic method definition.
1352 * LOCKING: Acquires the loader lock.
1354 MonoGenericContainer
*
1355 mono_method_get_generic_container (MonoMethod
*method
)
1357 MonoGenericContainer
*container
;
1359 if (!method
->is_generic
)
1362 container
= (MonoGenericContainer
*)mono_image_property_lookup (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1363 g_assert (container
);
1369 * mono_method_set_generic_container:
1371 * Sets the generic container of METHOD to CONTAINER.
1372 * LOCKING: Acquires the image lock.
1375 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1377 g_assert (method
->is_generic
);
1379 mono_image_property_insert (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1383 * mono_class_find_enum_basetype:
1384 * \param class The enum class
1386 * Determine the basetype of an enum by iterating through its fields. We do this
1387 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1390 mono_class_find_enum_basetype (MonoClass
*klass
, MonoError
*error
)
1392 MonoGenericContainer
*container
= NULL
;
1393 MonoImage
*image
= m_class_get_image (klass
);
1394 const int top
= mono_class_get_field_count (klass
);
1395 int i
, first_field_idx
;
1397 g_assert (m_class_is_enumtype (klass
));
1401 container
= mono_class_try_get_generic_container (klass
);
1402 if (mono_class_is_ginst (klass
)) {
1403 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1405 container
= mono_class_get_generic_container (gklass
);
1406 g_assert (container
);
1410 * Fetch all the field information.
1412 first_field_idx
= mono_class_get_first_field_idx (klass
);
1413 for (i
= 0; i
< top
; i
++){
1415 guint32 cols
[MONO_FIELD_SIZE
];
1416 int idx
= first_field_idx
+ i
;
1419 /* first_field_idx and idx points into the fieldptr table */
1420 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1422 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1425 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
))
1428 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
1429 mono_metadata_decode_value (sig
, &sig
);
1430 /* FIELD signature == 0x06 */
1432 mono_error_set_bad_image (error
, image
, "Invalid field signature %x, expected 0x6 but got %x", cols
[MONO_FIELD_SIGNATURE
], *sig
);
1436 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
1440 if (mono_class_is_ginst (klass
)) {
1441 //FIXME do we leak here?
1442 ftype
= mono_class_inflate_generic_type_checked (ftype
, mono_class_get_context (klass
), error
);
1445 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1450 mono_error_set_type_load_class (error
, klass
, "Could not find base type");
1457 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1460 mono_type_has_exceptions (MonoType
*type
)
1462 switch (type
->type
) {
1463 case MONO_TYPE_CLASS
:
1464 case MONO_TYPE_VALUETYPE
:
1465 case MONO_TYPE_SZARRAY
:
1466 return mono_class_has_failure (type
->data
.klass
);
1467 case MONO_TYPE_ARRAY
:
1468 return mono_class_has_failure (type
->data
.array
->eklass
);
1469 case MONO_TYPE_GENERICINST
:
1470 return mono_class_has_failure (mono_class_create_generic_inst (type
->data
.generic_class
));
1477 mono_error_set_for_class_failure (MonoError
*oerror
, const MonoClass
*klass
)
1479 g_assert (mono_class_has_failure (klass
));
1480 MonoErrorBoxed
*box
= mono_class_get_exception_data ((MonoClass
*)klass
);
1481 mono_error_set_from_boxed (oerror
, box
);
1487 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1491 mono_class_alloc (MonoClass
*klass
, int size
)
1493 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1495 return mono_image_set_alloc (gklass
->owner
, size
);
1497 return mono_image_alloc (m_class_get_image (klass
), size
);
1501 (mono_class_alloc0
) (MonoClass
*klass
, int size
)
1505 res
= mono_class_alloc (klass
, size
);
1506 memset (res
, 0, size
);
1510 #define mono_class_new0(klass,struct_type, n_structs) \
1511 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1514 * mono_class_set_failure_causedby_class:
1515 * \param klass the class that is failing
1516 * \param caused_by the class that caused the failure
1517 * \param msg Why \p klass is failing.
1519 * If \p caused_by has a failure, sets a TypeLoadException failure on
1520 * \p klass with message "\p msg, due to: {\p caused_by message}".
1522 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1525 mono_class_set_type_load_failure_causedby_class (MonoClass
*klass
, const MonoClass
*caused_by
, const gchar
* msg
)
1527 if (mono_class_has_failure (caused_by
)) {
1528 ERROR_DECL (cause_error
);
1529 mono_error_set_for_class_failure (cause_error
, caused_by
);
1530 mono_class_set_type_load_failure (klass
, "%s, due to: %s", msg
, mono_error_get_message (cause_error
));
1531 mono_error_cleanup (cause_error
);
1540 * mono_type_get_basic_type_from_generic:
1543 * Returns a closed type corresponding to the possibly open type
1547 mono_type_get_basic_type_from_generic (MonoType
*type
)
1549 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1550 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) &&
1551 (!type
->data
.generic_param
->gshared_constraint
|| type
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_OBJECT
))
1552 return mono_get_object_type ();
1557 * mono_class_get_method_by_index:
1559 * Returns klass->methods [index], initializing klass->methods if neccesary.
1561 * LOCKING: Acquires the loader lock.
1564 mono_class_get_method_by_index (MonoClass
*klass
, int index
)
1568 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1569 /* Avoid calling setup_methods () if possible */
1570 if (gklass
&& !m_class_get_methods (klass
)) {
1573 m
= mono_class_inflate_generic_method_full_checked (
1574 m_class_get_methods (gklass
->container_class
) [index
], klass
, mono_class_get_context (klass
), error
);
1575 g_assert (is_ok (error
)); /* FIXME don't swallow the error */
1577 * If setup_methods () is called later for this class, no duplicates are created,
1578 * since inflate_generic_method guarantees that only one instance of a method
1579 * is created for each context.
1582 mono_class_setup_methods (klass);
1583 g_assert (m == klass->methods [index]);
1587 mono_class_setup_methods (klass
);
1588 if (mono_class_has_failure (klass
)) /*FIXME do proper error handling*/
1590 g_assert (index
>= 0 && index
< mono_class_get_method_count (klass
));
1591 return m_class_get_methods (klass
) [index
];
1596 * mono_class_get_inflated_method:
1597 * \param klass an inflated class
1598 * \param method a method of \p klass's generic definition
1599 * \param error set on error
1601 * Given an inflated class \p klass and a method \p method which should be a
1602 * method of \p klass's generic definition, return the inflated method
1603 * corresponding to \p method.
1605 * On failure sets \p error and returns NULL.
1608 mono_class_get_inflated_method (MonoClass
*klass
, MonoMethod
*method
, MonoError
*error
)
1610 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1613 g_assert (method
->klass
== gklass
);
1615 mono_class_setup_methods (gklass
);
1616 if (mono_class_has_failure (gklass
)) {
1617 mono_error_set_for_class_failure (error
, gklass
);
1621 MonoMethod
**gklass_methods
= m_class_get_methods (gklass
);
1622 mcount
= mono_class_get_method_count (gklass
);
1623 for (i
= 0; i
< mcount
; ++i
) {
1624 if (gklass_methods
[i
] == method
) {
1625 MonoMethod
*inflated_method
= NULL
;
1626 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
1627 if (klass_methods
) {
1628 inflated_method
= klass_methods
[i
];
1630 inflated_method
= mono_class_inflate_generic_method_full_checked (gklass_methods
[i
], klass
, mono_class_get_context (klass
), error
);
1631 return_val_if_nok (error
, NULL
);
1633 g_assert (inflated_method
);
1634 return inflated_method
;
1638 g_assert_not_reached ();
1642 * mono_class_get_vtable_entry:
1644 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
1645 * LOCKING: Acquires the loader lock.
1648 mono_class_get_vtable_entry (MonoClass
*klass
, int offset
)
1652 if (m_class_get_rank (klass
) == 1) {
1653 MonoClass
*klass_parent
= m_class_get_parent (klass
);
1655 * szarrays do not overwrite any methods of Array, so we can avoid
1656 * initializing their vtables in some cases.
1658 mono_class_setup_vtable (klass_parent
);
1659 if (offset
< m_class_get_vtable_size (klass_parent
))
1660 return m_class_get_vtable (klass_parent
) [offset
];
1663 if (mono_class_is_ginst (klass
)) {
1665 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1666 mono_class_setup_vtable (gklass
);
1667 m
= m_class_get_vtable (gklass
) [offset
];
1669 m
= mono_class_inflate_generic_method_full_checked (m
, klass
, mono_class_get_context (klass
), error
);
1670 g_assert (is_ok (error
)); /* FIXME don't swallow this error */
1672 mono_class_setup_vtable (klass
);
1673 if (mono_class_has_failure (klass
))
1675 m
= m_class_get_vtable (klass
) [offset
];
1682 * mono_class_get_vtable_size:
1684 * Return the vtable size for KLASS.
1687 mono_class_get_vtable_size (MonoClass
*klass
)
1689 mono_class_setup_vtable (klass
);
1691 return m_class_get_vtable_size (klass
);
1695 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, GHashTable
**ifaces
, MonoError
*error
)
1700 mono_class_setup_interfaces (klass
, error
);
1701 return_if_nok (error
);
1703 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
1704 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
1705 ic
= klass_interfaces
[i
];
1708 *res
= g_ptr_array_new ();
1709 if (*ifaces
== NULL
)
1710 *ifaces
= g_hash_table_new (NULL
, NULL
);
1711 if (g_hash_table_lookup (*ifaces
, ic
))
1713 /* A gparam is not an implemented interface for the purposes of
1714 * mono_class_get_implemented_interfaces */
1715 if (mono_class_is_gparam (ic
))
1717 g_ptr_array_add (*res
, ic
);
1718 g_hash_table_insert (*ifaces
, ic
, ic
);
1719 mono_class_init_internal (ic
);
1720 if (mono_class_has_failure (ic
)) {
1721 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
1725 collect_implemented_interfaces_aux (ic
, res
, ifaces
, error
);
1726 return_if_nok (error
);
1731 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
1733 GPtrArray
*res
= NULL
;
1734 GHashTable
*ifaces
= NULL
;
1736 collect_implemented_interfaces_aux (klass
, &res
, &ifaces
, error
);
1738 g_hash_table_destroy (ifaces
);
1739 if (!is_ok (error
)) {
1741 g_ptr_array_free (res
, TRUE
);
1747 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
1749 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
)
1752 MonoClass
**klass_interfaces_packed
= m_class_get_interfaces_packed (klass
);
1753 for (i
= m_class_get_interface_offsets_count (klass
) -1 ; i
>= 0 ; i
-- ){
1754 MonoClass
*result
= klass_interfaces_packed
[i
];
1755 if (m_class_get_interface_id(result
) == m_class_get_interface_id(itf
)) {
1756 return m_class_get_interface_offsets_packed (klass
) [i
];
1763 * mono_class_interface_offset_with_variance:
1765 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
1766 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
1768 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
1770 * FIXME figure out MS disambiguation rules and fix this function.
1773 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
)
1775 int i
= mono_class_interface_offset (klass
, itf
);
1776 *non_exact_match
= FALSE
;
1780 int klass_interface_offsets_count
= m_class_get_interface_offsets_count (klass
);
1782 if (m_class_is_array_special_interface (itf
) && m_class_get_rank (klass
) < 2) {
1783 MonoClass
*gtd
= mono_class_get_generic_type_definition (itf
);
1786 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1787 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1789 *non_exact_match
= TRUE
;
1795 return m_class_get_interface_offsets_packed (klass
) [found
];
1797 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1798 if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass
) [i
]) == gtd
) {
1800 *non_exact_match
= TRUE
;
1808 return m_class_get_interface_offsets_packed (klass
) [found
];
1811 if (!mono_class_has_variant_generic_params (itf
))
1814 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1815 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1816 *non_exact_match
= TRUE
;
1817 return m_class_get_interface_offsets_packed (klass
) [i
];
1826 * mono_method_get_vtable_slot:
1828 * Returns method->slot, computing it if neccesary. Return -1 on failure.
1829 * LOCKING: Acquires the loader lock.
1831 * FIXME Use proper MonoError machinery here.
1834 mono_method_get_vtable_slot (MonoMethod
*method
)
1836 if (method
->slot
== -1) {
1837 mono_class_setup_vtable (method
->klass
);
1838 if (mono_class_has_failure (method
->klass
))
1840 if (method
->slot
== -1) {
1844 if (!mono_class_is_ginst (method
->klass
)) {
1845 g_assert (method
->is_inflated
);
1846 return mono_method_get_vtable_slot (((MonoMethodInflated
*)method
)->declaring
);
1849 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
1850 g_assert (mono_class_is_ginst (method
->klass
));
1851 gklass
= mono_class_get_generic_class (method
->klass
)->container_class
;
1852 mono_class_setup_methods (method
->klass
);
1853 MonoMethod
**klass_methods
= m_class_get_methods (method
->klass
);
1854 g_assert (klass_methods
);
1855 mcount
= mono_class_get_method_count (method
->klass
);
1856 for (i
= 0; i
< mcount
; ++i
) {
1857 if (klass_methods
[i
] == method
)
1860 g_assert (i
< mcount
);
1861 g_assert (m_class_get_methods (gklass
));
1862 method
->slot
= m_class_get_methods (gklass
) [i
]->slot
;
1864 g_assert (method
->slot
!= -1);
1866 return method
->slot
;
1870 * mono_method_get_vtable_index:
1871 * \param method a method
1873 * Returns the index into the runtime vtable to access the method or,
1874 * in the case of a virtual generic method, the virtual generic method
1875 * thunk. Returns -1 on failure.
1877 * FIXME Use proper MonoError machinery here.
1880 mono_method_get_vtable_index (MonoMethod
*method
)
1882 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1883 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
1884 if (imethod
->declaring
->is_generic
)
1885 return mono_method_get_vtable_slot (imethod
->declaring
);
1887 return mono_method_get_vtable_slot (method
);
1891 * mono_class_has_finalizer:
1893 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
1896 * LOCKING: Acquires the loader lock;
1899 mono_class_has_finalizer (MonoClass
*klass
)
1901 if (!m_class_is_has_finalize_inited (klass
))
1902 mono_class_setup_has_finalizer (klass
);
1904 return m_class_has_finalize (klass
);
1908 mono_is_corlib_image (MonoImage
*image
)
1910 return image
== mono_defaults
.corlib
;
1914 /** Is klass a Nullable<T> ginst? */
1916 mono_class_is_nullable (MonoClass
*klass
)
1918 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1919 return gklass
&& gklass
->container_class
== mono_defaults
.generic_nullable_class
;
1922 /** if klass is T? return T */
1924 mono_class_get_nullable_param_internal (MonoClass
*klass
)
1926 g_assert (mono_class_is_nullable (klass
));
1927 return mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
1931 mono_class_get_nullable_param (MonoClass
*klass
)
1933 MonoClass
*result
= NULL
;
1934 MONO_ENTER_GC_UNSAFE
;
1935 result
= mono_class_get_nullable_param_internal (klass
);
1936 MONO_EXIT_GC_UNSAFE
;
1941 mono_type_is_primitive (MonoType
*type
)
1943 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1944 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1948 get_image_for_container (MonoGenericContainer
*container
)
1951 if (container
->is_anonymous
) {
1952 result
= container
->owner
.image
;
1955 if (container
->is_method
) {
1956 MonoMethod
*method
= container
->owner
.method
;
1957 g_assert_checked (method
);
1958 klass
= method
->klass
;
1960 klass
= container
->owner
.klass
;
1962 g_assert_checked (klass
);
1963 result
= m_class_get_image (klass
);
1970 mono_get_image_for_generic_param (MonoGenericParam
*param
)
1972 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
1973 g_assert_checked (container
);
1974 return get_image_for_container (container
);
1977 // Make a string in the designated image consisting of a single integer.
1978 #define INT_STRING_SIZE 16
1980 mono_make_generic_name_string (MonoImage
*image
, int num
)
1982 char *name
= (char *)mono_image_alloc0 (image
, INT_STRING_SIZE
);
1983 g_snprintf (name
, INT_STRING_SIZE
, "%d", num
);
1988 * mono_class_from_generic_parameter:
1989 * \param param Parameter to find/construct a class for.
1990 * \param arg2 Is ignored.
1991 * \param arg3 Is ignored.
1994 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*arg2 G_GNUC_UNUSED
, gboolean arg3 G_GNUC_UNUSED
)
1996 return mono_class_create_generic_parameter (param
);
2000 * mono_ptr_class_get:
2003 mono_ptr_class_get (MonoType
*type
)
2005 return mono_class_create_ptr (type
);
2009 * mono_class_from_mono_type:
2010 * \param type describes the type to return
2011 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
2014 mono_class_from_mono_type (MonoType
*type
)
2017 MONO_ENTER_GC_UNSAFE
;
2018 result
= mono_class_from_mono_type_internal (type
);
2019 MONO_EXIT_GC_UNSAFE
;
2024 mono_class_from_mono_type_internal (MonoType
*type
)
2027 switch (type
->type
) {
2028 case MONO_TYPE_OBJECT
:
2029 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
2030 case MONO_TYPE_VOID
:
2031 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
2032 case MONO_TYPE_BOOLEAN
:
2033 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
2034 case MONO_TYPE_CHAR
:
2035 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
2037 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
2039 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
2041 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
2043 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
2045 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
2047 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
2049 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
2051 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
2053 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
2055 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
2057 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
2059 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
2060 case MONO_TYPE_STRING
:
2061 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
2062 case MONO_TYPE_TYPEDBYREF
:
2063 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
2064 case MONO_TYPE_ARRAY
:
2065 return mono_class_create_bounded_array (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
2067 return mono_class_create_ptr (type
->data
.type
);
2068 case MONO_TYPE_FNPTR
:
2069 return mono_class_create_fnptr (type
->data
.method
);
2070 case MONO_TYPE_SZARRAY
:
2071 return mono_class_create_array (type
->data
.klass
, 1);
2072 case MONO_TYPE_CLASS
:
2073 case MONO_TYPE_VALUETYPE
:
2074 return type
->data
.klass
;
2075 case MONO_TYPE_GENERICINST
:
2076 return mono_class_create_generic_inst (type
->data
.generic_class
);
2077 case MONO_TYPE_MVAR
:
2079 return mono_class_create_generic_parameter (type
->data
.generic_param
);
2081 g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type
->type
);
2082 g_assert_not_reached ();
2085 // Yes, this returns NULL, even if it is documented as not doing so, but there
2086 // is no way for the code to make it this far, due to the assert above.
2091 * mono_type_retrieve_from_typespec
2092 * \param image context where the image is created
2093 * \param type_spec typespec token
2094 * \param context the generic context used to evaluate generic instantiations in
2097 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
2099 MonoType
*t
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
2101 *did_inflate
= FALSE
;
2106 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
2107 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
2109 if (!is_ok (error
)) {
2115 *did_inflate
= TRUE
;
2122 * mono_class_create_from_typespec
2123 * \param image context where the image is created
2124 * \param type_spec typespec token
2125 * \param context the generic context used to evaluate generic instantiations in
2128 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
2131 gboolean inflated
= FALSE
;
2132 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
2133 return_val_if_nok (error
, NULL
);
2134 ret
= mono_class_from_mono_type_internal (t
);
2136 mono_metadata_free_type (t
);
2141 * mono_bounded_array_class_get:
2142 * \param element_class element class
2143 * \param rank the dimension of the array class
2144 * \param bounded whenever the array has non-zero bounds
2145 * \returns A class object describing the array with element type \p element_type and
2146 * dimension \p rank.
2149 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
2151 return mono_class_create_bounded_array (eclass
, rank
, bounded
);
2155 * mono_array_class_get:
2156 * \param element_class element class
2157 * \param rank the dimension of the array class
2158 * \returns A class object describing the array with element type \p element_type and
2159 * dimension \p rank.
2162 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
2164 return mono_class_create_array (eclass
, rank
);
2168 * mono_class_instance_size:
2169 * \param klass a class
2171 * Use to get the size of a class in bytes.
2173 * \returns The size of an object instance
2176 mono_class_instance_size (MonoClass
*klass
)
2178 if (!m_class_is_size_inited (klass
))
2179 mono_class_init_internal (klass
);
2181 return m_class_get_instance_size (klass
);
2185 * mono_class_min_align:
2186 * \param klass a class
2188 * Use to get the computed minimum alignment requirements for the specified class.
2190 * Returns: minimum alignment requirements
2193 mono_class_min_align (MonoClass
*klass
)
2195 if (!m_class_is_size_inited (klass
))
2196 mono_class_init_internal (klass
);
2198 return m_class_get_min_align (klass
);
2202 * mono_class_data_size:
2203 * \param klass a class
2205 * \returns The size of the static class data
2208 mono_class_data_size (MonoClass
*klass
)
2210 if (!m_class_is_inited (klass
))
2211 mono_class_init_internal (klass
);
2212 /* This can happen with dynamically created types */
2213 if (!m_class_is_fields_inited (klass
))
2214 mono_class_setup_fields (klass
);
2216 /* in arrays, sizes.class_size is unioned with element_size
2217 * and arrays have no static fields
2219 if (m_class_get_rank (klass
))
2221 return m_class_get_sizes (klass
).class_size
;
2225 * Auxiliary routine to mono_class_get_field
2227 * Takes a field index instead of a field token.
2229 static MonoClassField
*
2230 mono_class_get_field_idx (MonoClass
*klass
, int idx
)
2232 mono_class_setup_fields (klass
);
2233 if (mono_class_has_failure (klass
))
2237 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2238 int fcount
= mono_class_get_field_count (klass
);
2239 MonoImage
*klass_image
= m_class_get_image (klass
);
2240 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2241 if (klass_image
->uncompressed_metadata
) {
2243 * first_field_idx points to the FieldPtr table, while idx points into the
2244 * Field table, so we have to do a search.
2246 /*FIXME this is broken for types with multiple fields with the same name.*/
2247 const char *name
= mono_metadata_string_heap (klass_image
, mono_metadata_decode_row_col (&klass_image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
2250 for (i
= 0; i
< fcount
; ++i
)
2251 if (mono_field_get_name (&klass_fields
[i
]) == name
)
2252 return &klass_fields
[i
];
2253 g_assert_not_reached ();
2256 if ((idx
>= first_field_idx
) && (idx
< first_field_idx
+ fcount
)){
2257 return &klass_fields
[idx
- first_field_idx
];
2261 klass
= m_class_get_parent (klass
);
2267 * mono_class_get_field:
2268 * \param class the class to lookup the field.
2269 * \param field_token the field token
2271 * \returns A \c MonoClassField representing the type and offset of
2272 * the field, or a NULL value if the field does not belong to this
2276 mono_class_get_field (MonoClass
*klass
, guint32 field_token
)
2278 int idx
= mono_metadata_token_index (field_token
);
2280 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
2282 return mono_class_get_field_idx (klass
, idx
- 1);
2286 * mono_class_get_field_from_name:
2287 * \param klass the class to lookup the field.
2288 * \param name the field name
2290 * Search the class \p klass and its parents for a field with the name \p name.
2292 * \returns The \c MonoClassField pointer of the named field or NULL
2295 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
2297 MonoClassField
*result
;
2298 MONO_ENTER_GC_UNSAFE
;
2299 result
= mono_class_get_field_from_name_full (klass
, name
, NULL
);
2300 MONO_EXIT_GC_UNSAFE
;
2305 * mono_class_get_field_from_name_full:
2306 * \param klass the class to lookup the field.
2307 * \param name the field name
2308 * \param type the type of the fields. This optional.
2310 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
2312 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
2313 * of its generic type definition.
2315 * \returns The MonoClassField pointer of the named field or NULL
2318 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
2320 MONO_REQ_GC_UNSAFE_MODE
;
2324 mono_class_setup_fields (klass
);
2325 if (mono_class_has_failure (klass
))
2329 int fcount
= mono_class_get_field_count (klass
);
2330 for (i
= 0; i
< fcount
; ++i
) {
2331 MonoClassField
*field
= &m_class_get_fields (klass
) [i
];
2333 if (strcmp (name
, mono_field_get_name (field
)) != 0)
2337 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
2338 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
2343 klass
= m_class_get_parent (klass
);
2349 * mono_class_get_field_token:
2350 * \param field the field we need the token of
2352 * Get the token of a field. Note that the tokesn is only valid for the image
2353 * the field was loaded from. Don't use this function for fields in dynamic types.
2355 * \returns The token representing the field in the image it was loaded from.
2358 mono_class_get_field_token (MonoClassField
*field
)
2360 MonoClass
*klass
= field
->parent
;
2363 mono_class_setup_fields (klass
);
2366 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2369 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2370 int fcount
= mono_class_get_field_count (klass
);
2371 for (i
= 0; i
< fcount
; ++i
) {
2372 if (&klass_fields
[i
] == field
) {
2373 int idx
= first_field_idx
+ i
+ 1;
2375 if (m_class_get_image (klass
)->uncompressed_metadata
)
2376 idx
= mono_metadata_translate_token_index (m_class_get_image (klass
), MONO_TABLE_FIELD
, idx
);
2377 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
2380 klass
= m_class_get_parent (klass
);
2383 g_assert_not_reached ();
2388 mono_field_get_index (MonoClassField
*field
)
2390 int index
= field
- m_class_get_fields (field
->parent
);
2391 g_assert (index
>= 0 && index
< mono_class_get_field_count (field
->parent
));
2397 * mono_class_get_field_default_value:
2399 * Return the default value of the field as a pointer into the metadata blob.
2402 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
2405 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2407 MonoClass
*klass
= field
->parent
;
2408 MonoFieldDefaultValue
*def_values
;
2410 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
2412 def_values
= mono_class_get_field_def_values (klass
);
2414 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
2416 mono_class_set_field_def_values (klass
, def_values
);
2419 field_index
= mono_field_get_index (field
);
2421 if (!def_values
[field_index
].data
) {
2422 MonoImage
*field_parent_image
= m_class_get_image (field
->parent
);
2423 cindex
= mono_metadata_get_constant_index (field_parent_image
, mono_class_get_field_token (field
), 0);
2427 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
2429 mono_metadata_decode_row (&field_parent_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2430 def_values
[field_index
].def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2431 mono_memory_barrier ();
2432 def_values
[field_index
].data
= (const char *)mono_metadata_blob_heap (field_parent_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2435 *def_type
= def_values
[field_index
].def_type
;
2436 return def_values
[field_index
].data
;
2440 mono_property_get_index (MonoProperty
*prop
)
2442 MonoClassPropertyInfo
*info
= mono_class_get_property_info (prop
->parent
);
2443 int index
= prop
- info
->properties
;
2445 g_assert (index
>= 0 && index
< info
->count
);
2451 * mono_class_get_property_default_value:
2453 * Return the default value of the field as a pointer into the metadata blob.
2456 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
2459 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2460 MonoClass
*klass
= property
->parent
;
2461 MonoImage
*klass_image
= m_class_get_image (klass
);
2463 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
2465 * We don't cache here because it is not used by C# so it's quite rare, but
2466 * we still do the lookup in klass->ext because that is where the data
2467 * is stored for dynamic assemblies.
2470 if (image_is_dynamic (klass_image
)) {
2471 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2472 int prop_index
= mono_property_get_index (property
);
2473 if (info
->def_values
&& info
->def_values
[prop_index
].data
) {
2474 *def_type
= info
->def_values
[prop_index
].def_type
;
2475 return info
->def_values
[prop_index
].data
;
2479 cindex
= mono_metadata_get_constant_index (klass_image
, mono_class_get_property_token (property
), 0);
2483 mono_metadata_decode_row (&klass_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2484 *def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2485 return (const char *)mono_metadata_blob_heap (klass_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2489 * mono_class_get_event_token:
2492 mono_class_get_event_token (MonoEvent
*event
)
2494 MonoClass
*klass
= event
->parent
;
2498 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
2500 for (i
= 0; i
< info
->count
; ++i
) {
2501 if (&info
->events
[i
] == event
)
2502 return mono_metadata_make_token (MONO_TABLE_EVENT
, info
->first
+ i
+ 1);
2505 klass
= m_class_get_parent (klass
);
2508 g_assert_not_reached ();
2513 mono_class_get_property_from_name_internal (MonoClass
*klass
, const char *name
)
2515 MONO_REQ_GC_UNSAFE_MODE
;
2518 gpointer iter
= NULL
;
2519 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2520 if (! strcmp (name
, p
->name
))
2523 klass
= m_class_get_parent (klass
);
2529 * mono_class_get_property_token:
2530 * \param prop MonoProperty to query
2532 * \returns The ECMA token for the specified property.
2535 mono_class_get_property_token (MonoProperty
*prop
)
2537 MonoClass
*klass
= prop
->parent
;
2541 gpointer iter
= NULL
;
2542 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2543 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2544 if (&info
->properties
[i
] == prop
)
2545 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, info
->first
+ i
+ 1);
2549 klass
= m_class_get_parent (klass
);
2552 g_assert_not_reached ();
2557 * mono_class_name_from_token:
2560 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
2562 const char *name
, *nspace
;
2563 if (image_is_dynamic (image
))
2564 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
2566 switch (type_token
& 0xff000000){
2567 case MONO_TOKEN_TYPE_DEF
: {
2568 guint32 cols
[MONO_TYPEDEF_SIZE
];
2569 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2570 guint tidx
= mono_metadata_token_index (type_token
);
2572 if (tidx
> tt
->rows
)
2573 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2575 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2576 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2577 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2578 if (strlen (nspace
) == 0)
2579 return g_strdup_printf ("%s", name
);
2581 return g_strdup_printf ("%s.%s", nspace
, name
);
2584 case MONO_TOKEN_TYPE_REF
: {
2586 guint32 cols
[MONO_TYPEREF_SIZE
];
2587 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2588 guint tidx
= mono_metadata_token_index (type_token
);
2591 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2593 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, error
)) {
2594 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2595 mono_error_cleanup (error
);
2599 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
2600 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2601 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2602 if (strlen (nspace
) == 0)
2603 return g_strdup_printf ("%s", name
);
2605 return g_strdup_printf ("%s.%s", nspace
, name
);
2608 case MONO_TOKEN_TYPE_SPEC
:
2609 return g_strdup_printf ("Typespec 0x%08x", type_token
);
2611 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2616 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
2618 if (image_is_dynamic (image
))
2619 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
2621 switch (type_token
& 0xff000000){
2622 case MONO_TOKEN_TYPE_DEF
:
2623 if (image
->assembly
)
2624 return mono_stringify_assembly_name (&image
->assembly
->aname
);
2625 else if (image
->assembly_name
)
2626 return g_strdup (image
->assembly_name
);
2627 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
2628 case MONO_TOKEN_TYPE_REF
: {
2630 MonoAssemblyName aname
;
2631 guint32 cols
[MONO_TYPEREF_SIZE
];
2632 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2633 guint32 idx
= mono_metadata_token_index (type_token
);
2636 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2638 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, error
)) {
2639 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2640 mono_error_cleanup (error
);
2643 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
2645 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
2646 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
2647 case MONO_RESOLUTION_SCOPE_MODULE
:
2649 return g_strdup ("");
2650 case MONO_RESOLUTION_SCOPE_MODULEREF
:
2652 return g_strdup ("");
2653 case MONO_RESOLUTION_SCOPE_TYPEREF
:
2655 return g_strdup ("");
2656 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
2657 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
2658 return mono_stringify_assembly_name (&aname
);
2660 g_assert_not_reached ();
2664 case MONO_TOKEN_TYPE_SPEC
:
2666 return g_strdup ("");
2668 g_assert_not_reached ();
2675 * mono_class_get_full:
2676 * \param image the image where the class resides
2677 * \param type_token the token for the class
2678 * \param context the generic context used to evaluate generic instantiations in
2679 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
2680 * \returns The \c MonoClass that represents \p type_token in \p image
2683 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
2687 klass
= mono_class_get_checked (image
, type_token
, error
);
2689 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2690 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2692 mono_error_assert_ok (error
);
2698 mono_class_get_and_inflate_typespec_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2703 klass
= mono_class_get_checked (image
, type_token
, error
);
2705 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2706 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2711 * mono_class_get_checked:
2712 * \param image the image where the class resides
2713 * \param type_token the token for the class
2714 * \param error error object to return any error
2716 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
2719 mono_class_get_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
2721 MonoClass
*klass
= NULL
;
2725 if (image_is_dynamic (image
)) {
2726 int table
= mono_metadata_token_table (type_token
);
2728 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
2729 mono_error_set_bad_image (error
, image
,"Bad token table for dynamic image: %x", table
);
2732 klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, NULL
, error
);
2736 switch (type_token
& 0xff000000){
2737 case MONO_TOKEN_TYPE_DEF
:
2738 klass
= mono_class_create_from_typedef (image
, type_token
, error
);
2740 case MONO_TOKEN_TYPE_REF
:
2741 klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
2743 case MONO_TOKEN_TYPE_SPEC
:
2744 klass
= mono_class_create_from_typespec (image
, type_token
, NULL
, error
);
2747 mono_error_set_bad_image (error
, image
, "Unknown type token %x", type_token
& 0xff000000);
2751 /* Generic case, should be avoided for when a better error is possible. */
2752 if (!klass
&& is_ok (error
)) {
2753 char *name
= mono_class_name_from_token (image
, type_token
);
2754 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
2755 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
);
2763 * mono_type_get_checked:
2764 * \param image the image where the type resides
2765 * \param type_token the token for the type
2766 * \param context the generic context used to evaluate generic instantiations in
2767 * \param error Error handling context
2769 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
2771 * \returns The MonoType that represents \p type_token in \p image
2774 mono_type_get_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2776 MonoType
*type
= NULL
;
2777 gboolean inflated
= FALSE
;
2781 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
2782 if (image_is_dynamic (image
)) {
2783 MonoClass
*klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, context
, error
);
2784 return_val_if_nok (error
, NULL
);
2785 return m_class_get_byval_arg (klass
);
2788 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
2789 MonoClass
*klass
= mono_class_get_checked (image
, type_token
, error
);
2793 if (m_class_has_failure (klass
)) {
2794 mono_error_set_for_class_failure (error
, klass
);
2797 return m_class_get_byval_arg (klass
);
2800 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, error
);
2807 MonoType
*tmp
= type
;
2808 type
= m_class_get_byval_arg (mono_class_from_mono_type_internal (type
));
2809 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
2810 * A MonoClass::_byval_arg of a generic type definion has type CLASS.
2811 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with _byval_arg.
2813 * The long term solution is to chaise this places and make then set MonoType::type correctly.
2815 if (type
->type
!= tmp
->type
)
2818 mono_metadata_free_type (tmp
);
2825 * \param image image where the class token will be looked up.
2826 * \param type_token a type token from the image
2827 * \returns the \c MonoClass with the given \p type_token on the \p image
2830 mono_class_get (MonoImage
*image
, guint32 type_token
)
2833 MonoClass
*result
= mono_class_get_checked (image
, type_token
, error
);
2834 mono_error_assert_ok (error
);
2839 * mono_image_init_name_cache:
2841 * Initializes the class name cache stored in image->name_cache.
2843 * LOCKING: Acquires the corresponding image lock.
2846 mono_image_init_name_cache (MonoImage
*image
)
2848 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2849 guint32 cols
[MONO_TYPEDEF_SIZE
];
2852 guint32 i
, visib
, nspace_index
;
2853 GHashTable
*name_cache2
, *nspace_table
, *the_name_cache
;
2855 if (image
->name_cache
)
2858 the_name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
2860 if (image_is_dynamic (image
)) {
2861 mono_image_lock (image
);
2862 if (image
->name_cache
) {
2863 /* Somebody initialized it before us */
2864 g_hash_table_destroy (the_name_cache
);
2866 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2868 mono_image_unlock (image
);
2872 /* Temporary hash table to avoid lookups in the nspace_table */
2873 name_cache2
= g_hash_table_new (NULL
, NULL
);
2875 for (i
= 1; i
<= t
->rows
; ++i
) {
2876 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
2877 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2879 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2880 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2882 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
2884 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2885 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2887 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
2888 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2889 if (!nspace_table
) {
2890 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2891 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2892 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2895 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
2898 /* Load type names from EXPORTEDTYPES table */
2900 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
2901 guint32 cols
[MONO_EXP_TYPE_SIZE
];
2904 for (i
= 0; i
< t
->rows
; ++i
) {
2905 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
2907 guint32 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
2908 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_EXP_TYPE
)
2912 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
2913 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
2915 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
2916 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2917 if (!nspace_table
) {
2918 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2919 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2920 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2923 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
2927 g_hash_table_destroy (name_cache2
);
2929 mono_image_lock (image
);
2930 if (image
->name_cache
) {
2931 /* Somebody initialized it before us */
2932 g_hash_table_destroy (the_name_cache
);
2934 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2936 mono_image_unlock (image
);
2939 /*FIXME Only dynamic assemblies should allow this operation.*/
2941 * mono_image_add_to_name_cache:
2944 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
2945 const char *name
, guint32 index
)
2947 GHashTable
*nspace_table
;
2948 GHashTable
*name_cache
;
2951 mono_image_init_name_cache (image
);
2952 mono_image_lock (image
);
2954 name_cache
= image
->name_cache
;
2955 if (!(nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache
, nspace
))) {
2956 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2957 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
2960 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
2961 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
2963 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
2965 mono_image_unlock (image
);
2974 find_all_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2976 char *name
= (char*)key
;
2977 FindAllUserData
*data
= (FindAllUserData
*)user_data
;
2978 if (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0)
2979 data
->values
= g_slist_prepend (data
->values
, value
);
2988 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2990 char *name
= (char*)key
;
2991 FindUserData
*data
= (FindUserData
*)user_data
;
2993 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
2994 data
->value
= value
;
2998 * mono_class_from_name_case:
2999 * \param image The MonoImage where the type is looked up in
3000 * \param name_space the type namespace
3001 * \param name the type short name.
3002 * \deprecated use the mono_class_from_name_case_checked variant instead.
3004 * Obtains a \c MonoClass with a given namespace and a given name which
3005 * is located in the given \c MonoImage. The namespace and name
3006 * lookups are case insensitive.
3009 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
3012 MonoClass
*res
= mono_class_from_name_case_checked (image
, name_space
, name
, error
);
3013 mono_error_cleanup (error
);
3019 * mono_class_from_name_case_checked:
3020 * \param image The MonoImage where the type is looked up in
3021 * \param name_space the type namespace
3022 * \param name the type short name.
3025 * Obtains a MonoClass with a given namespace and a given name which
3026 * is located in the given MonoImage. The namespace and name
3027 * lookups are case insensitive.
3029 * \returns The MonoClass if the given namespace and name were found, or NULL if it
3030 * was not found. The \p error object will contain information about the problem
3034 mono_class_from_name_case_checked (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
3037 GHashTable
*visited_images
;
3039 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3041 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, FALSE
, error
);
3043 g_hash_table_destroy (visited_images
);
3049 return_nested_in (MonoClass
*klass
, char *nested
, gboolean case_sensitive
)
3052 char *s
= strchr (nested
, '/');
3053 gpointer iter
= NULL
;
3060 while ((found
= mono_class_get_nested_types (klass
, &iter
))) {
3061 const char *name
= m_class_get_name (found
);
3064 strcmp_result
= strcmp (name
, nested
);
3066 strcmp_result
= mono_utf8_strcasecmp (name
, nested
);
3068 if (strcmp_result
== 0) {
3070 return return_nested_in (found
, s
, case_sensitive
);
3078 search_modules (MonoImage
*image
, const char *name_space
, const char *name
, gboolean case_sensitive
, MonoError
*error
)
3080 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
3081 MonoImage
*file_image
;
3088 * The EXPORTEDTYPES table only contains public types, so have to search the
3090 * Note: image->modules contains the contents of the MODULEREF table, while
3091 * the real module list is in the FILE table.
3093 for (i
= 0; i
< file_table
->rows
; i
++) {
3094 guint32 cols
[MONO_FILE_SIZE
];
3095 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
3096 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
3099 file_image
= mono_image_load_file_for_image_checked (image
, i
+ 1, error
);
3102 klass
= mono_class_from_name_checked (file_image
, name_space
, name
, error
);
3104 klass
= mono_class_from_name_case_checked (file_image
, name_space
, name
, error
);
3106 if (klass
|| !is_ok (error
))
3115 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, gboolean case_sensitive
, MonoError
*error
)
3117 GHashTable
*nspace_table
= NULL
;
3118 MonoImage
*loaded_image
= NULL
;
3127 // Checking visited images avoids stack overflows when cyclic references exist.
3128 if (g_hash_table_lookup (visited_images
, image
))
3131 g_hash_table_insert (visited_images
, image
, GUINT_TO_POINTER(1));
3133 if ((nested
= (char*)strchr (name
, '/'))) {
3134 int pos
= nested
- name
;
3135 int len
= strlen (name
);
3138 memcpy (buf
, name
, len
+ 1);
3140 nested
= buf
+ pos
+ 1;
3144 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
3145 // The AOT cache in get_class_from_name is case-sensitive, so don't bother with it for case-insensitive lookups
3146 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0 && case_sensitive
) {
3147 gboolean res
= get_class_from_name (image
, name_space
, name
, &klass
);
3150 klass
= search_modules (image
, name_space
, name
, case_sensitive
, error
);
3155 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3161 mono_image_init_name_cache (image
);
3162 mono_image_lock (image
);
3164 if (case_sensitive
) {
3165 nspace_table
= (GHashTable
*)g_hash_table_lookup (image
->name_cache
, name_space
);
3168 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
3170 FindAllUserData all_user_data
= { name_space
, NULL
};
3171 FindUserData user_data
= { name
, NULL
};
3174 // We're forced to check all matching namespaces, not just the first one found,
3175 // because our desired type could be in any of the ones that match case-insensitively.
3176 g_hash_table_foreach (image
->name_cache
, find_all_nocase
, &all_user_data
);
3178 values
= all_user_data
.values
;
3179 while (values
&& !user_data
.value
) {
3180 nspace_table
= (GHashTable
*)values
->data
;
3181 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
3182 values
= values
->next
;
3185 g_slist_free (all_user_data
.values
);
3187 if (user_data
.value
)
3188 token
= GPOINTER_TO_UINT (user_data
.value
);
3191 mono_image_unlock (image
);
3193 if (!token
&& image_is_dynamic (image
) && image
->modules
) {
3194 /* Search modules as well */
3195 for (i
= 0; i
< image
->module_count
; ++i
) {
3196 MonoImage
*module
= image
->modules
[i
];
3199 klass
= mono_class_from_name_checked (module
, name_space
, name
, error
);
3201 klass
= mono_class_from_name_case_checked (module
, name_space
, name
, error
);
3203 if (klass
|| !is_ok (error
))
3209 klass
= search_modules (image
, name_space
, name
, case_sensitive
, error
);
3210 if (klass
|| !is_ok (error
))
3215 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
3216 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3217 guint32 cols
[MONO_EXP_TYPE_SIZE
];
3220 idx
= mono_metadata_token_index (token
);
3222 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
3224 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
3225 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
3226 loaded_image
= mono_assembly_load_module_checked (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
, error
);
3229 klass
= mono_class_from_name_checked_aux (loaded_image
, name_space
, name
, visited_images
, case_sensitive
, error
);
3231 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3233 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
3234 guint32 assembly_idx
;
3236 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
3238 mono_assembly_load_reference (image
, assembly_idx
- 1);
3239 g_assert (image
->references
[assembly_idx
- 1]);
3240 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
3242 klass
= mono_class_from_name_checked_aux (image
->references
[assembly_idx
- 1]->image
, name_space
, name
, visited_images
, case_sensitive
, error
);
3244 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3247 g_assert_not_reached ();
3251 token
= MONO_TOKEN_TYPE_DEF
| token
;
3253 klass
= mono_class_get_checked (image
, token
, error
);
3255 return return_nested_in (klass
, nested
, case_sensitive
);
3260 * mono_class_from_name_checked:
3261 * \param image The MonoImage where the type is looked up in
3262 * \param name_space the type namespace
3263 * \param name the type short name.
3265 * Obtains a MonoClass with a given namespace and a given name which
3266 * is located in the given MonoImage.
3268 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
3269 * set if the class was not found or it will return NULL and set the error if there was a loading error.
3272 mono_class_from_name_checked (MonoImage
*image
, const char* name_space
, const char *name
, MonoError
*error
)
3275 GHashTable
*visited_images
;
3277 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3279 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, TRUE
, error
);
3281 g_hash_table_destroy (visited_images
);
3287 * mono_class_from_name:
3288 * \param image The \c MonoImage where the type is looked up in
3289 * \param name_space the type namespace
3290 * \param name the type short name.
3292 * Obtains a \c MonoClass with a given namespace and a given name which
3293 * is located in the given \c MonoImage.
3295 * To reference nested classes, use the "/" character as a separator.
3296 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
3297 * inside \c Foo, like this: "class Foo { class Bar {} }".
3300 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3303 MONO_ENTER_GC_UNSAFE
;
3306 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3307 mono_error_cleanup (error
); /* FIXME Don't swallow the error */
3308 MONO_EXIT_GC_UNSAFE
;
3313 * mono_class_load_from_name:
3314 * \param image The MonoImage where the type is looked up in
3315 * \param name_space the type namespace
3316 * \param name the type short name.
3318 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
3319 * This function should be used by the runtime for critical types to which there's no way to recover but crash
3320 * If they are missing. Thing of System.Object or System.String.
3323 mono_class_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3328 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3330 g_error ("Runtime critical type %s.%s not found", name_space
, name
);
3331 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3336 * mono_class_try_load_from_name:
3337 * \param image The MonoImage where the type is looked up in
3338 * \param name_space the type namespace
3339 * \param name the type short name.
3341 * This function tries to load a type, returning the class was found or NULL otherwise.
3342 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
3344 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
3345 * a type that we would otherwise assume to be available but was not due some error.
3349 mono_class_try_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3354 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3355 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3360 mono_interface_implements_interface (MonoClass
*interface_implementer
, MonoClass
*interface_implemented
)
3364 mono_class_setup_interfaces (interface_implementer
, error
);
3365 if (!is_ok (error
)) {
3366 mono_error_cleanup (error
);
3369 MonoClass
**klass_interfaces
= m_class_get_interfaces (interface_implementer
);
3370 for (i
= 0; i
< m_class_get_interface_count (interface_implementer
); i
++) {
3371 MonoClass
*ic
= klass_interfaces
[i
];
3372 if (mono_class_is_ginst (ic
))
3373 ic
= mono_class_get_generic_type_definition (ic
);
3374 if (ic
== interface_implemented
)
3381 mono_class_is_subclass_of_internal (MonoClass
*klass
, MonoClass
*klassc
,
3382 gboolean check_interfaces
)
3384 MONO_REQ_GC_UNSAFE_MODE
;
3385 /* FIXME test for interfaces with variant generic arguments */
3386 mono_class_init_internal (klass
);
3387 mono_class_init_internal (klassc
);
3389 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3390 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, m_class_get_interface_id (klassc
)))
3392 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3395 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
3396 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
3397 MonoClass
*ic
= klass_interfaces
[i
];
3402 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) && mono_class_has_parent (klass
, klassc
))
3407 * MS.NET thinks interfaces are a subclass of Object, so we think it as
3410 if (klassc
== mono_defaults
.object_class
)
3417 mono_type_is_generic_argument (MonoType
*type
)
3419 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
3423 mono_class_has_variant_generic_params (MonoClass
*klass
)
3426 MonoGenericContainer
*container
;
3428 if (!mono_class_is_ginst (klass
))
3431 container
= mono_class_get_generic_container (mono_class_get_generic_class (klass
)->container_class
);
3433 for (i
= 0; i
< container
->type_argc
; ++i
)
3434 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
3441 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
3443 if (target
== candidate
)
3446 if (check_for_reference_conv
&&
3447 mono_type_is_generic_argument (m_class_get_byval_arg (target
)) &&
3448 mono_type_is_generic_argument (m_class_get_byval_arg (candidate
))) {
3449 MonoGenericParam
*gparam
= m_class_get_byval_arg (candidate
)->data
.generic_param
;
3450 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
3452 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
3455 if (!mono_class_is_assignable_from_internal (target
, candidate
))
3461 * @container the generic container from the GTD
3462 * @klass: the class to be assigned to
3463 * @oklass: the source class
3465 * Both @klass and @oklass must be instances of the same generic interface.
3467 * Returns: TRUE if @klass can be assigned to a @klass variable
3470 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
3473 MonoType
**klass_argv
, **oklass_argv
;
3474 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3475 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3477 if (klass
== oklass
)
3480 /*Viable candidates are instances of the same generic interface*/
3481 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3484 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3485 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3487 for (j
= 0; j
< container
->type_argc
; ++j
) {
3488 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3489 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3491 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
) || (m_class_is_valuetype (param1_class
) && param1_class
!= param2_class
))
3495 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3496 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3498 if (param1_class
!= param2_class
) {
3499 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3500 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
3502 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3503 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
3513 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
3515 MonoGenericParam
*gparam
, *ogparam
;
3516 MonoGenericParamInfo
*tinfo
, *cinfo
;
3517 MonoClass
**candidate_class
;
3518 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
3521 if (target
== candidate
)
3523 MonoType
*target_byval_arg
= m_class_get_byval_arg (target
);
3524 MonoType
*candidate_byval_arg
= m_class_get_byval_arg (candidate
);
3525 if (target_byval_arg
->type
!= candidate_byval_arg
->type
)
3528 gparam
= target_byval_arg
->data
.generic_param
;
3529 ogparam
= candidate_byval_arg
->data
.generic_param
;
3530 tinfo
= mono_generic_param_info (gparam
);
3531 cinfo
= mono_generic_param_info (ogparam
);
3533 class_constraint_satisfied
= FALSE
;
3534 valuetype_constraint_satisfied
= FALSE
;
3536 /*candidate must have a super set of target's special constraints*/
3537 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3538 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3540 if (cinfo
->constraints
) {
3541 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3542 MonoClass
*cc
= *candidate_class
;
3543 MonoType
*cc_byval_arg
= m_class_get_byval_arg (cc
);
3545 if (mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3546 class_constraint_satisfied
= TRUE
;
3547 else if (!mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3548 valuetype_constraint_satisfied
= TRUE
;
3551 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
3552 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
3554 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
3556 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
3558 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
3559 valuetype_constraint_satisfied
)) {
3564 /*candidate type constraints must be a superset of target's*/
3565 if (tinfo
->constraints
) {
3566 MonoClass
**target_class
;
3567 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
3568 MonoClass
*tc
= *target_class
;
3569 MonoType
*tc_byval_arg
= m_class_get_byval_arg (tc
);
3572 * A constraint from @target might inflate into @candidate itself and in that case we don't need
3573 * check it's constraints since it satisfy the constraint by itself.
3575 if (mono_metadata_type_equal (tc_byval_arg
, candidate_byval_arg
))
3578 if (!cinfo
->constraints
)
3581 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3582 MonoClass
*cc
= *candidate_class
;
3584 if (mono_class_is_assignable_from_internal (tc
, cc
))
3588 * This happens when we have the following:
3590 * Bar<K> where K : IFace
3591 * Foo<T, U> where T : U where U : IFace
3593 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
3596 if (mono_type_is_generic_argument (m_class_get_byval_arg (cc
))) {
3597 if (mono_gparam_is_assignable_from (target
, cc
))
3601 if (!*candidate_class
)
3606 /*candidate itself must have a constraint that satisfy target*/
3607 if (cinfo
->constraints
) {
3608 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3609 MonoClass
*cc
= *candidate_class
;
3610 if (mono_class_is_assignable_from_internal (target
, cc
))
3618 * mono_class_is_assignable_from_internal:
3619 * \param klass the class to be assigned to
3620 * \param oklass the source class
3622 * \returns TRUE if an instance of class \p oklass can be assigned to an
3623 * instance of class \p klass
3626 mono_class_is_assignable_from_internal (MonoClass
*klass
, MonoClass
*oklass
)
3628 gboolean result
= FALSE
;
3630 mono_class_is_assignable_from_checked (klass
, oklass
, &result
, error
);
3631 mono_error_cleanup (error
);
3636 * mono_class_is_assignable_from:
3637 * \param klass the class to be assigned to
3638 * \param oklass the source class
3640 * \returns TRUE if an instance of class \p oklass can be assigned to an
3641 * instance of class \p klass
3644 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
3647 MONO_ENTER_GC_UNSAFE
;
3648 result
= mono_class_is_assignable_from_internal (klass
, oklass
);
3649 MONO_EXIT_GC_UNSAFE
;
3654 * mono_class_is_assignable_from_checked:
3655 * \param klass the class to be assigned to
3656 * \param oklass the source class
3657 * \param result set if there was no error
3658 * \param error set if there was an error
3660 * Sets \p result to TRUE if an instance of class \p oklass can be assigned to
3661 * an instance of class \p klass or FALSE if it cannot. On error, no \p error
3662 * is set and \p result is not valid.
3665 mono_class_is_assignable_from_checked (MonoClass
*klass
, MonoClass
*oklass
, gboolean
*result
, MonoError
*error
)
3668 if (klass
== oklass
) {
3673 MONO_REQ_GC_UNSAFE_MODE
;
3674 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
3675 if (!m_class_is_inited (klass
))
3676 mono_class_init_internal (klass
);
3678 if (!m_class_is_inited (oklass
))
3679 mono_class_init_internal (oklass
);
3681 if (mono_class_has_failure (klass
)) {
3682 mono_error_set_for_class_failure (error
, klass
);
3687 if (mono_class_has_failure (oklass
)) {
3688 mono_error_set_for_class_failure (error
, oklass
);
3693 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
3694 MonoType
*oklass_byval_arg
= m_class_get_byval_arg (oklass
);
3696 if (mono_type_is_generic_argument (klass_byval_arg
)) {
3697 if (!mono_type_is_generic_argument (oklass_byval_arg
)) {
3701 *result
= mono_gparam_is_assignable_from (klass
, oklass
);
3705 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
3706 * has a constraint which is a class type:
3709 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
3711 * In this case, Foo is assignable from T1.
3713 if (mono_type_is_generic_argument (oklass_byval_arg
)) {
3714 MonoGenericParam
*gparam
= oklass_byval_arg
->data
.generic_param
;
3715 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
3719 for (i
= 0; constraints
[i
]; ++i
) {
3720 if (mono_class_is_assignable_from_internal (klass
, constraints
[i
])) {
3727 *result
= mono_class_has_parent (oklass
, klass
);
3731 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3733 /* interface_offsets might not be set for dynamic classes */
3734 if (mono_class_get_ref_info_handle (oklass
) && !m_class_get_interface_bitmap (oklass
)) {
3736 * oklass might be a generic type parameter but they have
3737 * interface_offsets set.
3739 gboolean assign_result
= mono_reflection_call_is_assignable_to (oklass
, klass
, error
);
3740 return_if_nok (error
);
3741 *result
= assign_result
;
3744 if (!m_class_get_interface_bitmap (oklass
)) {
3745 /* Happens with generic instances of not-yet created dynamic types */
3749 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, m_class_get_interface_id (klass
))) {
3754 if (m_class_is_array_special_interface (klass
) && m_class_get_rank (oklass
) == 1) {
3755 if (mono_class_is_gtd (klass
)) {
3756 /* klass is an array special gtd like
3757 * IList`1<>, and oklass is X[] for some X.
3758 * Moreover we know that X isn't !0 (the gparam
3759 * of IList`1) because in that case we would
3760 * have returned TRUE for
3761 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
3766 // FIXME: IEnumerator`1 should not be an array special interface.
3767 // The correct fix is to make
3768 // ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
3769 // return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
3770 // and to stop marking IEnumerable`1 as an array_special_interface.
3771 if (mono_class_get_generic_type_definition (klass
) == mono_defaults
.generic_ienumerator_class
) {
3776 //XXX we could offset this by having the cast target computed at JIT time
3777 //XXX we could go even further and emit a wrapper that would do the extra type check
3778 MonoClass
*iface_klass
= mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
3779 MonoClass
*obj_klass
= m_class_get_cast_class (oklass
); //This gets us the cast class of element type of the array
3781 // 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
3782 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
3783 if (!mono_class_is_nullable (iface_klass
)) {
3784 if (m_class_is_valuetype (iface_klass
))
3785 iface_klass
= m_class_get_cast_class (iface_klass
);
3787 //array covariant casts only operates on scalar to scalar
3788 //This is so int[] can't be casted to IComparable<int>[]
3789 if (!(m_class_is_valuetype (obj_klass
) && !m_class_is_valuetype (iface_klass
)) && mono_class_is_assignable_from_internal (iface_klass
, obj_klass
)) {
3796 if (mono_class_has_variant_generic_params (klass
)) {
3798 mono_class_setup_interfaces (oklass
, error
);
3799 return_if_nok (error
);
3801 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
3802 for (i
= 0; i
< m_class_get_interface_offsets_count (oklass
); ++i
) {
3803 MonoClass
*iface
= m_class_get_interfaces_packed (oklass
) [i
];
3805 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
)) {
3814 } else if (m_class_is_delegate (klass
)) {
3815 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
)) {
3819 } else if (m_class_get_rank (klass
)) {
3820 MonoClass
*eclass
, *eoclass
;
3822 if (m_class_get_rank (oklass
) != m_class_get_rank (klass
)) {
3827 /* vectors vs. one dimensional arrays */
3828 if (oklass_byval_arg
->type
!= klass_byval_arg
->type
) {
3833 eclass
= m_class_get_cast_class (klass
);
3834 eoclass
= m_class_get_cast_class (oklass
);
3837 * a is b does not imply a[] is b[] when a is a valuetype, and
3838 * b is a reference type.
3841 if (m_class_is_valuetype (eoclass
)) {
3842 if ((eclass
== mono_defaults
.enum_class
) ||
3843 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
3844 (!m_class_is_valuetype (eclass
))) {
3851 * a is b does not imply a[] is b[] in the case where b is an interface and
3852 * a is a generic parameter, unless a has an additional class constraint.
3856 * class G<T> where T : I {}
3857 * class H<U> where U : class, I {}
3859 * public static void Main() {
3860 * var t = typeof(G<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3861 * var i = typeof(I).MakeArrayType();
3862 * var u = typeof(H<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3863 * Console.WriteLine("I[] assignable from T[] ? {0}", i.IsAssignableFrom(t));
3864 * Console.WriteLine("I[] assignable from U[] ? {0}", i.IsAssignableFrom(u));
3868 * This should print:
3869 * I[] assignable from T[] ? False
3870 * I[] assignable from U[] ? True
3873 if (MONO_CLASS_IS_INTERFACE_INTERNAL (eclass
)) {
3874 MonoType
*eoclass_byval_arg
= m_class_get_byval_arg (eoclass
);
3875 if (mono_type_is_generic_argument (eoclass_byval_arg
)) {
3876 MonoGenericParam
*eoparam
= eoclass_byval_arg
->data
.generic_param
;
3877 MonoGenericParamInfo
*eoinfo
= mono_generic_param_info (eoparam
);
3878 int eomask
= eoinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3879 // check for class constraint
3880 if ((eomask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0) {
3887 if (mono_class_is_nullable (eclass
) ^ mono_class_is_nullable (eoclass
)) {
3892 mono_class_is_assignable_from_checked (eclass
, eoclass
, result
, error
);
3894 } else if (mono_class_is_nullable (klass
)) {
3895 if (mono_class_is_nullable (oklass
))
3896 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), m_class_get_cast_class (oklass
), result
, error
);
3898 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), oklass
, result
, error
);
3900 } else if (klass
== mono_defaults
.object_class
) {
3901 if (m_class_get_class_kind (oklass
) == MONO_CLASS_POINTER
)
3908 *result
= mono_class_has_parent (oklass
, klass
);
3911 /*Check if @oklass is variant compatible with @klass.*/
3913 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
3916 MonoType
**klass_argv
, **oklass_argv
;
3917 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3918 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3920 /*Viable candidates are instances of the same generic interface*/
3921 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3924 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3925 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3927 for (j
= 0; j
< container
->type_argc
; ++j
) {
3928 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3929 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3931 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
))
3935 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3936 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3938 if (param1_class
!= param2_class
) {
3939 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3940 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
3942 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3943 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
3951 /*Check if @candidate implements the interface @target*/
3953 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
3957 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
3959 if (is_variant
&& MONO_CLASS_IS_INTERFACE_INTERNAL (candidate
)) {
3960 if (mono_class_is_variant_compatible_slow (target
, candidate
))
3965 if (candidate
== target
)
3968 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3969 if (image_is_dynamic (m_class_get_image (candidate
)) && !m_class_was_typebuilder (candidate
)) {
3970 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info_raw (candidate
); /* FIXME use handles */
3972 if (tb
&& tb
->interfaces
) {
3973 for (j
= mono_array_length_internal (tb
->interfaces
) - 1; j
>= 0; --j
) {
3974 MonoReflectionType
*iface
= mono_array_get_internal (tb
->interfaces
, MonoReflectionType
*, j
);
3975 MonoClass
*iface_class
;
3977 /* we can't realize the type here since it can do pretty much anything. */
3980 iface_class
= mono_class_from_mono_type_internal (iface
->type
);
3981 if (iface_class
== target
)
3983 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
3985 if (mono_class_implement_interface_slow (target
, iface_class
))
3990 /*setup_interfaces don't mono_class_init_internal anything*/
3991 /*FIXME this doesn't handle primitive type arrays.
3992 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3993 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3995 mono_class_setup_interfaces (candidate
, error
);
3996 if (!is_ok (error
)) {
3997 mono_error_cleanup (error
);
4001 int candidate_interface_count
= m_class_get_interface_count (candidate
);
4002 MonoClass
**candidate_interfaces
= m_class_get_interfaces (candidate
);
4003 for (i
= 0; i
< candidate_interface_count
; ++i
) {
4004 if (candidate_interfaces
[i
] == target
)
4007 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate_interfaces
[i
]))
4010 if (mono_class_implement_interface_slow (target
, candidate_interfaces
[i
]))
4014 candidate
= m_class_get_parent (candidate
);
4015 } while (candidate
);
4021 * Check if @oklass can be assigned to @klass.
4022 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
4025 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
4027 if (candidate
== target
)
4029 if (target
== mono_defaults
.object_class
)
4032 if (mono_class_has_parent (candidate
, target
))
4035 /*If target is not an interface there is no need to check them.*/
4036 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target
))
4037 return mono_class_implement_interface_slow (target
, candidate
);
4039 if (m_class_is_delegate (target
) && mono_class_has_variant_generic_params (target
))
4040 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
4042 if (m_class_get_rank (target
)) {
4043 MonoClass
*eclass
, *eoclass
;
4045 if (m_class_get_rank (target
) != m_class_get_rank (candidate
))
4048 /* vectors vs. one dimensional arrays */
4049 if (m_class_get_byval_arg (target
)->type
!= m_class_get_byval_arg (candidate
)->type
)
4052 eclass
= m_class_get_cast_class (target
);
4053 eoclass
= m_class_get_cast_class (candidate
);
4056 * a is b does not imply a[] is b[] when a is a valuetype, and
4057 * b is a reference type.
4060 if (m_class_is_valuetype (eoclass
)) {
4061 if ((eclass
== mono_defaults
.enum_class
) ||
4062 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
4063 (eclass
== mono_defaults
.object_class
))
4067 return mono_class_is_assignable_from_slow (eclass
, eoclass
);
4069 /*FIXME properly handle nullables */
4070 /*FIXME properly handle (M)VAR */
4075 * mono_generic_param_get_base_type:
4077 * Return the base type of the given generic parameter from its constraints.
4079 * Could be another generic parameter, or it could be Object or ValueType.
4082 mono_generic_param_get_base_type (MonoClass
*klass
)
4084 MonoType
*type
= m_class_get_byval_arg (klass
);
4085 g_assert (mono_type_is_generic_argument (type
));
4087 MonoGenericParam
*gparam
= type
->data
.generic_param
;
4089 g_assert (gparam
->owner
&& !gparam
->owner
->is_anonymous
);
4091 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
4093 MonoClass
*base_class
= mono_defaults
.object_class
;
4097 for (i
= 0; constraints
[i
]; ++i
) {
4098 MonoClass
*constraint
= constraints
[i
];
4100 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint
))
4103 MonoType
*constraint_type
= m_class_get_byval_arg (constraint
);
4104 if (mono_type_is_generic_argument (constraint_type
)) {
4105 MonoGenericParam
*constraint_param
= constraint_type
->data
.generic_param
;
4106 MonoGenericParamInfo
*constraint_info
= mono_generic_param_info (constraint_param
);
4107 if ((constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0 &&
4108 (constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) == 0)
4112 base_class
= constraint
;
4117 if (base_class
== mono_defaults
.object_class
)
4119 MonoGenericParamInfo
*gparam_info
= mono_generic_param_info (gparam
);
4120 if ((gparam_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0) {
4121 base_class
= mono_class_get_valuetype_class ();
4129 * mono_class_get_cctor:
4130 * \param klass A MonoClass pointer
4132 * \returns The static constructor of \p klass if it exists, NULL otherwise.
4135 mono_class_get_cctor (MonoClass
*klass
)
4137 MonoMethod
*result
= NULL
;
4139 MonoCachedClassInfo cached_info
;
4141 if (image_is_dynamic (m_class_get_image (klass
))) {
4143 * has_cctor is not set for these classes because mono_class_init_internal () is
4146 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4147 mono_error_assert_msg_ok (error
, "Could not lookup class cctor in dynamic image");
4151 mono_class_init_internal (klass
);
4153 if (!m_class_has_cctor (klass
))
4156 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
4157 result
= mono_class_get_inflated_method (klass
, mono_class_get_cctor (mono_class_get_generic_class (klass
)->container_class
), error
);
4158 mono_error_assert_msg_ok (error
, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
4162 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4163 result
= mono_get_method_checked (m_class_get_image (klass
), cached_info
.cctor_token
, klass
, NULL
, error
);
4164 mono_error_assert_msg_ok (error
, "Could not lookup class cctor from cached metadata");
4168 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4169 mono_error_assert_msg_ok (error
, "Could not lookup class cctor");
4174 * mono_class_get_finalizer:
4175 * \param klass: The MonoClass pointer
4177 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
4180 mono_class_get_finalizer (MonoClass
*klass
)
4182 MonoCachedClassInfo cached_info
;
4184 if (!m_class_is_inited (klass
))
4185 mono_class_init_internal (klass
);
4186 if (!mono_class_has_finalizer (klass
))
4189 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4191 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, error
);
4192 mono_error_assert_msg_ok (error
, "Could not lookup finalizer from cached metadata");
4195 mono_class_setup_vtable (klass
);
4196 return m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
4201 * mono_class_needs_cctor_run:
4202 * \param klass the MonoClass pointer
4203 * \param caller a MonoMethod describing the caller
4205 * Determines whenever the class has a static constructor and whenever it
4206 * needs to be called when executing CALLER.
4209 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
4213 method
= mono_class_get_cctor (klass
);
4215 return (method
== caller
) ? FALSE
: TRUE
;
4221 * mono_class_array_element_size:
4224 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4227 mono_class_array_element_size (MonoClass
*klass
)
4229 MonoType
*type
= m_class_get_byval_arg (klass
);
4232 switch (type
->type
) {
4235 case MONO_TYPE_BOOLEAN
:
4239 case MONO_TYPE_CHAR
:
4248 case MONO_TYPE_CLASS
:
4249 case MONO_TYPE_STRING
:
4250 case MONO_TYPE_OBJECT
:
4251 case MONO_TYPE_SZARRAY
:
4252 case MONO_TYPE_ARRAY
:
4253 return TARGET_SIZEOF_VOID_P
;
4258 case MONO_TYPE_VALUETYPE
:
4259 if (m_class_is_enumtype (type
->data
.klass
)) {
4260 type
= mono_class_enum_basetype_internal (type
->data
.klass
);
4261 klass
= m_class_get_element_class (klass
);
4264 return mono_class_value_size (klass
, NULL
);
4265 case MONO_TYPE_GENERICINST
:
4266 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
4269 case MONO_TYPE_MVAR
: {
4272 return mono_type_size (type
, &align
);
4274 case MONO_TYPE_VOID
:
4278 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
4284 * mono_array_element_size:
4285 * \param ac pointer to a \c MonoArrayClass
4287 * \returns The size of single array element.
4289 * LOCKING: Acquires the loader lock.
4292 mono_array_element_size (MonoClass
*ac
)
4294 g_assert (m_class_get_rank (ac
));
4295 if (G_UNLIKELY (!m_class_is_size_inited (ac
))) {
4296 mono_class_setup_fields (ac
);
4298 return m_class_get_sizes (ac
).element_size
;
4305 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4306 MonoGenericContext
*context
)
4309 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, error
);
4310 mono_error_assert_ok (error
);
4315 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4316 MonoGenericContext
*context
, MonoError
*error
)
4320 if (image_is_dynamic (image
)) {
4321 MonoClass
*tmp_handle_class
;
4322 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
, error
);
4324 mono_error_assert_ok (error
);
4325 g_assert (tmp_handle_class
);
4327 *handle_class
= tmp_handle_class
;
4329 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
4330 return m_class_get_byval_arg ((MonoClass
*)obj
);
4335 switch (token
& 0xff000000) {
4336 case MONO_TOKEN_TYPE_DEF
:
4337 case MONO_TOKEN_TYPE_REF
:
4338 case MONO_TOKEN_TYPE_SPEC
: {
4341 *handle_class
= mono_defaults
.typehandle_class
;
4342 type
= mono_type_get_checked (image
, token
, context
, error
);
4346 mono_class_init_internal (mono_class_from_mono_type_internal (type
));
4347 /* We return a MonoType* as handle */
4350 case MONO_TOKEN_FIELD_DEF
: {
4352 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
4354 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4358 *handle_class
= mono_defaults
.fieldhandle_class
;
4359 klass
= mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
4363 mono_class_init_internal (klass
);
4364 return mono_class_get_field (klass
, token
);
4366 case MONO_TOKEN_METHOD_DEF
:
4367 case MONO_TOKEN_METHOD_SPEC
: {
4369 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4371 *handle_class
= mono_defaults
.methodhandle_class
;
4377 case MONO_TOKEN_MEMBER_REF
: {
4378 guint32 cols
[MONO_MEMBERREF_SIZE
];
4380 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
4381 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
4382 mono_metadata_decode_blob_size (sig
, &sig
);
4383 if (*sig
== 0x6) { /* it's a field */
4385 MonoClassField
*field
;
4386 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
4388 *handle_class
= mono_defaults
.fieldhandle_class
;
4392 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4394 *handle_class
= mono_defaults
.methodhandle_class
;
4399 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4405 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
, MonoError
*error
)
4407 MonoClass
*handle_class
;
4409 return mono_reflection_lookup_dynamic_token (image
, token
, TRUE
, &handle_class
, context
, error
);
4413 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
4415 return mono_reflection_lookup_dynamic_token (image
, token
, valid_token
, handle_class
, context
, error
);
4418 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
4421 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
4423 get_cached_class_info
= func
;
4427 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
4429 if (!get_cached_class_info
)
4432 return get_cached_class_info (klass
, res
);
4436 mono_install_get_class_from_name (MonoGetClassFromName func
)
4438 get_class_from_name
= func
;
4442 * mono_class_get_image:
4444 * Use this method to get the \c MonoImage* where this class came from.
4446 * \returns The image where this class is defined.
4449 mono_class_get_image (MonoClass
*klass
)
4451 return m_class_get_image (klass
);
4455 * mono_class_get_element_class:
4456 * \param klass the \c MonoClass to act on
4458 * Use this function to get the element class of an array.
4460 * \returns The element class of an array.
4463 mono_class_get_element_class (MonoClass
*klass
)
4466 MONO_ENTER_GC_UNSAFE
;
4467 result
= m_class_get_element_class (klass
);
4468 MONO_EXIT_GC_UNSAFE
;
4473 * mono_class_is_valuetype:
4474 * \param klass the \c MonoClass to act on
4476 * Use this method to determine if the provided \c MonoClass* represents a value type,
4477 * or a reference type.
4479 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4482 mono_class_is_valuetype (MonoClass
*klass
)
4485 MONO_ENTER_GC_UNSAFE
;
4486 result
= m_class_is_valuetype (klass
);
4487 MONO_EXIT_GC_UNSAFE
;
4492 * mono_class_is_enum:
4493 * \param klass the \c MonoClass to act on
4495 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4497 * \returns TRUE if the \c MonoClass represents an enumeration.
4500 mono_class_is_enum (MonoClass
*klass
)
4503 MONO_ENTER_GC_UNSAFE
;
4504 result
= m_class_is_enumtype (klass
);
4505 MONO_EXIT_GC_UNSAFE
;
4510 * mono_class_enum_basetype_internal:
4511 * \param klass the \c MonoClass to act on
4513 * Use this function to get the underlying type for an enumeration value.
4515 * \returns The underlying type representation for an enumeration.
4518 mono_class_enum_basetype_internal (MonoClass
*klass
)
4520 if (m_class_get_element_class (klass
) == klass
)
4521 /* SRE or broken types */
4523 return m_class_get_byval_arg (m_class_get_element_class (klass
));
4527 * mono_class_enum_basetype:
4528 * \param klass the \c MonoClass to act on
4530 * Use this function to get the underlying type for an enumeration value.
4532 * \returns The underlying type representation for an enumeration.
4535 mono_class_enum_basetype (MonoClass
*klass
)
4538 MONO_ENTER_GC_UNSAFE
;
4539 res
= mono_class_enum_basetype_internal (klass
);
4540 MONO_EXIT_GC_UNSAFE
;
4545 * mono_class_get_parent
4546 * \param klass the \c MonoClass to act on
4548 * \returns The parent class for this class.
4551 mono_class_get_parent (MonoClass
*klass
)
4554 MONO_ENTER_GC_UNSAFE
;
4555 result
= m_class_get_parent (klass
);
4556 MONO_EXIT_GC_UNSAFE
;
4561 * mono_class_get_nesting_type:
4562 * \param klass the \c MonoClass to act on
4564 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4566 * If the return is NULL, this indicates that this class is not nested.
4568 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4571 mono_class_get_nesting_type (MonoClass
*klass
)
4573 return m_class_get_nested_in (klass
);
4577 * mono_class_get_rank:
4578 * \param klass the MonoClass to act on
4580 * \returns The rank for the array (the number of dimensions).
4583 mono_class_get_rank (MonoClass
*klass
)
4585 return m_class_get_rank (klass
);
4589 * mono_class_get_name
4590 * \param klass the \c MonoClass to act on
4592 * \returns The name of the class.
4595 mono_class_get_name (MonoClass
*klass
)
4598 MONO_ENTER_GC_UNSAFE
;
4599 result
= m_class_get_name (klass
);
4600 MONO_EXIT_GC_UNSAFE
;
4605 * mono_class_get_namespace:
4606 * \param klass the \c MonoClass to act on
4608 * \returns The namespace of the class.
4611 mono_class_get_namespace (MonoClass
*klass
)
4614 MONO_ENTER_GC_UNSAFE
;
4615 result
= m_class_get_name_space (klass
);
4616 MONO_EXIT_GC_UNSAFE
;
4621 * mono_class_get_type:
4622 * \param klass the \c MonoClass to act on
4624 * This method returns the internal \c MonoType representation for the class.
4626 * \returns The \c MonoType from the class.
4629 mono_class_get_type (MonoClass
*klass
)
4631 return m_class_get_byval_arg (klass
);
4635 * mono_class_get_type_token:
4636 * \param klass the \c MonoClass to act on
4638 * This method returns type token for the class.
4640 * \returns The type token for the class.
4643 mono_class_get_type_token (MonoClass
*klass
)
4645 return m_class_get_type_token (klass
);
4649 * mono_class_get_byref_type:
4650 * \param klass the \c MonoClass to act on
4655 mono_class_get_byref_type (MonoClass
*klass
)
4657 return m_class_get_this_arg (klass
);
4661 * mono_class_num_fields:
4662 * \param klass the \c MonoClass to act on
4664 * \returns The number of static and instance fields in the class.
4667 mono_class_num_fields (MonoClass
*klass
)
4669 return mono_class_get_field_count (klass
);
4673 * mono_class_num_methods:
4674 * \param klass the \c MonoClass to act on
4676 * \returns The number of methods in the class.
4679 mono_class_num_methods (MonoClass
*klass
)
4681 return mono_class_get_method_count (klass
);
4685 * mono_class_num_properties
4686 * \param klass the \c MonoClass to act on
4688 * \returns The number of properties in the class.
4691 mono_class_num_properties (MonoClass
*klass
)
4693 mono_class_setup_properties (klass
);
4695 return mono_class_get_property_info (klass
)->count
;
4699 * mono_class_num_events:
4700 * \param klass the \c MonoClass to act on
4702 * \returns The number of events in the class.
4705 mono_class_num_events (MonoClass
*klass
)
4707 mono_class_setup_events (klass
);
4709 return mono_class_get_event_info (klass
)->count
;
4713 * mono_class_get_fields:
4714 * \param klass the \c MonoClass to act on
4716 * This routine is an iterator routine for retrieving the fields in a class.
4718 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4719 * iterate over all of the elements. When no more values are
4720 * available, the return value is NULL.
4722 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4725 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
4727 MonoClassField
*result
;
4728 MONO_ENTER_GC_UNSAFE
;
4729 result
= mono_class_get_fields_internal (klass
, iter
);
4730 MONO_EXIT_GC_UNSAFE
;
4735 mono_class_get_fields_internal (MonoClass
*klass
, gpointer
*iter
)
4737 MonoClassField
* field
;
4741 mono_class_setup_fields (klass
);
4742 if (mono_class_has_failure (klass
))
4744 /* start from the first */
4745 if (mono_class_get_field_count (klass
)) {
4746 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
4747 *iter
= &klass_fields
[0];
4748 return &klass_fields
[0];
4754 field
= (MonoClassField
*)*iter
;
4756 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
4764 * mono_class_get_methods:
4765 * \param klass the \c MonoClass to act on
4767 * This routine is an iterator routine for retrieving the fields in a class.
4769 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4770 * iterate over all of the elements. When no more values are
4771 * available, the return value is NULL.
4773 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4776 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
4778 MonoMethod
** method
;
4782 mono_class_setup_methods (klass
);
4784 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
4786 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4787 * FIXME we should better report this error to the caller
4791 /* start from the first */
4792 if (mono_class_get_method_count (klass
)) {
4793 *iter
= &klass_methods
[0];
4794 return klass_methods
[0];
4800 method
= (MonoMethod
**)*iter
;
4802 if (method
< &m_class_get_methods (klass
) [mono_class_get_method_count (klass
)]) {
4810 * mono_class_get_properties:
4811 * \param klass the \c MonoClass to act on
4813 * This routine is an iterator routine for retrieving the properties in a class.
4815 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4816 * iterate over all of the elements. When no more values are
4817 * available, the return value is NULL.
4819 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4822 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
4824 MonoProperty
* property
;
4828 mono_class_setup_properties (klass
);
4829 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4830 /* start from the first */
4832 *iter
= &info
->properties
[0];
4833 return (MonoProperty
*)*iter
;
4839 property
= (MonoProperty
*)*iter
;
4841 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4842 if (property
< &info
->properties
[info
->count
]) {
4844 return (MonoProperty
*)*iter
;
4850 * mono_class_get_events:
4851 * \param klass the \c MonoClass to act on
4853 * This routine is an iterator routine for retrieving the properties in a class.
4855 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4856 * iterate over all of the elements. When no more values are
4857 * available, the return value is NULL.
4859 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4862 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
4868 mono_class_setup_events (klass
);
4869 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4870 /* start from the first */
4872 *iter
= &info
->events
[0];
4873 return (MonoEvent
*)*iter
;
4879 event
= (MonoEvent
*)*iter
;
4881 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4882 if (event
< &info
->events
[info
->count
]) {
4884 return (MonoEvent
*)*iter
;
4890 * mono_class_get_interfaces
4891 * \param klass the \c MonoClass to act on
4893 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4895 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4896 * iterate over all of the elements. When no more values are
4897 * available, the return value is NULL.
4899 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4902 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
4909 if (!m_class_is_inited (klass
))
4910 mono_class_init_internal (klass
);
4911 if (!m_class_is_interfaces_inited (klass
)) {
4912 mono_class_setup_interfaces (klass
, error
);
4913 if (!is_ok (error
)) {
4914 mono_error_cleanup (error
);
4918 /* start from the first */
4919 if (m_class_get_interface_count (klass
)) {
4920 *iter
= &m_class_get_interfaces (klass
) [0];
4921 return m_class_get_interfaces (klass
) [0];
4927 iface
= (MonoClass
**)*iter
;
4929 if (iface
< &m_class_get_interfaces (klass
) [m_class_get_interface_count (klass
)]) {
4937 * mono_class_get_nested_types
4938 * \param klass the \c MonoClass to act on
4940 * This routine is an iterator routine for retrieving the nested types of a class.
4941 * This works only if \p klass is non-generic, or a generic type definition.
4943 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4944 * iterate over all of the elements. When no more values are
4945 * available, the return value is NULL.
4947 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4950 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
4956 if (!m_class_is_nested_classes_inited (klass
))
4957 mono_class_setup_nested_types (klass
);
4960 GList
*nested_classes
= mono_class_get_nested_classes_property (klass
);
4961 /* start from the first */
4962 if (nested_classes
) {
4963 *iter
= nested_classes
;
4964 return (MonoClass
*)nested_classes
->data
;
4966 /* no nested types */
4970 item
= (GList
*)*iter
;
4974 return (MonoClass
*)item
->data
;
4981 * mono_class_is_delegate
4982 * \param klass the \c MonoClass to act on
4984 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4987 mono_class_is_delegate (MonoClass
*klass
)
4990 MONO_ENTER_GC_UNSAFE
;
4991 result
= m_class_is_delegate (klass
);
4992 MONO_EXIT_GC_UNSAFE
;
4997 * mono_class_implements_interface
4998 * \param klass The MonoClass to act on
4999 * \param interface The interface to check if \p klass implements.
5001 * \returns TRUE if \p klass implements \p interface.
5004 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
5006 return mono_class_is_assignable_from_internal (iface
, klass
);
5010 class_implements_interface_ignore_generics (MonoClass
* klass
, MonoClass
* iface
)
5014 if (mono_class_is_ginst (iface
))
5015 iface
= mono_class_get_generic_type_definition (iface
);
5016 while (klass
!= NULL
) {
5017 if (mono_class_is_assignable_from_internal (iface
, klass
))
5019 mono_class_setup_interfaces (klass
, error
);
5020 if (!is_ok (error
)) {
5021 mono_error_cleanup (error
);
5024 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
5025 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
5026 MonoClass
*ic
= klass_interfaces
[i
];
5027 if (mono_class_is_ginst (ic
))
5028 ic
= mono_class_get_generic_type_definition (ic
);
5033 klass
= m_class_get_parent (klass
);
5040 * mono_field_get_name:
5041 * \param field the \c MonoClassField to act on
5043 * \returns The name of the field.
5046 mono_field_get_name (MonoClassField
*field
)
5052 * mono_field_get_type_internal:
5053 * \param field the \c MonoClassField to act on
5054 * \returns \c MonoType of the field.
5057 mono_field_get_type_internal (MonoClassField
*field
)
5059 MonoType
*type
= field
->type
;
5064 type
= mono_field_get_type_checked (field
, error
);
5065 if (!is_ok (error
)) {
5066 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (error
));
5067 mono_error_cleanup (error
);
5073 * mono_field_get_type:
5074 * \param field the \c MonoClassField to act on
5075 * \returns \c MonoType of the field.
5078 mono_field_get_type (MonoClassField
*field
)
5080 MonoType
*type
= field
->type
;
5084 MONO_ENTER_GC_UNSAFE
;
5085 type
= mono_field_get_type_internal (field
);
5086 MONO_EXIT_GC_UNSAFE
;
5091 * mono_field_get_type_checked:
5092 * \param field the \c MonoClassField to act on
5093 * \param error used to return any error found while retrieving \p field type
5095 * \returns \c MonoType of the field.
5098 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
5101 MonoType
*type
= field
->type
;
5104 mono_field_resolve_type (field
, error
);
5109 * mono_field_get_parent:
5110 * \param field the \c MonoClassField to act on
5112 * \returns \c MonoClass where the field was defined.
5115 mono_field_get_parent (MonoClassField
*field
)
5117 return field
->parent
;
5121 * mono_field_get_flags;
5122 * \param field the \c MonoClassField to act on
5124 * The metadata flags for a field are encoded using the
5125 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5127 * \returns The flags for the field.
5130 mono_field_get_flags (MonoClassField
*field
)
5133 return mono_field_resolve_flags (field
);
5134 return field
->type
->attrs
;
5138 * mono_field_get_offset:
5139 * \param field the \c MonoClassField to act on
5141 * \returns The field offset.
5144 mono_field_get_offset (MonoClassField
*field
)
5146 mono_class_setup_fields(field
->parent
);
5147 return field
->offset
;
5151 mono_field_get_rva (MonoClassField
*field
)
5155 MonoClass
*klass
= field
->parent
;
5156 MonoFieldDefaultValue
*def_values
;
5158 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
5160 def_values
= mono_class_get_field_def_values (klass
);
5162 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
5164 mono_class_set_field_def_values (klass
, def_values
);
5167 field_index
= mono_field_get_index (field
);
5169 if (!def_values
[field_index
].data
&& !image_is_dynamic (m_class_get_image (klass
))) {
5170 int first_field_idx
= mono_class_get_first_field_idx (klass
);
5171 mono_metadata_field_info (m_class_get_image (field
->parent
), first_field_idx
+ field_index
, NULL
, &rva
, NULL
);
5173 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), m_class_get_name (field
->parent
));
5174 def_values
[field_index
].data
= mono_image_rva_map (m_class_get_image (field
->parent
), rva
);
5177 return def_values
[field_index
].data
;
5181 * mono_field_get_data:
5182 * \param field the \c MonoClassField to act on
5184 * \returns A pointer to the metadata constant value or to the field
5185 * data if it has an RVA flag.
5188 mono_field_get_data (MonoClassField
*field
)
5190 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
5191 MonoTypeEnum def_type
;
5193 return mono_class_get_field_default_value (field
, &def_type
);
5194 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
5195 return mono_field_get_rva (field
);
5202 * mono_property_get_name:
5203 * \param prop the \c MonoProperty to act on
5204 * \returns The name of the property
5207 mono_property_get_name (MonoProperty
*prop
)
5213 * mono_property_get_set_method
5214 * \param prop the \c MonoProperty to act on.
5215 * \returns The setter method of the property, a \c MonoMethod.
5218 mono_property_get_set_method (MonoProperty
*prop
)
5224 * mono_property_get_get_method
5225 * \param prop the MonoProperty to act on.
5226 * \returns The getter method of the property (A \c MonoMethod)
5229 mono_property_get_get_method (MonoProperty
*prop
)
5235 * mono_property_get_parent:
5236 * \param prop the \c MonoProperty to act on.
5237 * \returns The \c MonoClass where the property was defined.
5240 mono_property_get_parent (MonoProperty
*prop
)
5242 return prop
->parent
;
5246 * mono_property_get_flags:
5247 * \param prop the \c MonoProperty to act on.
5249 * The metadata flags for a property are encoded using the
5250 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5252 * \returns The flags for the property.
5255 mono_property_get_flags (MonoProperty
*prop
)
5261 * mono_event_get_name:
5262 * \param event the MonoEvent to act on
5263 * \returns The name of the event.
5266 mono_event_get_name (MonoEvent
*event
)
5272 * mono_event_get_add_method:
5273 * \param event The \c MonoEvent to act on.
5274 * \returns The \c add method for the event, a \c MonoMethod.
5277 mono_event_get_add_method (MonoEvent
*event
)
5283 * mono_event_get_remove_method:
5284 * \param event The \c MonoEvent to act on.
5285 * \returns The \c remove method for the event, a \c MonoMethod.
5288 mono_event_get_remove_method (MonoEvent
*event
)
5290 return event
->remove
;
5294 * mono_event_get_raise_method:
5295 * \param event The \c MonoEvent to act on.
5296 * \returns The \c raise method for the event, a \c MonoMethod.
5299 mono_event_get_raise_method (MonoEvent
*event
)
5301 return event
->raise
;
5305 * mono_event_get_parent:
5306 * \param event the MonoEvent to act on.
5307 * \returns The \c MonoClass where the event is defined.
5310 mono_event_get_parent (MonoEvent
*event
)
5312 return event
->parent
;
5316 * mono_event_get_flags
5317 * \param event the \c MonoEvent to act on.
5319 * The metadata flags for an event are encoded using the
5320 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5322 * \returns The flags for the event.
5325 mono_event_get_flags (MonoEvent
*event
)
5327 return event
->attrs
;
5331 * mono_class_get_method_from_name:
5332 * \param klass where to look for the method
5333 * \param name name of the method
5334 * \param param_count number of parameters. -1 for any number.
5336 * Obtains a \c MonoMethod with a given name and number of parameters.
5337 * It only works if there are no multiple signatures for any given method name.
5340 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
5343 MONO_ENTER_GC_UNSAFE
;
5345 result
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, 0, error
);
5346 mono_error_cleanup (error
);
5347 MONO_EXIT_GC_UNSAFE
;
5352 mono_find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5354 MonoImage
*klass_image
= m_class_get_image (klass
);
5355 MonoMethod
*res
= NULL
;
5358 /* Search directly in the metadata to avoid calling setup_methods () */
5359 int first_idx
= mono_class_get_first_method_idx (klass
);
5360 int mcount
= mono_class_get_method_count (klass
);
5361 for (i
= 0; i
< mcount
; ++i
) {
5363 guint32 cols
[MONO_METHOD_SIZE
];
5365 MonoMethodSignature
*sig
;
5367 /* first_idx points into the methodptr table */
5368 mono_metadata_decode_table_row (klass_image
, MONO_TABLE_METHOD
, first_idx
+ i
, cols
, MONO_METHOD_SIZE
);
5370 if (!strcmp (mono_metadata_string_heap (klass_image
, cols
[MONO_METHOD_NAME
]), name
)) {
5371 method
= mono_get_method_checked (klass_image
, MONO_TOKEN_METHOD_DEF
| (first_idx
+ i
+ 1), klass
, NULL
, error
);
5373 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5376 if (param_count
== -1) {
5380 sig
= mono_method_signature_checked (method
, error
);
5382 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5385 if (sig
->param_count
== param_count
) {
5396 * mono_class_get_method_from_name_flags:
5397 * \param klass where to look for the method
5398 * \param name_space name of the method
5399 * \param param_count number of parameters. -1 for any number.
5400 * \param flags flags which must be set in the method
5402 * Obtains a \c MonoMethod with a given name and number of parameters.
5403 * It only works if there are no multiple signatures for any given method name.
5406 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5409 MONO_ENTER_GC_UNSAFE
;
5411 method
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, flags
, error
);
5412 mono_error_cleanup (error
);
5413 MONO_EXIT_GC_UNSAFE
;
5418 * mono_class_get_method_from_name_checked:
5419 * \param klass where to look for the method
5420 * \param name_space name of the method
5421 * \param param_count number of parameters. -1 for any number.
5422 * \param flags flags which must be set in the method
5425 * Obtains a \c MonoMethod with a given name and number of parameters.
5426 * It only works if there are no multiple signatures for any given method name.
5429 mono_class_get_method_from_name_checked (MonoClass
*klass
, const char *name
,
5430 int param_count
, int flags
, MonoError
*error
)
5432 MonoMethod
*res
= NULL
;
5435 mono_class_init_internal (klass
);
5437 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
5438 res
= mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass
)->container_class
, name
, param_count
, flags
, error
);
5441 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), error
);
5446 if (m_class_get_methods (klass
) || !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
5447 mono_class_setup_methods (klass
);
5449 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5450 See mono/tests/array_load_exception.il
5451 FIXME we should better report this error to the caller
5453 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
5456 int mcount
= mono_class_get_method_count (klass
);
5457 for (i
= 0; i
< mcount
; ++i
) {
5458 MonoMethod
*method
= klass_methods
[i
];
5460 if (method
->name
[0] == name
[0] &&
5461 !strcmp (name
, method
->name
) &&
5462 (param_count
== -1 || mono_method_signature_internal (method
)->param_count
== param_count
) &&
5463 ((method
->flags
& flags
) == flags
)) {
5470 res
= mono_find_method_in_metadata (klass
, name
, param_count
, flags
);
5477 mono_class_has_failure (const MonoClass
*klass
)
5479 g_assert (klass
!= NULL
);
5480 return m_class_has_failure ((MonoClass
*)klass
) != 0;
5485 * mono_class_set_type_load_failure:
5486 * \param klass class in which the failure was detected
5487 * \param fmt \c printf -style error message string.
5489 * Collect detected failure informaion in the class for later processing.
5490 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5491 * Note that only the first failure is kept.
5493 * LOCKING: Acquires the loader lock.
5495 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5498 mono_class_set_type_load_failure (MonoClass
*klass
, const char * fmt
, ...)
5500 ERROR_DECL (prepare_error
);
5503 if (mono_class_has_failure (klass
))
5506 va_start (args
, fmt
);
5507 mono_error_vset_type_load_class (prepare_error
, klass
, fmt
, args
);
5510 MonoErrorBoxed
*box
= mono_error_box (prepare_error
, m_class_get_image (klass
));
5511 mono_error_cleanup (prepare_error
);
5512 return mono_class_set_failure (klass
, box
);
5516 * mono_class_get_exception_for_failure:
5517 * \param klass class in which the failure was detected
5519 * \returns a constructed MonoException than the caller can then throw
5520 * using mono_raise_exception - or NULL if no failure is present (or
5521 * doesn't result in an exception).
5524 mono_class_get_exception_for_failure (MonoClass
*klass
)
5526 if (!mono_class_has_failure (klass
))
5528 ERROR_DECL (unboxed_error
);
5529 mono_error_set_for_class_failure (unboxed_error
, klass
);
5530 return mono_error_convert_to_exception (unboxed_error
);
5534 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
5536 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
5537 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
5539 if (outer_klass
== inner_klass
)
5541 inner_klass
= m_class_get_nested_in (inner_klass
);
5542 } while (inner_klass
);
5547 mono_class_get_generic_type_definition (MonoClass
*klass
)
5549 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5550 return gklass
? gklass
->container_class
: klass
;
5554 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5556 * Generic instantiations are ignored for all super types of @klass.
5558 * Visibility checks ignoring generic instantiations.
5560 * Class implementing interface visibility checks ignore generic instantiations
5563 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
5566 klass
= mono_class_get_generic_type_definition (klass
);
5567 parent
= mono_class_get_generic_type_definition (parent
);
5568 mono_class_setup_supertypes (klass
);
5570 for (i
= 0; i
< m_class_get_idepth (klass
); ++i
) {
5571 if (parent
== mono_class_get_generic_type_definition (m_class_get_supertypes (klass
) [i
]))
5575 if (MONO_CLASS_IS_INTERFACE_INTERNAL (parent
) && class_implements_interface_ignore_generics (klass
, parent
))
5581 * Subtype can only access parent members with family protection if the site object
5582 * is subclass of Subtype. For example:
5583 * class A { protected int x; }
5585 * void valid_access () {
5589 * void invalid_access () {
5596 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
5598 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5599 /* Can happen with default interface methods */
5600 if (!class_implements_interface_ignore_generics (access_klass
, member_klass
))
5602 } else if (member_klass
!= access_klass
&& MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5603 /* Can happen with default interface methods */
5604 if (!mono_interface_implements_interface (access_klass
, member_klass
))
5607 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
5611 if (context_klass
== NULL
)
5613 /*if access_klass is not member_klass context_klass must be type compat*/
5614 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
5620 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
5623 if (accessing
== accessed
)
5625 if (!accessed
|| !accessing
)
5628 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5629 * anywhere so untrusted friends are not safe to access platform's code internals */
5630 if (mono_security_core_clr_enabled ()) {
5631 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
5635 mono_assembly_load_friends (accessed
);
5636 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
5637 MonoAssemblyName
*friend_
= (MonoAssemblyName
*)tmp
->data
;
5638 /* Be conservative with checks */
5641 if (g_ascii_strcasecmp (accessing
->aname
.name
, friend_
->name
))
5643 if (friend_
->public_key_token
[0]) {
5644 if (!accessing
->aname
.public_key_token
[0])
5646 if (!mono_public_tokens_are_equal (friend_
->public_key_token
, accessing
->aname
.public_key_token
))
5655 * If klass is a generic type or if it is derived from a generic type, return the
5656 * MonoClass of the generic definition
5657 * Returns NULL if not found
5660 get_generic_definition_class (MonoClass
*klass
)
5663 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5664 if (gklass
&& gklass
->container_class
)
5665 return gklass
->container_class
;
5666 klass
= m_class_get_parent (klass
);
5672 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
5675 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
5676 MonoType
*type
= ginst
->type_argv
[i
];
5677 switch (type
->type
) {
5678 case MONO_TYPE_SZARRAY
:
5679 if (!can_access_type (access_klass
, type
->data
.klass
))
5682 case MONO_TYPE_ARRAY
:
5683 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
5687 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
->data
.type
)))
5690 case MONO_TYPE_CLASS
:
5691 case MONO_TYPE_VALUETYPE
:
5692 case MONO_TYPE_GENERICINST
:
5693 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
)))
5703 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
5707 if (access_klass
== member_klass
)
5710 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5711 MonoAssembly
*member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5713 if (access_klass_assembly
&& m_class_get_image (access_klass
)->assembly
->corlib_internal
)
5716 if (m_class_get_element_class (access_klass
) && !m_class_is_enumtype (access_klass
)) {
5717 access_klass
= m_class_get_element_class (access_klass
);
5718 access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5721 if (m_class_get_element_class (member_klass
) && !m_class_is_enumtype (member_klass
)) {
5722 member_klass
= m_class_get_element_class (member_klass
);
5723 member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5726 access_level
= mono_class_get_flags (member_klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5728 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass
)))
5731 if (mono_class_is_ginst (member_klass
) && !can_access_instantiation (access_klass
, mono_class_get_generic_class (member_klass
)->context
.class_inst
))
5734 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
)))
5737 /*Non nested type with nested visibility. We just fail it.*/
5738 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& m_class_get_nested_in (member_klass
) == NULL
)
5741 MonoClass
*member_klass_nested_in
= m_class_get_nested_in (member_klass
);
5742 switch (access_level
) {
5743 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
5744 return can_access_internals (access_klass_assembly
, member_klass_assembly
);
5746 case TYPE_ATTRIBUTE_PUBLIC
:
5749 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
5750 return member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5752 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
5753 return is_nesting_type (member_klass
, access_klass
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5755 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
5756 return mono_class_has_parent_and_ignore_generics (access_klass
, m_class_get_nested_in (member_klass
));
5758 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
5759 return can_access_internals (access_klass_assembly
, member_klass_assembly
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5761 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
5762 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) &&
5763 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5765 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
5766 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) ||
5767 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5772 /* FIXME: check visibility of type, too */
5774 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
5776 MonoClass
*member_generic_def
;
5777 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5778 if (access_klass_assembly
&& access_klass_assembly
->corlib_internal
)
5781 MonoGenericClass
*access_gklass
= mono_class_try_get_generic_class (access_klass
);
5782 if (((access_gklass
&& access_gklass
->container_class
) ||
5783 mono_class_is_gtd (access_klass
)) &&
5784 (member_generic_def
= get_generic_definition_class (member_klass
))) {
5785 MonoClass
*access_container
;
5787 if (mono_class_is_gtd (access_klass
))
5788 access_container
= access_klass
;
5790 access_container
= access_gklass
->container_class
;
5792 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
5796 MonoImage
*member_klass_image
= m_class_get_image (member_klass
);
5797 /* Partition I 8.5.3.2 */
5798 /* the access level values are the same for fields and methods */
5799 switch (access_level
) {
5800 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
5801 /* same compilation unit */
5802 return m_class_get_image (access_klass
) == member_klass_image
;
5803 case FIELD_ATTRIBUTE_PRIVATE
:
5804 return access_klass
== member_klass
;
5805 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
5806 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
5807 can_access_internals (access_klass_assembly
, member_klass_image
->assembly
))
5810 case FIELD_ATTRIBUTE_ASSEMBLY
:
5811 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5812 case FIELD_ATTRIBUTE_FAMILY
:
5813 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5816 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
5817 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5819 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5820 case FIELD_ATTRIBUTE_PUBLIC
:
5827 * mono_method_can_access_field:
5828 * \param method Method that will attempt to access the field
5829 * \param field the field to access
5831 * Used to determine if a method is allowed to access the specified field.
5833 * \returns TRUE if the given \p method is allowed to access the \p field while following
5834 * the accessibility rules of the CLI.
5837 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
5839 /* FIXME: check all overlapping fields */
5840 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5842 MonoClass
*nested
= m_class_get_nested_in (method
->klass
);
5844 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5847 nested
= m_class_get_nested_in (nested
);
5854 mono_method_get_method_definition (MonoMethod
*method
)
5856 while (method
->is_inflated
)
5857 method
= ((MonoMethodInflated
*)method
)->declaring
;
5862 * mono_method_can_access_method:
5863 * \param method Method that will attempt to access the other method
5864 * \param called the method that we want to probe for accessibility.
5866 * Used to determine if the \p method is allowed to access the specified \p called method.
5868 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5869 * the accessibility rules of the CLI.
5872 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
5874 method
= mono_method_get_method_definition (method
);
5875 called
= mono_method_get_method_definition (called
);
5876 return mono_method_can_access_method_full (method
, called
, NULL
);
5880 * mono_method_can_access_method_full:
5881 * @method: The caller method
5882 * @called: The called method
5883 * @context_klass: The static type on stack of the owner @called object used
5885 * This function must be used with instance calls, as they have more strict family accessibility.
5886 * It can be used with static methods, but context_klass should be NULL.
5888 * Returns: TRUE if caller have proper visibility and acessibility to @called
5891 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
5893 /* Wrappers are except from access checks */
5894 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| called
->wrapper_type
!= MONO_WRAPPER_NONE
)
5897 MonoClass
*access_class
= method
->klass
;
5898 MonoClass
*member_class
= called
->klass
;
5899 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5901 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5903 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5906 nested
= m_class_get_nested_in (nested
);
5913 can
= can_access_type (access_class
, member_class
);
5915 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5917 can
= can_access_type (nested
, member_class
);
5920 nested
= m_class_get_nested_in (nested
);
5927 if (called
->is_inflated
) {
5928 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
5929 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
5938 * mono_method_can_access_field_full:
5939 * @method: The caller method
5940 * @field: The accessed field
5941 * @context_klass: The static type on stack of the owner @field object used
5943 * This function must be used with instance fields, as they have more strict family accessibility.
5944 * It can be used with static fields, but context_klass should be NULL.
5946 * Returns: TRUE if caller have proper visibility and acessibility to @field
5949 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
5951 MonoClass
*access_class
= method
->klass
;
5952 MonoClass
*member_class
= field
->parent
;
5953 /* FIXME: check all overlapping fields */
5954 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5956 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5958 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5961 nested
= m_class_get_nested_in (nested
);
5968 can
= can_access_type (access_class
, member_class
);
5970 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5972 can
= can_access_type (nested
, member_class
);
5975 nested
= m_class_get_nested_in (nested
);
5985 * mono_class_can_access_class:
5986 * @source_class: The source class
5987 * @target_class: The accessed class
5989 * This function returns is @target_class is visible to @source_class
5991 * Returns: TRUE if source have proper visibility and acessibility to target
5994 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
5996 return can_access_type (source_class
, target_class
);
6000 * mono_type_is_valid_enum_basetype:
6001 * \param type The MonoType to check
6002 * \returns TRUE if the type can be used as the basetype of an enum
6004 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
6005 switch (type
->type
) {
6008 case MONO_TYPE_BOOLEAN
:
6011 case MONO_TYPE_CHAR
:
6029 * mono_class_is_valid_enum:
6030 * \param klass An enum class to be validated
6032 * This method verify the required properties an enum should have.
6034 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
6035 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
6036 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
6038 * \returns TRUE if the informed enum class is valid
6041 mono_class_is_valid_enum (MonoClass
*klass
)
6043 MonoClassField
* field
;
6044 gpointer iter
= NULL
;
6045 gboolean found_base_field
= FALSE
;
6047 g_assert (m_class_is_enumtype (klass
));
6048 MonoClass
*klass_parent
= m_class_get_parent (klass
);
6049 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
6050 if (!klass_parent
|| strcmp (m_class_get_name (klass_parent
), "Enum") || strcmp (m_class_get_name_space (klass_parent
), "System") ) {
6054 if (!mono_class_is_auto_layout (klass
))
6057 while ((field
= mono_class_get_fields_internal (klass
, &iter
))) {
6058 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
6059 if (found_base_field
)
6061 found_base_field
= TRUE
;
6062 if (!mono_type_is_valid_enum_basetype (field
->type
))
6067 if (!found_base_field
)
6070 if (mono_class_get_method_count (klass
) > 0)
6077 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
6079 return gklass
->context
.class_inst
== mono_class_get_generic_container (gklass
->container_class
)->context
.class_inst
;
6083 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
6085 MonoClass
*klass
= field
->parent
;
6086 MonoImage
*image
= m_class_get_image (klass
);
6087 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6089 int field_idx
= field
- m_class_get_fields (klass
);
6094 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6095 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
6096 if (!is_ok (error
)) {
6097 char *full_name
= mono_type_get_full_name (gtd
);
6098 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
));
6102 ftype
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (klass
), error
);
6103 if (!is_ok (error
)) {
6104 char *full_name
= mono_type_get_full_name (klass
);
6105 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
));
6110 guint32 cols
[MONO_FIELD_SIZE
];
6111 MonoGenericContainer
*container
= NULL
;
6112 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6114 /*FIXME, in theory we do not lazy load SRE fields*/
6115 g_assert (!image_is_dynamic (image
));
6117 if (mono_class_is_gtd (klass
)) {
6118 container
= mono_class_get_generic_container (klass
);
6120 container
= mono_class_get_generic_container (gtd
);
6121 g_assert (container
);
6124 /* first_field_idx and idx points into the fieldptr table */
6125 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
6127 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
)) {
6128 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
6132 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
6134 mono_metadata_decode_value (sig
, &sig
);
6135 /* FIELD signature == 0x06 */
6136 g_assert (*sig
== 0x06);
6138 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
6140 char *full_name
= mono_type_get_full_name (klass
);
6141 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
));
6145 mono_memory_barrier ();
6146 field
->type
= ftype
;
6150 mono_field_resolve_flags (MonoClassField
*field
)
6152 MonoClass
*klass
= field
->parent
;
6153 MonoImage
*image
= m_class_get_image (klass
);
6154 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6155 int field_idx
= field
- m_class_get_fields (klass
);
6158 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6159 return mono_field_get_flags (gfield
);
6161 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6163 /*FIXME, in theory we do not lazy load SRE fields*/
6164 g_assert (!image_is_dynamic (image
));
6166 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
6171 * mono_class_get_fields_lazy:
6172 * \param klass the MonoClass to act on
6174 * This routine is an iterator routine for retrieving the fields in a class.
6175 * Only minimal information about fields are loaded. Accessors must be used
6176 * for all MonoClassField returned.
6178 * You must pass a gpointer that points to zero and is treated as an opaque handle to
6179 * iterate over all of the elements. When no more values are
6180 * available, the return value is NULL.
6182 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
6185 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
6187 MonoClassField
* field
;
6191 mono_class_setup_basic_field_info (klass
);
6192 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
6195 /* start from the first */
6196 if (mono_class_get_field_count (klass
)) {
6197 *iter
= &klass_fields
[0];
6198 return (MonoClassField
*)*iter
;
6204 field
= (MonoClassField
*)*iter
;
6206 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
6208 return (MonoClassField
*)*iter
;
6214 mono_class_full_name (MonoClass
*klass
)
6216 return mono_type_full_name (m_class_get_byval_arg (klass
));
6219 /* Declare all shared lazy type lookup functions */
6220 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle
, "System.Runtime.InteropServices", "SafeHandle")
6223 * mono_method_get_base_method:
6224 * \param method a method
6225 * \param definition if true, get the definition
6226 * \param error set on failure
6228 * Given a virtual method associated with a subclass, return the corresponding
6229 * method from an ancestor. If \p definition is FALSE, returns the method in the
6230 * superclass of the given method. If \p definition is TRUE, return the method
6231 * in the ancestor class where it was first declared. The type arguments will
6232 * be inflated in the ancestor classes. If the method is not associated with a
6233 * class, or isn't virtual, returns the method itself. On failure returns NULL
6234 * and sets \p error.
6237 mono_method_get_base_method (MonoMethod
*method
, gboolean definition
, MonoError
*error
)
6239 MonoClass
*klass
, *parent
;
6240 MonoGenericContext
*generic_inst
= NULL
;
6241 MonoMethod
*result
= NULL
;
6244 if (method
->klass
== NULL
)
6247 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6248 MONO_CLASS_IS_INTERFACE_INTERNAL (method
->klass
) ||
6249 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6252 slot
= mono_method_get_vtable_slot (method
);
6256 klass
= method
->klass
;
6257 if (mono_class_is_gtd (klass
)) {
6258 /* If we get a GTD like Foo`2 replace look instead at its instantiation with its own generic params: Foo`2<!0, !1>. */
6259 /* In particular we want generic_inst to be initialized to <!0,
6260 * !1> so that we can inflate parent classes correctly as we go
6261 * up the class hierarchy. */
6262 MonoType
*ty
= mono_class_gtd_get_canonical_inst (klass
);
6263 g_assert (ty
->type
== MONO_TYPE_GENERICINST
);
6264 MonoGenericClass
*gklass
= ty
->data
.generic_class
;
6265 generic_inst
= mono_generic_class_get_context (gklass
);
6266 klass
= gklass
->container_class
;
6267 } else if (mono_class_is_ginst (klass
)) {
6268 generic_inst
= mono_class_get_context (klass
);
6269 klass
= mono_class_get_generic_class (klass
)->container_class
;
6274 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6275 for (parent
= m_class_get_parent (klass
); parent
!= NULL
; parent
= m_class_get_parent (parent
)) {
6276 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6277 or klass is the generic container class and generic_inst is the instantiation.
6279 when we go to the parent, if the parent is an open constructed type, we need to
6280 replace the type parameters by the definitions from the generic_inst, and then take it
6281 apart again into the klass and the generic_inst.
6283 For cases like this:
6284 class C<T> : B<T, int> {
6285 public override void Foo () { ... }
6287 class B<U,V> : A<HashMap<U,V>> {
6288 public override void Foo () { ... }
6291 public virtual void Foo () { ... }
6294 if at each iteration the parent isn't open, we can skip inflating it. if at some
6295 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6298 MonoGenericContext
*parent_inst
= NULL
;
6299 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent
))) {
6300 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, error
);
6301 return_val_if_nok (error
, NULL
);
6303 if (mono_class_is_ginst (parent
)) {
6304 parent_inst
= mono_class_get_context (parent
);
6305 parent
= mono_class_get_generic_class (parent
)->container_class
;
6308 mono_class_setup_vtable (parent
);
6309 if (m_class_get_vtable_size (parent
) <= slot
)
6312 generic_inst
= parent_inst
;
6315 /* When we get here, possibly after a retry, if generic_inst is
6316 * set, then the class is must be a gtd */
6317 g_assert (generic_inst
== NULL
|| mono_class_is_gtd (klass
));
6319 klass
= m_class_get_parent (klass
);
6322 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass
))) {
6323 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6324 return_val_if_nok (error
, NULL
);
6326 generic_inst
= NULL
;
6328 if (mono_class_is_ginst (klass
)) {
6329 generic_inst
= mono_class_get_context (klass
);
6330 klass
= mono_class_get_generic_class (klass
)->container_class
;
6336 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6337 return_val_if_nok (error
, NULL
);
6338 generic_inst
= NULL
;
6341 if (klass
== method
->klass
)
6344 /*This is possible if definition == FALSE.
6345 * Do it here to be really sure we don't read invalid memory.
6347 if (slot
>= m_class_get_vtable_size (klass
))
6350 mono_class_setup_vtable (klass
);
6352 result
= m_class_get_vtable (klass
) [slot
];
6353 if (result
== NULL
) {
6354 /* It is an abstract method */
6355 gboolean found
= FALSE
;
6356 gpointer iter
= NULL
;
6357 while ((result
= mono_class_get_methods (klass
, &iter
))) {
6358 if (result
->slot
== slot
) {
6363 /* found might be FALSE if we looked in an abstract class
6364 * that doesn't override an abstract method of its
6366 * abstract class Base {
6367 * public abstract void Foo ();
6369 * abstract class Derived : Base { }
6370 * class Child : Derived {
6371 * public override void Foo () { }
6374 * if m was Child.Foo and we ask for the base method,
6375 * then we get here with klass == Derived and found == FALSE
6377 /* but it shouldn't be the case that if we're looking
6378 * for the definition and didn't find a result; the
6379 * loop above should've taken us as far as we could
6381 g_assert (!(definition
&& !found
));
6386 g_assert (result
!= NULL
);
6391 mono_method_is_constructor (MonoMethod
*method
)
6393 return ((method
->flags
& CTOR_REQUIRED_FLAGS
) == CTOR_REQUIRED_FLAGS
&&
6394 !(method
->flags
& CTOR_INVALID_FLAGS
) &&
6395 !strcmp (".ctor", method
->name
));
6399 mono_class_has_default_constructor (MonoClass
*klass
, gboolean public_only
)
6404 mono_class_setup_methods (klass
);
6405 if (mono_class_has_failure (klass
))
6408 int mcount
= mono_class_get_method_count (klass
);
6409 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
6410 for (i
= 0; i
< mcount
; ++i
) {
6411 method
= klass_methods
[i
];
6412 if (mono_method_is_constructor (method
) &&
6413 mono_method_signature_internal (method
) &&
6414 mono_method_signature_internal (method
)->param_count
== 0 &&
6415 (!public_only
|| (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))