Permalink
Browse files

Allow TypeBuilder.DefineMethodOverride () to be called multiple times…

…. Fixes #5665.
  • Loading branch information...
1 parent 5309fe8 commit 72c896066ba21252a8bdecfe741bb982442c017c @vargaz vargaz committed Jun 24, 2012
@@ -61,7 +61,7 @@ public sealed class MethodBuilder : MethodInfo, _MethodBuilder
private TypeBuilder type;
internal ParameterBuilder[] pinfo;
private CustomAttributeBuilder[] cattrs;
- private MethodInfo override_method;
+ private MethodInfo[] override_methods;
private string pi_dll;
private string pi_entry;
private CharSet charset;
@@ -329,8 +329,12 @@ public ParameterBuilder DefineParameter (int position, ParameterAttributes attri
internal void check_override ()
{
- if (override_method != null && override_method.IsVirtual && !IsVirtual)
- throw new TypeLoadException (String.Format("Method '{0}' override '{1}' but it is not virtual", name, override_method));
+ if (override_methods != null) {
+ foreach (var m in override_methods) {
+ if (m.IsVirtual && !IsVirtual)
+ throw new TypeLoadException (String.Format("Method '{0}' override '{1}' but it is not virtual", name, m));
+ }
+ }
}
internal void fixup ()
@@ -522,9 +526,20 @@ internal override int get_next_table_index (object obj, int table, bool inc)
return type.get_next_table_index (obj, table, inc);
}
+ void ExtendArray<T> (ref T[] array, T elem) {
+ if (array == null) {
+ array = new T [1];
+ } else {
+ var newa = new T [array.Length + 1];
+ Array.Copy (array, newa, array.Length);
+ array = newa;
+ }
+ array [array.Length - 1] = elem;
+ }
+
internal void set_override (MethodInfo mdecl)
{
- override_method = mdecl;
+ ExtendArray<MethodInfo> (ref override_methods, mdecl);
}
private void RejectIfCreated ()
@@ -56,7 +56,7 @@ public static class Environment {
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 101;
+ private const int mono_corlib_version = 102;
#pragma warning restore 169
[ComVisible (true)]
@@ -75,7 +75,7 @@
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 101
+#define MONO_CORLIB_VERSION 102
typedef struct
{
@@ -983,7 +983,7 @@ typedef struct {
MonoObject *type;
MonoArray *pinfo;
MonoArray *cattrs;
- MonoReflectionMethod *override_method;
+ MonoArray *override_methods;
MonoString *dll;
MonoString *dllentry;
guint32 charset;
View
@@ -1543,29 +1543,35 @@ mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuild
MonoDynamicTable *table;
guint32 *values;
guint32 tok;
+ MonoReflectionMethod *m;
+ int i;
- if (!mb->override_method)
+ if (!mb->override_methods)
return;
- table = &assembly->tables [MONO_TABLE_METHODIMPL];
- table->rows ++;
- alloc_table (table, table->rows);
- values = table->values + table->rows * MONO_METHODIMPL_SIZE;
- values [MONO_METHODIMPL_CLASS] = tb->table_idx;
- values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+ for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
+ m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
- tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
- switch (mono_metadata_token_table (tok)) {
- case MONO_TABLE_MEMBERREF:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
- break;
- case MONO_TABLE_METHOD:
- tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
- break;
- default:
- g_assert_not_reached ();
+ table = &assembly->tables [MONO_TABLE_METHODIMPL];
+ table->rows ++;
+ alloc_table (table, table->rows);
+ values = table->values + table->rows * MONO_METHODIMPL_SIZE;
+ values [MONO_METHODIMPL_CLASS] = tb->table_idx;
+ values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
+
+ tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
+ switch (mono_metadata_token_table (tok)) {
+ case MONO_TABLE_MEMBERREF:
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
+ break;
+ case MONO_TABLE_METHOD:
+ tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ values [MONO_METHODIMPL_DECLARATION] = tok;
}
- values [MONO_METHODIMPL_DECLARATION] = tok;
}
#ifndef DISABLE_REFLECTION_EMIT
@@ -10884,7 +10890,8 @@ void
mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
{
MonoReflectionTypeBuilder *tb;
- int i, onum;
+ int i, j, onum;
+ MonoReflectionMethod *m;
*overrides = NULL;
*num_overrides = 0;
@@ -10903,8 +10910,8 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
for (i = 0; i < tb->num_methods; ++i) {
MonoReflectionMethodBuilder *mb =
mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_method)
- onum ++;
+ if (mb->override_methods)
+ onum += mono_array_length (mb->override_methods);
}
}
@@ -10915,13 +10922,17 @@ mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides
for (i = 0; i < tb->num_methods; ++i) {
MonoReflectionMethodBuilder *mb =
mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
- if (mb->override_method) {
- (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
- (*overrides) [onum * 2 + 1] = mb->mhandle;
+ if (mb->override_methods) {
+ for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
+ m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
- g_assert (mb->mhandle);
+ (*overrides) [onum * 2] = mono_reflection_method_get_handle (m);
+ (*overrides) [onum * 2 + 1] = mb->mhandle;
- onum ++;
+ g_assert (mb->mhandle);
+
+ onum ++;
+ }
}
}
}
View
@@ -20,6 +20,7 @@ public class Tests
GenericTypeParameterBuilder [] typeParams = if_tb.DefineGenericParameters ("T");
MethodBuilder if_mb = if_tb.DefineMethod ("foo", MethodAttributes.Public|MethodAttributes.Abstract|MethodAttributes.Virtual, typeParams [0], Type.EmptyTypes);
+ MethodBuilder if_mb2 = if_tb.DefineMethod ("foo2", MethodAttributes.Public|MethodAttributes.Abstract|MethodAttributes.Virtual, typeParams [0], Type.EmptyTypes);
TypeBuilder tb = module.DefineType ("Foo`1", TypeAttributes.Public, typeof (object));
@@ -42,13 +43,15 @@ public class Tests
gen.Emit (OpCodes.Ret);
tb.DefineMethodOverride (mb, TypeBuilder.GetMethod (inst, if_mb));
+ tb.DefineMethodOverride (mb, TypeBuilder.GetMethod (inst, if_mb2));
var k = if_tb.CreateType ();
Type t = tb.CreateType ();
object obj = Activator.CreateInstance (t.MakeGenericType (new Type [] { typeof (string)}));
var info = k.MakeGenericType (new Type [] { typeof (string) }).GetMethod ("foo");
var res = info.Invoke (obj, null);
+
return res == null ? 0 : 1;
}
}

0 comments on commit 72c8960

Please sign in to comment.