Fix #73038.
[mono.git] / mcs / mcs / pending.cs
index eebb4117ab52306e948b0d5554273d1323079760..98a4e9993eec4b4a0b9fb137bf6a577f7784202a 100644 (file)
@@ -23,7 +23,7 @@ namespace Mono.CSharp {
 
                // 
                // Whether it is optional, this is used to allow the explicit/implicit
-               // implementation when a parent class already implements an interface. 
+               // implementation when a base class already implements an interface. 
                //
                // For example:
                //
@@ -68,7 +68,7 @@ namespace Mono.CSharp {
 
                /// <summary>
                ///   This is the array of TypeAndMethods that describes the pending implementations
-               ///   (both interfaces and abstract methods in parent class)
+               ///   (both interfaces and abstract methods in base class)
                /// </summary>
                TypeAndMethods [] pending_implementations;
 
@@ -88,7 +88,7 @@ namespace Mono.CSharp {
 
                // <remarks>
                //   Returns a list of the abstract methods that are exposed by all of our
-               //   parents that we must implement.  Notice that this `flattens' the
+               //   bases that we must implement.  Notice that this `flattens' the
                //   method search space, and takes into account overrides.  
                // </remarks>
                static ArrayList GetAbstractMethods (Type t)
@@ -102,8 +102,8 @@ namespace Mono.CSharp {
                                
                                mi = TypeContainer.FindMembers (
                                        current_type, MemberTypes.Method,
-                                       BindingFlags.Public | BindingFlags.Instance |
-                                       BindingFlags.DeclaredOnly,
+                                       BindingFlags.Public | BindingFlags.NonPublic |
+                                       BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                        virtual_method_filter, null);
 
                                if (current_type == TypeManager.object_type)
@@ -175,7 +175,13 @@ namespace Mono.CSharp {
                                
                                int j = 0;
                                foreach (MethodInfo m in mi){
-                                       Type [] types = TypeManager.GetArgumentTypes (m);
+                                       Type [] types;
+                                       
+                                       // If there is a previous error, just ignore
+                                       if (m == null)
+                                               types = TypeManager.NoTypes;
+                                       else
+                                               types = TypeManager.GetArgumentTypes (m);
                                        
                                        pending_implementations [i].args [j] = types;
                                        j++;
@@ -248,9 +254,9 @@ namespace Mono.CSharp {
                        if (type_builder.BaseType == null)
                                return ret;
                        
-                       Type [] parent_impls = TypeManager.GetInterfaces (type_builder.BaseType);
+                       Type [] base_impls = TypeManager.GetInterfaces (type_builder.BaseType);
                        
-                       foreach (Type t in parent_impls) {
+                       foreach (Type t in base_impls) {
                                for (int i = 0; i < ret.Length; i ++) {
                                        if (t == ret [i].Type) {
                                                ret [i].Optional = true;
@@ -450,7 +456,7 @@ namespace Mono.CSharp {
                ///   For that case, we create an explicit implementation function
                ///   I.M in Y.
                /// </summary>
-               void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
+               void DefineProxy (Type iface, MethodInfo base_method, MethodInfo iface_method,
                                  Type [] args)
                {
                        MethodBuilder proxy;
@@ -463,36 +469,26 @@ namespace Mono.CSharp {
                                MethodAttributes.NewSlot |
                                MethodAttributes.Virtual,
                                CallingConventions.Standard | CallingConventions.HasThis,
-                               parent_method.ReturnType, args);
+                               base_method.ReturnType, args);
 
                        int top = args.Length;
                        ILGenerator ig = proxy.GetILGenerator ();
 
-                       ig.Emit (OpCodes.Ldarg_0);
-                       for (int i = 0; i < top; i++){
-                               switch (i){
-                               case 0:
-                                       ig.Emit (OpCodes.Ldarg_1); break;
-                               case 1:
-                                       ig.Emit (OpCodes.Ldarg_2); break;
-                               case 2:
-                                       ig.Emit (OpCodes.Ldarg_3); break;
-                               default:
-                                       ig.Emit (OpCodes.Ldarg, i - 1); break;
-                               }
-                       }
-                       ig.Emit (OpCodes.Call, parent_method);
+                       for (int i = 0; i <= top; i++)
+                               ParameterReference.EmitLdArg (ig, i);
+
+                       ig.Emit (OpCodes.Call, base_method);
                        ig.Emit (OpCodes.Ret);
 
                        container.TypeBuilder.DefineMethodOverride (proxy, iface_method);
                }
                
                /// <summary>
-               ///   This function tells whether one of our parent classes implements
+               ///   This function tells whether one of our base classes implements
                ///   the given method (which turns out, it is valid to have an interface
-               ///   implementation in a parent
+               ///   implementation in a base
                /// </summary>
-               bool ParentImplements (Type iface_type, MethodInfo mi)
+               bool BaseImplements (Type iface_type, MethodInfo mi)
                {
                        MethodSignature ms;
                        
@@ -506,9 +502,9 @@ namespace Mono.CSharp {
                        if (list.Count == 0)
                                return false;
 
-                       MethodInfo parent = (MethodInfo) list [0];
-                       if (!parent.IsAbstract)
-                               DefineProxy (iface_type, parent, mi, args);
+                       MethodInfo base_method = (MethodInfo) list [0];
+                       if (!base_method.IsAbstract)
+                               DefineProxy (iface_type, base_method, mi, args);
                        return true;
                }
 
@@ -540,21 +536,28 @@ namespace Mono.CSharp {
                                                        continue;
                                                }
 
-                                               if (ParentImplements (type, mi))
+                                               if (BaseImplements (type, mi))
                                                        continue;
 
                                                if (pending_implementations [i].optional)
                                                        continue;
-                                               
+
+                                               Report.SymbolRelatedToPreviousError (mi);
                                                if (pending_implementations [i].found [j]) {
-                                                       string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
-                                                       Report.Error (536, container.Location,
-                                                                     "'{0}' does not implement interface member '{1}'. '{2}.{3}' " +
-                                                                     "is either static, not public, or has the wrong return type",
-                                                                     container.Name, TypeManager.CSharpSignature (mi),
-                                                                     container.Name, methodLabel[methodLabel.Length - 1]);
+                                                       if (mi.IsSpecialName) {
+                                                               string name = TypeManager.CSharpName (mi.DeclaringType) + '.' + mi.Name.Substring (4);
+                                                               Report.Error (551, container.Location, "Explicit interface implementation '{0}.{1}' is missing accessor '{1}'",
+                                                                       container.Name, name);
+                                                       } else {
+                                                               string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
+                                                               Report.Error (536, container.Location,
+                                                                       "'{0}' does not implement interface member '{1}'. '{2}.{3}' " +
+                                                                       "is either static, not public, or has the wrong return type",
+                                                                       container.Name, TypeManager.CSharpSignature (mi),
+                                                                       container.Name, methodLabel[methodLabel.Length - 1]);
+                                                       }
                                                }
-                                               else { 
+                                               else {
                                                        Report.Error (535, container.Location, "'{0}' does not implement interface member '{1}'",
                                                                container.Name, TypeManager.CSharpSignature (mi));
                                                }