// Author:
// Miguel de Icaza (miguel@gnu.org)
//
-// Licensed under the terms of the GNU GPL
-//
-// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
+// Dual licensed under the terms of the MIT X11 or GNU GPL
//
+// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com)
+// Copyright 2003-2008 Novell, Inc.
//
using System;
pending_implementations = new TypeAndMethods [total];
int i = 0;
- foreach (MissingInterfacesInfo missing in missing_ifaces){
+ if (abstract_methods != null) {
+ int count = abstract_methods.Count;
+ pending_implementations [i].methods = new MethodInfo [count];
+ pending_implementations [i].need_proxy = new MethodInfo [count];
+
+ abstract_methods.CopyTo (pending_implementations [i].methods, 0);
+ pending_implementations [i].found = new bool [count];
+ pending_implementations [i].args = new Type [count][];
+ pending_implementations [i].mods = new Parameter.Modifier [count][];
+ pending_implementations [i].type = type_builder;
+
+ string indexer_name = TypeManager.IndexerPropertyName (type_builder);
+ pending_implementations [i].set_indexer_name = "set_" + indexer_name;
+ pending_implementations [i].get_indexer_name = "get_" + indexer_name;
+
+ int j = 0;
+ foreach (MemberInfo m in abstract_methods) {
+ MethodInfo mi = (MethodInfo) m;
+
+ ParameterData pd = TypeManager.GetParameterData (mi);
+ Type [] types = pd.Types;
+
+ pending_implementations [i].args [j] = types;
+ pending_implementations [i].mods [j] = null;
+ if (pd.Count > 0) {
+ Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
+ for (int k = 0; k < pd.Count; k++)
+ pm [k] = pd.ParameterModifier (k);
+ pending_implementations [i].mods [j] = pm;
+ }
+
+ j++;
+ }
+ ++i;
+ }
+
+ foreach (MissingInterfacesInfo missing in missing_ifaces) {
MethodInfo [] mi;
Type t = missing.Type;
-
+
if (!t.IsInterface)
continue;
TypeContainer iface;
iface = TypeManager.LookupInterface (t);
-
+
mi = iface.GetMethods ();
} else
mi = t.GetMethods ();
-
+
int count = mi.Length;
pending_implementations [i].type = t;
pending_implementations [i].optional = missing.Optional;
int j = 0;
foreach (MethodInfo m in mi){
- pending_implementations [i].args [j] = TypeManager.NoTypes;
+ pending_implementations [i].args [j] = Type.EmptyTypes;
pending_implementations [i].mods [j] = null;
// If there is a previous error, just ignore
if (m == null)
continue;
- pending_implementations [i].args [j] = TypeManager.GetArgumentTypes (m);
-
ParameterData pd = TypeManager.GetParameterData (m);
+ pending_implementations [i].args [j] = pd.Types;
if (pd.Count > 0){
Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
}
i++;
}
-
- if (abstract_methods != null){
- int count = abstract_methods.Count;
- pending_implementations [i].methods = new MethodInfo [count];
- pending_implementations [i].need_proxy = new MethodInfo [count];
-
- abstract_methods.CopyTo (pending_implementations [i].methods, 0);
- pending_implementations [i].found = new bool [count];
- pending_implementations [i].args = new Type [count][];
- pending_implementations [i].mods = new Parameter.Modifier [count][];
- pending_implementations [i].type = type_builder;
-
- string indexer_name = TypeManager.IndexerPropertyName (type_builder);
- pending_implementations [i].set_indexer_name = "set_" + indexer_name;
- pending_implementations [i].get_indexer_name = "get_" + indexer_name;
-
- int j = 0;
- foreach (MemberInfo m in abstract_methods){
- MethodInfo mi = (MethodInfo) m;
-
- Type [] types = TypeManager.GetArgumentTypes (mi);
- ParameterData pd = TypeManager.GetParameterData (mi);
-
- pending_implementations [i].args [j] = types;
- pending_implementations [i].mods [j] = null;
- if (pd.Count > 0){
- Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
- for (int k = 0; k < pd.Count; k++)
- pm [k] = pd.ParameterModifier (k);
- pending_implementations [i].mods [j] = pm;
- }
-
- j++;
- }
- }
}
struct MissingInterfacesInfo {
for (int i = 0; i < impl.Length; i++)
ret [i] = new MissingInterfacesInfo (impl [i]);
-
+
// we really should not get here because Object doesnt implement any
// interfaces. But it could implement something internal, so we have
// to handle that case.
if (m == null)
continue;
+ string mname = TypeManager.GetMethodName (m);
+
//
// `need_proxy' is not null when we're implementing an
// interface indexer and this is Clear(One/All) operation.
// for an interface indexer).
//
if (name == null){
- if (m.Name != tm.get_indexer_name && m.Name != tm.set_indexer_name)
+ if (mname != tm.get_indexer_name && mname != tm.set_indexer_name)
continue;
- } else if ((need_proxy == null) && (name != m.Name))
+ } else if ((need_proxy == null) && (name != mname))
continue;
- if (ret_type != m.ReturnType){
- if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
- (m.ReturnType == null && ret_type == TypeManager.void_type)))
- continue;
- }
+ Type rt = TypeManager.TypeToCoreType (m.ReturnType);
+ if (!TypeManager.IsEqual (ret_type, rt) &&
+ !(ret_type == null && rt == TypeManager.void_type) &&
+ !(rt == null && ret_type == TypeManager.void_type))
+ continue;
//
// Check if we have the same parameters
//
- if (tm.args [i].Length != arg_len)
+
+ if (tm.args [i] == null && arg_len != 0)
+ continue;
+ if (tm.args [i] != null && tm.args [i].Length != arg_len)
continue;
- int j, top = args.Count;
+ int j;
- for (j = 0; j < top; j++)
- if (tm.args [i][j] != args.ParameterType (j) ||
- (tm.mods [i][j] != args.ParameterModifier (j) &&
- tm.mods [i][j] != Parameter.Modifier.PARAMS &&
- args.ParameterModifier (j) != Parameter.Modifier.PARAMS)
- )
+ for (j = 0; j < arg_len; j++) {
+ if (!TypeManager.IsEqual (tm.args [i][j], args.ParameterType (j)))
+ break;
+ if (tm.mods [i][j] == args.ParameterModifier (j))
+ continue;
+ // The modifiers are different, but if one of them
+ // is a PARAMS modifier, and the other isn't, ignore
+ // the difference.
+ if (tm.mods [i][j] != Parameter.Modifier.PARAMS &&
+ args.ParameterModifier (j) != Parameter.Modifier.PARAMS)
break;
- if (j != top)
+ }
+ if (j != arg_len)
continue;
if (op != Operation.Lookup){
// a proxy if the implementation's IndexerName doesn't
// match the IndexerName in the interface.
bool name_matches = false;
- if (name == m.Name || m.Name == tm.get_indexer_name || m.Name == tm.set_indexer_name)
+ if (name == mname || mname == tm.get_indexer_name || mname == tm.set_indexer_name)
name_matches = true;
-
+
if ((t == null) && (need_proxy != null) && !name_matches)
tm.need_proxy [i] = need_proxy;
else
{
MethodBuilder proxy;
- string proxy_name = iface.Name + "." + iface_method.Name;
+ string proxy_name = SimpleName.RemoveGenericArity (iface.Name) + '.' + iface_method.Name;
proxy = container.TypeBuilder.DefineMethod (
proxy_name,
CallingConventions.Standard | CallingConventions.HasThis,
base_method.ReturnType, args);
+ ParameterData pd = TypeManager.GetParameterData (iface_method);
+ proxy.DefineParameter (0, ParameterAttributes.None, "");
+ for (int i = 0; i < pd.Count; i++) {
+ string name = pd.ParameterName (i);
+ ParameterAttributes attr = Parameter.GetParameterAttributes (pd.ParameterModifier (i));
+ proxy.DefineParameter (i + 1, attr, name);
+ }
+
int top = args.Length;
ILGenerator ig = proxy.GetILGenerator ();
{
MethodSignature ms;
- Type [] args = TypeManager.GetArgumentTypes (mi);
- ms = new MethodSignature (mi.Name, mi.ReturnType, args);
+ Type [] args = TypeManager.GetParameterData (mi).Types;
+ ms = new MethodSignature (mi.Name, TypeManager.TypeToCoreType (mi.ReturnType), args);
MemberList list = TypeContainer.FindMembers (
container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance,
if (TypeManager.ImplementsInterface (container.TypeBuilder.BaseType, iface_type))
return true;
- //
- // FIXME: We should be creating fewer proxies. The runtime can handle most cases.
- // At worst, if we can't avoid creating the proxy, we may need to make the
- // proxy use Callvirt.
- //
MethodInfo base_method = (MethodInfo) list [0];
+ if (base_method.DeclaringType.IsInterface)
+ return false;
+
if (!base_method.IsAbstract && !base_method.IsVirtual)
+ // FIXME: We can avoid creating a proxy if base_method can be marked 'final virtual' instead.
+ // However, it's too late now, the MethodBuilder has already been created (see bug 377519)
DefineProxy (iface_type, base_method, mi, args);
return true;
Type type = pending_implementations [i].type;
int j = 0;
+ bool base_implements_type = type.IsInterface &&
+ container.TypeBuilder.BaseType != null &&
+ TypeManager.ImplementsInterface (container.TypeBuilder.BaseType, type);
+
foreach (MethodInfo mi in pending_implementations [i].methods){
if (mi == null)
continue;
pending_implementations [i].need_proxy [j];
if (need_proxy != null) {
- Type [] args = TypeManager.GetArgumentTypes (mi);
+ Type [] args = TypeManager.GetParameterData (mi).Types;
DefineProxy (type, need_proxy, mi, args);
continue;
}
- if (BaseImplements (type, mi))
+ if (base_implements_type || BaseImplements (type, mi))
continue;
if (pending_implementations [i].optional)