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}'",