X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fpending.cs;h=d95f8f13956d867d0d60df079a4a10e9ebe98c80;hb=34866ac4c20c781f10c40fe6f6fe0c39733fd946;hp=b7403eda8ee1fc25c2551683bc694db9317733c8;hpb=15af51806d816ad6ad966bc1dfbdd232b63fde52;p=mono.git
diff --git a/mcs/mcs/pending.cs b/mcs/mcs/pending.cs
index b7403eda8ee..d95f8f13956 100644
--- a/mcs/mcs/pending.cs
+++ b/mcs/mcs/pending.cs
@@ -108,7 +108,7 @@ namespace Mono.CSharp {
throw new NotImplementedException ();
}
- public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
+ public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
{
throw new NotImplementedException ();
}
@@ -129,7 +129,7 @@ namespace Mono.CSharp {
///
/// The container for this PendingImplementation
///
- readonly TypeContainer container;
+ readonly TypeDefinition container;
///
/// This is the array of TypeAndMethods that describes the pending implementations
@@ -137,7 +137,7 @@ namespace Mono.CSharp {
///
TypeAndMethods [] pending_implementations;
- PendingImplementation (TypeContainer container, MissingInterfacesInfo[] missing_ifaces, MethodSpec[] abstract_methods, int total)
+ PendingImplementation (TypeDefinition container, MissingInterfacesInfo[] missing_ifaces, MethodSpec[] abstract_methods, int total)
{
var type_builder = container.Definition;
@@ -147,7 +147,6 @@ namespace Mono.CSharp {
int i = 0;
if (abstract_methods != null) {
int count = abstract_methods.Length;
- pending_implementations [i].methods = new MethodSpec [count];
pending_implementations [i].need_proxy = new MethodSpec [count];
pending_implementations [i].methods = abstract_methods;
@@ -189,20 +188,20 @@ namespace Mono.CSharp {
static readonly MissingInterfacesInfo [] EmptyMissingInterfacesInfo = new MissingInterfacesInfo [0];
- static MissingInterfacesInfo [] GetMissingInterfaces (TypeContainer container)
+ static MissingInterfacesInfo [] GetMissingInterfaces (TypeDefinition container)
{
//
- // Notice that Interfaces will only return the interfaces that the Type
- // is supposed to implement, not all the interfaces that the type implements.
+ // Interfaces will return all interfaces that the container
+ // implements including any inherited interfaces
//
var impl = container.Definition.Interfaces;
if (impl == null || impl.Count == 0)
return EmptyMissingInterfacesInfo;
- MissingInterfacesInfo[] ret = new MissingInterfacesInfo[impl.Count];
+ var ret = new MissingInterfacesInfo[impl.Count];
- for (int i = 0; i < impl.Count; i++)
+ for (int i = 0; i < ret.Length; i++)
ret [i] = new MissingInterfacesInfo (impl [i]);
// we really should not get here because Object doesnt implement any
@@ -233,7 +232,7 @@ namespace Mono.CSharp {
// Register method implementations are either abstract methods
// flagged as such on the base class or interface methods
//
- static public PendingImplementation GetPendingImplementations (TypeContainer container)
+ static public PendingImplementation GetPendingImplementations (TypeDefinition container)
{
TypeSpec b = container.BaseType;
@@ -305,11 +304,10 @@ namespace Mono.CSharp {
//
// First check exact modifiers match
//
- const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
- if ((cp[pi].ModFlags & ref_out) == (tp[pi].ModFlags & ref_out))
+ if ((cp[pi].ModFlags & Parameter.Modifier.RefOutMask) == (tp[pi].ModFlags & Parameter.Modifier.RefOutMask))
continue;
- if ((cp[pi].ModFlags & tp[pi].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
+ if (((cp[pi].ModFlags | tp[pi].ModFlags) & Parameter.Modifier.RefOutMask) == Parameter.Modifier.RefOutMask) {
ref_only_difference = true;
continue;
}
@@ -508,7 +506,7 @@ namespace Mono.CSharp {
}
int top = param.Count;
- var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null);
+ var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null, null);
ec.EmitThis ();
// TODO: GetAllParametersArguments
for (int i = 0; i < top; i++)
@@ -528,17 +526,64 @@ namespace Mono.CSharp {
bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method)
{
base_method = null;
- var base_type = container.BaseType;
+ bool base_can_implement = true;
+ TypeSpec lookup_type;
+
+ //
+ // Special handling for properties/indexers which cannot have accessors
+ // implementing an interface found in different types (e.g. current and base)
+ //
+ if (mi.IsAccessor && container.Interfaces != null) {
+
+ bool new_implementation = false;
+ foreach (var iface in container.Interfaces) {
+ if (TypeSpecComparer.IsEqual (iface, iface_type)) {
+ new_implementation = true;
+ break;
+ }
+ }
+
+ if (new_implementation) {
+ MemberFilter filter;
+ bool getter = mi.Name [0] == 'g';
+ if (mi.Parameters.Count > (getter ? 0 : 1)) {
+ var indexer_params = getter ? mi.Parameters : IndexerSpec.CreateParametersFromSetter (mi, mi.Parameters.Count - 1);
+ var ptype = getter ? mi.ReturnType : mi.Parameters.Types [mi.Parameters.Count - 1];
+ filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, indexer_params, ptype);
+ } else {
+ var pname = mi.Name.Substring (4);
+ var ptype = getter ? mi.ReturnType : mi.Parameters.Types [0];
+ filter = MemberFilter.Property (pname, ptype);
+ }
+
+ var prop = MemberCache.FindMember (container.CurrentType, filter, BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);
+ if (prop != null && (prop.Modifiers & Modifiers.NEW) != 0)
+ base_can_implement = false;
+ }
+ }
+
+ if (base_can_implement) {
+ lookup_type = container.BaseType;
+
+ if (lookup_type.ImplementsInterface (iface_type, false))
+ return true;
+ } else {
+ lookup_type = container.CurrentType;
+ }
//
// Setup filter with no return type to give better error message
// about mismatch at return type when the check bellow rejects them
//
var parameters = mi.Parameters;
+ MethodSpec close_match = null;
+
while (true) {
- var candidates = MemberCache.FindMembers (base_type, mi.Name, false);
- if (candidates == null)
+ var candidates = MemberCache.FindMembers (lookup_type, mi.Name, !base_can_implement);
+ if (candidates == null) {
+ base_method = close_match;
return false;
+ }
MethodSpec similar_candidate = null;
foreach (var candidate in candidates) {
@@ -549,7 +594,7 @@ namespace Mono.CSharp {
continue;
var candidate_param = ((MethodSpec) candidate).Parameters;
- if (!TypeSpecComparer.Override.IsSame (parameters.Types, candidate_param.Types))
+ if (!TypeSpecComparer.Override.IsEqual (parameters.Types, candidate_param.Types))
continue;
bool modifiers_match = true;
@@ -557,8 +602,7 @@ namespace Mono.CSharp {
//
// First check exact ref/out match
//
- const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
- if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out))
+ if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
continue;
modifiers_match = false;
@@ -566,7 +610,7 @@ namespace Mono.CSharp {
//
// Different in ref/out only
//
- if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
+ if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask)) {
if (similar_candidate == null) {
if (!candidate.IsPublic)
break;
@@ -589,22 +633,32 @@ namespace Mono.CSharp {
continue;
//
- // From this point on the candidate is used for detailed error reporting
+ // From this point the candidate is used for detailed error reporting
// because it's very close match to what we are looking for
//
- base_method = (MethodSpec) candidate;
+ var m = (MethodSpec) candidate;
+
+ if (!m.IsPublic) {
+ if (close_match == null)
+ close_match = m;
- if (!candidate.IsPublic)
- return false;
+ continue;
+ }
- if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType))
- return false;
+ if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, m.ReturnType)) {
+ if (close_match == null)
+ close_match = m;
- if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, base_method, mi)) {
+ continue;
+ }
+
+ base_method = m;
+
+ if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints (container, m, mi)) {
return true;
}
}
-
+
if (base_method != null) {
if (similar_candidate != null) {
Report.SymbolRelatedToPreviousError (similar_candidate);
@@ -618,9 +672,14 @@ namespace Mono.CSharp {
break;
}
- base_type = candidates[0].DeclaringType.BaseType;
- if (base_type == null)
+ if (!base_can_implement)
+ return false;
+
+ lookup_type = candidates[0].DeclaringType.BaseType;
+ if (lookup_type == null) {
+ base_method = close_match;
return false;
+ }
}
if (!base_method.IsVirtual) {
@@ -654,10 +713,6 @@ namespace Mono.CSharp {
for (i = 0; i < top; i++){
TypeSpec type = pending_implementations [i].type;
- bool base_implements_type = type.IsInterface &&
- container.BaseType != null &&
- container.BaseType.ImplementsInterface (type, false);
-
for (int j = 0; j < pending_implementations [i].methods.Count; ++j) {
var mi = pending_implementations[i].methods[j];
if (mi == null)
@@ -672,11 +727,8 @@ namespace Mono.CSharp {
continue;
}
- if (pending_implementations [i].optional)
- continue;
-
- MethodSpec candidate = null;
- if (base_implements_type || BaseImplements (type, mi, out candidate))
+ MethodSpec candidate;
+ if (BaseImplements (type, mi, out candidate))
continue;
if (candidate == null) {
@@ -694,8 +746,13 @@ namespace Mono.CSharp {
container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
} else if ((candidate.Modifiers & Modifiers.PUBLIC) == 0) {
Report.Error (737, container.Location,
- "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' in not public",
+ "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' is not public",
container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ());
+ } else if (mi.ReturnType.Kind == MemberKind.ByRef) {
+ Report.Error (8152, container.Location,
+ "`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not return by reference",
+ container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError (),
+ candidate.ReturnType.GetSignatureForError ());
} else {
Report.Error (738, container.Location,
"`{0}' does not implement interface member `{1}' and the best implementing candidate `{2}' return type `{3}' does not match interface member return type `{4}'",