2002-08-03 Martin Baulig <martin@gnome.org>
authorMartin Baulig <martin@novell.com>
Sat, 3 Aug 2002 18:05:05 +0000 (18:05 -0000)
committerMartin Baulig <martin@novell.com>
Sat, 3 Aug 2002 18:05:05 +0000 (18:05 -0000)
* class.cs (Method.IsOperator): New public field.
(Method.CheckBase): Report CS0111 if there's already a method
with the same parameters in the current class.  Report CS0508 when
attempting to change the return type of an inherited method.
(MethodData.Emit): Report CS0179 if a method doesn't have a body
and it's not marked abstract or extern.
(PropertyBase): New abstract base class for Property and Indexer.
(PropertyBase.CheckBase): Moved here from Property and made it work
for indexers.
(PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is
the same so we can reuse it there.
(Property, Indexer): Derive from PropertyBase.
(MethodSignature.inheritable_property_signature_filter): New delegate
to find properties and indexers.

* decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name'
argument and improved error reporting.

* parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to
EmptyReadOnlyParameters and made it a property.

* typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded
version of this method which takes a `PropertyInfo indexer'.
(TypeManager.RegisterIndexer): New method.

* class.cs: Added myself as author of this file :-)

svn path=/trunk/mcs/; revision=6381

mcs/mcs/ChangeLog
mcs/mcs/class.cs
mcs/mcs/cs-parser.jay
mcs/mcs/decl.cs
mcs/mcs/interface.cs
mcs/mcs/parameter.cs
mcs/mcs/typemanager.cs

index c29a89f2b452c47e63cad328e456b62b21492192..7fe5ac8a8b0e472d91023e544b5b4cc63c9d451d 100755 (executable)
@@ -1,3 +1,32 @@
+2002-08-03  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Method.IsOperator): New public field.
+       (Method.CheckBase): Report CS0111 if there's already a method
+       with the same parameters in the current class.  Report CS0508 when
+       attempting to change the return type of an inherited method.
+       (MethodData.Emit): Report CS0179 if a method doesn't have a body
+       and it's not marked abstract or extern.
+       (PropertyBase): New abstract base class for Property and Indexer.
+       (PropertyBase.CheckBase): Moved here from Property and made it work
+       for indexers.
+       (PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is
+       the same so we can reuse it there.
+       (Property, Indexer): Derive from PropertyBase.
+       (MethodSignature.inheritable_property_signature_filter): New delegate
+       to find properties and indexers.
+
+       * decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name'
+       argument and improved error reporting.
+
+       * parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to
+       EmptyReadOnlyParameters and made it a property.
+
+       * typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded
+       version of this method which takes a `PropertyInfo indexer'.
+       (TypeManager.RegisterIndexer): New method.
+
+       * class.cs: Added myself as author of this file :-)
+
 2002-08-03  Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * class.cs: fixed compilation on windoze.
index 3857ad23cf692681676ec02fff923135dbf6c2d5..9ed6a21e3e0be7b634d03489744b8169e58bd813 100755 (executable)
@@ -1,7 +1,8 @@
 //
 // class.cs: Class and Struct handlers
 //
-// Author: Miguel de Icaza (miguel@gnu.org)
+// Authors: Miguel de Icaza (miguel@gnu.org)
+//          Martin Baulig (martin@gnome.org)
 //
 // Licensed under the terms of the GNU GPL
 //
@@ -555,7 +556,7 @@ namespace Mono.CSharp {
                        Constructor c;
                        int mods = 0;
 
-                       c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
+                       c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
                                             new ConstructorBaseInitializer (null, new Location (-1)),
                                             new Location (-1));
                        
@@ -1947,6 +1948,9 @@ namespace Mono.CSharp {
                        return MemberType;
                }
 
+               // Whether this is an operator method.
+               public bool IsOperator;
+
                 void DuplicateEntryPoint (MethodInfo b, Location location)
                 {
                         Report.Error (
@@ -1998,6 +2002,25 @@ namespace Mono.CSharp {
                        if (!DoDefineParameters (parent))
                                return false;
 
+                       MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+                       if (!IsOperator) {
+                               MemberInfo [] mi_this;
+
+                               mi_this = TypeContainer.FindMembers (
+                                       parent.TypeBuilder, MemberTypes.Method,
+                                       BindingFlags.NonPublic | BindingFlags.Public |
+                                       BindingFlags.Static | BindingFlags.Instance |
+                                       BindingFlags.DeclaredOnly,
+                                       MethodSignature.method_signature_filter, ms);
+
+                               if (mi_this != null && mi_this.Length > 0) {
+                                       Report.Error (111, Location, "Class `" + parent.Name + "' " +
+                                                     "already defines a member called `" + Name + "' " +
+                                                     "with the same parameter types");
+                                       return false;
+                               }
+                       }
+
                        //
                        // Verify if the parent has a type with the same name, and then
                        // check whether we have to create a new slot for it or not.
@@ -2006,7 +2029,6 @@ namespace Mono.CSharp {
 
                        // ptype is only null for System.Object while compiling corlib.
                        if (ptype != null){
-                               MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
                                MemberInfo [] mi, mi_static, mi_instance;
 
                                mi_static = TypeContainer.FindMembers (
@@ -2028,10 +2050,25 @@ namespace Mono.CSharp {
                                        mi = null;
 
                                if (mi != null && mi.Length > 0){
-                                       if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
+                                       parent_method = (MethodInfo) mi [0];
+                                       string name = parent_method.DeclaringType.Name + "." +
+                                               parent_method.Name;
+
+                                       if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
                                                return false;
+
+                                       if ((ModFlags & Modifiers.NEW) == 0) {
+                                               Type parent_ret = TypeManager.TypeToCoreType (
+                                                       parent_method.ReturnType);
+
+                                               if (parent_ret != MemberType) {
+                                                       Report.Error (
+                                                               508, parent.MakeName (Name) + ": cannot " +
+                                                               "change return type when overriding " +
+                                                               "inherited member " + name);
+                                                       return false;
+                                               }
                                        }
-                                       parent_method = (MethodInfo) mi [0];
                                } else {
                                        if ((ModFlags & Modifiers.NEW) != 0)
                                                WarningNotHiding (parent);
@@ -2056,6 +2093,9 @@ namespace Mono.CSharp {
                        if (!DoDefine (parent))
                                return false;
 
+                       if (!CheckBase (parent))
+                               return false;
+
                        CallingConventions cc = GetCallingConvention (parent is Class);
 
                        MethodData = new MethodData (this, null, MemberType, ParameterTypes,
@@ -2717,19 +2757,31 @@ namespace Mono.CSharp {
                                //
                                if ((modifiers & Modifiers.ABSTRACT) != 0)
                                        Report.Error (
-                                               500, "Abstract method `" +
+                                               500, Location, "Abstract method `" +
                                                TypeManager.CSharpSignature (builder) +
                                                "' can not have a body");
 
                                if ((modifiers & Modifiers.EXTERN) != 0)
                                        Report.Error (
-                                               179, "External method `" +
+                                               179, Location, "External method `" +
                                                TypeManager.CSharpSignature (builder) +
                                                "' can not have a body");
 
                                return;
                        }
 
+                       //
+                       // Methods must have a body unless they're extern or abstract
+                       //
+                       if (block == null) {
+                               Report.Error (
+                                       501, Location, "Method `" +
+                                       TypeManager.CSharpSignature (builder) +
+                                       "' must declare a body since it is not marked " +
+                                       "abstract or extern");
+                               return;
+                       }
+
                        //
                        // Handle destructors specially
                        //
@@ -2926,9 +2978,6 @@ namespace Mono.CSharp {
                        if (MemberType.IsPointer && !UnsafeOK (parent))
                                return false;
                        
-                       if (!CheckBase (parent))
-                               return false;
-
                        //
                        // Check for explicit interface implementation
                        //
@@ -3095,57 +3144,78 @@ namespace Mono.CSharp {
                        OptAttributes = attrs;
                }
        }
-                       
-       public class Property : MemberBase {
+
+       //
+       // Properties and Indexers both generate PropertyBuilders, we use this to share 
+       // their common bits.
+       //
+       abstract public class PropertyBase : MethodCore {
                public Accessor Get, Set;
                public PropertyBuilder PropertyBuilder;
                public MethodBuilder GetBuilder, SetBuilder;
                public MethodData GetData, SetData;
 
-               const int AllowedModifiers =
-                       Modifiers.NEW |
-                       Modifiers.PUBLIC |
-                       Modifiers.PROTECTED |
-                       Modifiers.INTERNAL |
-                       Modifiers.PRIVATE |
-                       Modifiers.STATIC |
-                       Modifiers.SEALED |
-                       Modifiers.OVERRIDE |
-                       Modifiers.ABSTRACT |
-                       Modifiers.UNSAFE |
-                       Modifiers.EXTERN |
-                       Modifiers.VIRTUAL;
+               protected EmitContext ec;
 
-               public Property (Expression type, string name, int mod_flags,
-                                Accessor get_block, Accessor set_block,
-                                Attributes attrs, Location loc)
-                       : base (type, mod_flags, AllowedModifiers, name, attrs, loc)
+               public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
+                                    Parameters parameters, Accessor get_block, Accessor set_block,
+                                    Attributes attrs, Location loc)
+                       : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
                {
                        Get = get_block;
                        Set = set_block;
                }
 
+               protected override bool DoDefine (TypeContainer parent)
+               {
+                       if (!base.DoDefine (parent))
+                               return false;
+
+                       ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
+
+                       return true;
+               }
+
                //
                // Checks our base implementation if any
                //
                protected override bool CheckBase (TypeContainer parent)
                {
+                       // Check whether arguments were correct.
+                       if (!DoDefineParameters (parent))
+                               return false;
+
+                       MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+                       MemberInfo [] props_this;
+
+                       props_this = TypeContainer.FindMembers (
+                               parent.TypeBuilder, MemberTypes.Property,
+                               BindingFlags.NonPublic | BindingFlags.Public |
+                               BindingFlags.Static | BindingFlags.Instance |
+                               BindingFlags.DeclaredOnly,
+                               MethodSignature.method_signature_filter, ms);
+
+                       if (props_this != null && props_this.Length > 0) {
+                               Report.Error (111, Location, "Class `" + parent.Name + "' " +
+                                             "already defines a member called `" + Name + "' " +
+                                             "with the same parameter types");
+                               return false;
+                       }
+
                        //
                        // Find properties with the same name on the base class
                        //
-
                        MemberInfo [] props;
-                       MemberInfo [] props_static = TypeManager.MemberLookup (
-                               parent.TypeBuilder, 
-                               parent.TypeBuilder.BaseType,
-                               MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
-                               Name);
-
-                       MemberInfo [] props_instance = TypeManager.MemberLookup (
-                               parent.TypeBuilder, 
-                               parent.TypeBuilder.BaseType,
-                               MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
-                               Name);
+                       MemberInfo [] props_static = TypeContainer.FindMembers (
+                               parent.TypeBuilder.BaseType, MemberTypes.Property,
+                               BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
+                               MethodSignature.inheritable_property_signature_filter, ms);
+
+                       MemberInfo [] props_instance = TypeContainer.FindMembers (
+                               parent.TypeBuilder.BaseType, MemberTypes.Property,
+                               BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+                               MethodSignature.inheritable_property_signature_filter,
+                               ms);
 
                        //
                        // Find if we have anything
@@ -3160,9 +3230,6 @@ namespace Mono.CSharp {
                        //
                        // If we have something on the base.
                        if (props != null && props.Length > 0){
-                               if (props.Length > 1)
-                                       throw new Exception ("Should not happen");
-                               
                                PropertyInfo pi = (PropertyInfo) props [0];
 
                                MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
@@ -3171,36 +3238,95 @@ namespace Mono.CSharp {
                                MethodInfo reference = inherited_get == null ?
                                        inherited_set : inherited_get;
                                
-                               if (reference != null)
-                                       if (!CheckMethodAgainstBase (parent, flags, reference))
+                               if (reference != null) {
+                                       string name = reference.DeclaringType.Name + "." + Name;
+
+                                       if (!CheckMethodAgainstBase (parent, flags, reference, name))
                                                return false;
-                               
+                               }
+
+                               if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
+                                       Report.Error (508, parent.MakeName (Name) + ": cannot " +
+                                                     "change return type when overriding inherited " +
+                                                     "member `" + pi.DeclaringType + "." + pi.Name + "'");
+                                       return false;
+                               }
                        } else {
                                if ((ModFlags & Modifiers.NEW) != 0)
                                        WarningNotHiding (parent);
                                
                                if ((ModFlags & Modifiers.OVERRIDE) != 0){
-                                       Report.Error (115, Location,
-                                                     parent.MakeName (Name) +
-                                                     " no suitable properties found to override");
+                                       if (this is Indexer)
+                                               Report.Error (115, Location,
+                                                             parent.MakeName (Name) +
+                                                             " no suitable indexers found to override");
+                                       else
+                                               Report.Error (115, Location,
+                                                             parent.MakeName (Name) +
+                                                             " no suitable properties found to override");
                                        return false;
                                }
                        }
                        return true;
                }
 
+               public void Emit (TypeContainer tc)
+               {
+                       //
+                       // The PropertyBuilder can be null for explicit implementations, in that
+                       // case, we do not actually emit the ".property", so there is nowhere to
+                       // put the attribute
+                       //
+                       if (PropertyBuilder != null)
+                               Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
+
+                       if (GetData != null)
+                               GetData.Emit (tc, Get.Block, Get);
+
+                       if (SetData != null)
+                               SetData.Emit (tc, Set.Block, Set);
+               }
+       }
+                       
+       public class Property : PropertyBase {
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN |
+                       Modifiers.VIRTUAL;
+
+               public Property (Expression type, string name, int mod_flags,
+                                Accessor get_block, Accessor set_block,
+                                Attributes attrs, Location loc)
+                       : base (type, name, mod_flags, AllowedModifiers,
+                               Parameters.EmptyReadOnlyParameters,
+                               get_block, set_block, attrs, loc)
+               {
+               }
+
                public override bool Define (TypeContainer parent)
                {
                        if (!DoDefine (parent))
                                return false;
 
+                       if (!CheckBase (parent))
+                               return false;
+
                        flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
 
                        if (Get != null) {
                                Type [] parameters = TypeManager.NoTypes;
 
                                InternalParameters ip = new InternalParameters (
-                                       parent, Parameters.GetEmptyReadOnlyParameters ());
+                                       parent, Parameters.EmptyReadOnlyParameters);
 
                                GetData = new MethodData (this, "get", MemberType,
                                                          parameters, ip, CallingConventions.Standard,
@@ -3262,30 +3388,8 @@ namespace Mono.CSharp {
                        }
                        return true;
                }
-               
-               public void Emit (TypeContainer tc)
-               {
-                       EmitContext ec;
-
-                       ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
-
-                       //
-                       // The PropertyBuilder can be null for explicit implementations, in that
-                       // case, we do not actually emit the ".property", so there is nowhere to
-                       // put the attribute
-                       //
-                       if (PropertyBuilder != null)
-                               Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
-
-                       if (GetData != null)
-                               GetData.Emit (tc, Get.Block, Get);
-
-                       if (SetData != null)
-                               SetData.Emit (tc, Set.Block, Set);
-               }
        }
 
-
        /// </summary>
        ///  Gigantic workaround  for lameness in SRE follows :
        ///  This class derives from EventInfo and attempts to basically
@@ -3471,6 +3575,9 @@ namespace Mono.CSharp {
                        InternalParameters ip = new InternalParameters (
                                parent, new Parameters (parms, null, Location)); 
 
+                       if (!CheckBase (parent))
+                               return false;
+
                        //
                        // Now define the accessors
                        //
@@ -3587,7 +3694,7 @@ namespace Mono.CSharp {
        // 
        // int this [ args ]
  
-       public class Indexer : MemberBase {
+       public class Indexer : PropertyBase {
 
                const int AllowedModifiers =
                        Modifiers.NEW |
@@ -3602,13 +3709,6 @@ namespace Mono.CSharp {
                        Modifiers.EXTERN |
                        Modifiers.ABSTRACT;
 
-               public readonly Parameters FormalParameters;
-               public readonly Accessor   Get, Set;
-               public MethodData          GetData;
-               public MethodData          SetData;
-               public MethodBuilder       GetBuilder;
-               public MethodBuilder       SetBuilder;
-               public PropertyBuilder PropertyBuilder;
                public string IndexerName;
                public string InterfaceIndexerName;
 
@@ -3617,18 +3717,14 @@ namespace Mono.CSharp {
                //
                bool IsImplementing = false;
                
-               EmitContext ec;
-               
-               public Indexer (Expression type, string int_type, int flags, Parameters parms,
+               public Indexer (Expression type, string int_type, int flags, Parameters parameters,
                                Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
-                       : base (type, flags, AllowedModifiers, "", attrs, loc)
+                       : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
+                               attrs, loc)
                {
                        ExplicitInterfaceName = int_type;
-                       FormalParameters = parms;
-                       Get = get_block;
-                       Set = set_block;
                }
-                       
+
                public override bool Define (TypeContainer parent)
                {
                        PropertyAttributes prop_attr =
@@ -3638,14 +3734,6 @@ namespace Mono.CSharp {
                        if (!DoDefine (parent))
                                return false;
 
-                       Type [] parameters = FormalParameters.GetParameterInfo (parent);
-
-                       // Check if the and arguments were correct
-                       if ((parameters == null) || !CheckParameters (parent, parameters))
-                               return false;
-
-                       ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
-
                        IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
                        if (IndexerName == null)
                                IndexerName = "Item";
@@ -3663,11 +3751,14 @@ namespace Mono.CSharp {
                                Name = ShortName;
                        }
 
+                       if (!CheckBase (parent))
+                               return false;
+
                        if (Get != null){
-                                InternalParameters ip = new InternalParameters (parent, FormalParameters);
+                                InternalParameters ip = new InternalParameters (parent, Parameters);
 
                                GetData = new MethodData (this, "get", MemberType,
-                                                         parameters, ip, CallingConventions.Standard,
+                                                         ParameterTypes, ip, CallingConventions.Standard,
                                                          Get.OptAttributes, ModFlags, flags, false);
 
                                if (!GetData.Define (parent))
@@ -3677,12 +3768,12 @@ namespace Mono.CSharp {
                        }
                        
                        if (Set != null){
-                               int top = parameters.Length;
+                               int top = ParameterTypes.Length;
                                Type [] set_pars = new Type [top + 1];
-                               parameters.CopyTo (set_pars, 0);
+                               ParameterTypes.CopyTo (set_pars, 0);
                                set_pars [top] = MemberType;
 
-                               Parameter [] fixed_parms = FormalParameters.FixedParameters;
+                               Parameter [] fixed_parms = Parameters.FixedParameters;
 
                                if (fixed_parms == null){
                                        throw new Exception ("We currently do not support only array arguments in an indexer");
@@ -3724,7 +3815,7 @@ namespace Mono.CSharp {
                        //
                        // Now name the parameters
                        //
-                       Parameter [] p = FormalParameters.FixedParameters;
+                       Parameter [] p = Parameters.FixedParameters;
                        if (p != null) {
                                int i;
                                
@@ -3742,8 +3833,8 @@ namespace Mono.CSharp {
                                        SetBuilder.DefineParameter (
                                                i + 1, ParameterAttributes.None, "value");
                                        
-                               if (i != parameters.Length) {
-                                       Parameter array_param = FormalParameters.ArrayParameter;
+                               if (i != ParameterTypes.Length) {
+                                       Parameter array_param = Parameters.ArrayParameter;
                                        SetBuilder.DefineParameter (
                                                i + 1, array_param.Attributes, array_param.Name);
                                }
@@ -3760,10 +3851,9 @@ namespace Mono.CSharp {
                        // b) the indexer has a different IndexerName and this is no
                        //    explicit interface implementation.
                        //
-                       if (!IsImplementing ||
-                           (!IsExplicitImpl && (IndexerName != InterfaceIndexerName))){
+                       if (!IsExplicitImpl) {
                                PropertyBuilder = parent.TypeBuilder.DefineProperty (
-                                       IndexerName, prop_attr, MemberType, parameters);
+                                       IndexerName, prop_attr, MemberType, ParameterTypes);
 
                                if (GetData != null)
                                        PropertyBuilder.SetGetMethod (GetBuilder);
@@ -3771,29 +3861,12 @@ namespace Mono.CSharp {
                                if (SetData != null)
                                        PropertyBuilder.SetSetMethod (SetBuilder);
                                
-                               TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
+                               TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
+                                                            ParameterTypes);
                        }
 
                        return true;
                }
-
-               public void Emit (TypeContainer tc)
-               {
-                       //
-                       // The PropertyBuilder can be null for explicit implementations, in that
-                       // case, we do not actually emit the ".property", so there is nowhere to
-                       // put the attribute
-                       //
-                       if (PropertyBuilder != null)
-                               Attribute.ApplyAttributes (
-                                       ec, PropertyBuilder, this, OptAttributes, Location);
-
-                       if (GetData != null)
-                               GetData.Emit (tc, Get.Block, Get);
-
-                       if (SetData != null)
-                               SetData.Emit (tc, Set.Block, Set);
-               }
        }
 
        public class Operator : MemberCore {
@@ -3908,7 +3981,8 @@ namespace Mono.CSharp {
                        OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
                                                     new Parameters (param_list, null, Location),
                                                     OptAttributes, Mono.CSharp.Location.Null);
-                       
+
+                       OperatorMethod.IsOperator = true;                       
                        OperatorMethod.Define (parent);
 
                        if (OperatorMethod.MethodBuilder == null)
@@ -4051,12 +4125,22 @@ namespace Mono.CSharp {
                ///   from the current assembly and class
                /// </summary>
                public static MemberFilter inheritable_method_signature_filter;
+
+               /// <summary>
+               ///   This delegate is used to extract inheritable methods which
+               ///   have the same signature as the argument.  By inheritable,
+               ///   this means that we have permissions to override the method
+               ///   from the current assembly and class
+               /// </summary>
+               public static MemberFilter inheritable_property_signature_filter;
                
                static MethodSignature ()
                {
                        method_signature_filter = new MemberFilter (MemberSignatureCompare);
                        inheritable_method_signature_filter = new MemberFilter (
                                InheritableMemberSignatureCompare);
+                       inheritable_property_signature_filter = new MemberFilter (
+                               InheritablePropertySignatureCompare);
                }
                
                public MethodSignature (string name, Type ret_type, Type [] parameters)
@@ -4107,27 +4191,35 @@ namespace Mono.CSharp {
 
                static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
                {
-                       MethodInfo mi;
+                       MethodSignature sig = (MethodSignature) filter_criteria;
 
-                       if (! (m is MethodInfo))
+                       if (m.Name != sig.Name)
                                return false;
 
-                       MethodSignature sig = (MethodSignature) filter_criteria;
+                       Type ReturnType;
+                       MethodInfo mi = m as MethodInfo;
+                       PropertyInfo pi = m as PropertyInfo;
 
-                       if (m.Name != sig.Name)
+                       if (mi != null)
+                               ReturnType = mi.ReturnType;
+                       else if (pi != null)
+                               ReturnType = pi.PropertyType;
+                       else
                                return false;
                        
-                       mi = (MethodInfo) m;
-
                        //
                        // we use sig.RetType == null to mean `do not check the
                        // method return value.  
                        //
                        if (sig.RetType != null)
-                               if (mi.ReturnType != sig.RetType)
+                               if (ReturnType != sig.RetType)
                                        return false;
 
-                       Type [] args = TypeManager.GetArgumentTypes (mi);
+                       Type [] args;
+                       if (mi != null)
+                               args = TypeManager.GetArgumentTypes (mi);
+                       else
+                               args = TypeManager.GetArgumentTypes (pi);
                        Type [] sigp = sig.Parameters;
 
                        if (args.Length != sigp.Length)
@@ -4175,5 +4267,46 @@ namespace Mono.CSharp {
                        }
                        return false;
                }
+
+               //
+               // This filter should be used when we are requesting properties that
+               // we want to override.
+               //
+               // This makes a number of assumptions, for example
+               // that the methods being extracted are of a parent
+               // class (this means we know implicitly that we are
+               // being called to find out about members by a derived
+               // class).
+               // 
+               static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
+               {
+                       if (MemberSignatureCompare (m, filter_criteria)){
+                               PropertyInfo pi = (PropertyInfo) m;
+
+                               MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
+                               MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
+
+                               MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
+
+                               MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                               // If only accessible to the current class.
+                               if (prot == MethodAttributes.Private)
+                                       return false;
+
+                               // If only accessible to the defining assembly or 
+                               if (prot == MethodAttributes.FamANDAssem ||
+                                   prot == MethodAttributes.Assembly){
+                                       if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
+                                               return true;
+                                       else
+                                               return false;
+                               }
+
+                               // Anything else (FamOrAssembly and Public) is fine
+                               return true;
+                       }
+                       return false;
+               }
        }
 }
index 6cdb7a74d8a7013ff53517d8c006ecc323a6de3e..2eb2ab85708256bbe5fbeaff4f012dc0705c396e 100755 (executable)
@@ -876,7 +876,7 @@ method_body
        ;
 
 opt_formal_parameter_list
-       : /* empty */                   { $$ = Parameters.GetEmptyReadOnlyParameters (); }
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
        | formal_parameter_list
        ;
 
index d2327c607e0b85d59e412e4cffe3245eb5949e5d..377db34ae5898622b3ea3baf10ff7c4d26dfbde1 100755 (executable)
@@ -47,25 +47,21 @@ namespace Mono.CSharp {
                {
                        Report.Warning (
                                109, Location,
-                               "The member `" + parent.Name + "." + Name + "' does not hide an " +
+                               "The member " + parent.MakeName (Name) + " does not hide an " +
                                "inherited member.  The keyword new is not required");
                                                           
                }
 
-               static string MethodBaseName (MethodBase mb)
-               {
-                       return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
-               }
-
-               void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method)
+               void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
+                                                       string name)
                {
                        //
                        // FIXME: report the old/new permissions?
                        //
                        Report.Error (
-                               507, "`" + parent_method + "." + Name +
-                               ": can't change the access modifiers from `" +
-                               parent_method.DeclaringType.Name + "." + parent_method.Name + "'");
+                               507, Location, parent.MakeName (Name) +
+                               ": can't change the access modifiers when overriding inherited " +
+                               "member `" + name + "'");
                }
                
                //
@@ -75,8 +71,8 @@ namespace Mono.CSharp {
                // `name' is the user visible name for reporting errors (this is used to
                // provide the right name regarding method names and properties)
                //
-               protected bool CheckMethodAgainstBase (TypeContainer parent,
-                                                      MethodAttributes my_attrs, MethodInfo mb)
+               protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
+                                                      MethodInfo mb, string name)
                {
                        bool ok = true;
                        
@@ -84,8 +80,8 @@ namespace Mono.CSharp {
                                if (!(mb.IsAbstract || mb.IsVirtual)){
                                        Report.Error (
                                                506, Location, parent.MakeName (Name) +
-                                               ": cannot override inherited member " +
-                                               MethodBaseName (mb) + " because it is not " +
+                                               ": cannot override inherited member `" +
+                                               name + "' because it is not " +
                                                "virtual, abstract or override");
                                        ok = false;
                                }
@@ -94,8 +90,8 @@ namespace Mono.CSharp {
                                
                                if (mb.IsFinal) {
                                        Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
-                                                     "override inherited member " + MethodBaseName (mb) +
-                                                     " because it is sealed.");
+                                                     "override inherited member `" + name +
+                                                     "' because it is sealed.");
                                        ok = false;
                                }
 
@@ -106,7 +102,7 @@ namespace Mono.CSharp {
                                MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
 
                                if (thisp != parentp){
-                                       Error_CannotChangeAccessModifiers (parent, mb);
+                                       Error_CannotChangeAccessModifiers (parent, mb, name);
                                        ok = false;
                                }
                        }
@@ -116,12 +112,21 @@ namespace Mono.CSharp {
                                        if (Name != "Finalize" && (RootContext.WarningLevel >= 2)){
                                                Report.Warning (
                                                        114, Location, parent.MakeName (Name) + 
-                                                       " hides inherited member " + MethodBaseName (mb) +
-                                                       ".  To make the current member override that " +
+                                                       " hides inherited member `" + name +
+                                                       "'.  To make the current member override that " +
                                                        "implementation, add the override keyword, " +
                                                        "otherwise use the new keyword");
                                        }
                                }
+                       } else {
+                               if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
+                                       if (Name != "Finalize" && (RootContext.WarningLevel >= 1)){
+                                               Report.Warning (
+                                                       108, Location, "The keyword new is required on " +
+                                                       parent.MakeName (Name) + " because it hides " +
+                                                       "inherited member `" + name + "'");
+                                       }
+                               }
                        }
 
                        return ok;
index b94dc9caa5cef65050aa7c2e131e74bd0bdf8fd4..fd77a3f07cad3f0f6b8d99f7e828de19366f6448 100755 (executable)
@@ -378,7 +378,7 @@ namespace Mono.CSharp {
                                //
                                Type [] null_types = null;
                                InternalParameters inp = new InternalParameters
-                                       (null_types, Parameters.GetEmptyReadOnlyParameters ());
+                                       (null_types, Parameters.EmptyReadOnlyParameters);
                                
                                if (!RegisterMethod (get, inp, null)) {
                                        Error111 (ip);
index d72fb2f274cb5725273c10b05dacd8399146555c..ab125da9719db7706f4402dfa288341c340e9fd6 100755 (executable)
@@ -139,12 +139,13 @@ namespace Mono.CSharp {
                ///   This is used to reuse a set of empty parameters, because they
                ///   are common
                /// </summary>
-               public static Parameters GetEmptyReadOnlyParameters ()
-               {
-                       if (empty_parameters == null)
-                               empty_parameters = new Parameters (null, null, Location.Null);
+               public static Parameters EmptyReadOnlyParameters {
+                       get {
+                               if (empty_parameters == null)
+                                       empty_parameters = new Parameters (null, null, Location.Null);
                        
-                       return empty_parameters;
+                               return empty_parameters;
+                       }
                }
                
                public bool Empty {
index e193494f1d7a859542e0a0a336695f91809d0a21..72fa6d0ca928fd6083fdded94166da1fc5663b5e 100755 (executable)
@@ -196,6 +196,12 @@ public class TypeManager {
        // </remarks>
        static Hashtable method_arguments;
 
+       // <remarks>
+       //   Maps PropertyBuilder to a Type array that contains
+       //   the arguments to the indexer
+       // </remarks>
+       static Hashtable indexer_arguments;
+
        // <remarks>
        //   Maybe `method_arguments' should be replaced and only
        //   method_internal_params should be kept?
@@ -318,6 +324,7 @@ public class TypeManager {
                builder_to_method = new PtrHashtable ();
                method_arguments = new PtrHashtable ();
                method_internal_params = new PtrHashtable ();
+               indexer_arguments = new PtrHashtable ();
                builder_to_container = new PtrHashtable ();
                builder_to_ifaces = new PtrHashtable ();
                
@@ -1061,6 +1068,33 @@ public class TypeManager {
                        return types;
                }
        }
+
+       /// <summary>
+       ///    Returns the argument types for an indexer based on its PropertyInfo
+       ///
+       ///    For dynamic indexers, we use the compiler provided types, for
+       ///    indexers from existing assemblies we load them from GetParameters,
+       ///    and insert them into the cache
+       /// </summary>
+       static public Type [] GetArgumentTypes (PropertyInfo indexer)
+       {
+               if (indexer_arguments.Contains (indexer))
+                       return (Type []) indexer_arguments [indexer];
+               else {
+                       ParameterInfo [] pi = indexer.GetIndexParameters ();
+                       // Property, not an indexer.
+                       if (pi == null)
+                               return Type.EmptyTypes;
+                       int c = pi.Length;
+                       Type [] types = new Type [c];
+                       
+                       for (int i = 0; i < c; i++)
+                               types [i] = pi [i].ParameterType;
+
+                       indexer_arguments.Add (indexer, types);
+                       return types;
+               }
+       }
        
        // <remarks>
        //  This is a workaround the fact that GetValue is not
@@ -1166,7 +1200,17 @@ public class TypeManager {
 
                return true;
        }
-       
+
+       static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get, MethodBase set, Type[] args)
+       {
+               if (!RegisterProperty (pb, get,set))
+                       return false;
+
+               indexer_arguments.Add (pb, args);
+
+               return true;
+       }
+
        //
        // FIXME: we need to return the accessors depending on whether
        // they are visible or not.