2002-08-16 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / mcs / class.cs
index 9ed6a21e3e0be7b634d03489744b8169e58bd813..11d1b9be24a0a75746342c0c201dfe0186bebf01 100755 (executable)
@@ -1,3 +1,4 @@
+
 //
 // class.cs: Class and Struct handlers
 //
@@ -294,7 +295,7 @@ namespace Mono.CSharp {
                        
                        fields.Add (field);
                        
-                       if (field.Initializer != null){
+                       if (field.HasInitializer){
                                if ((field.ModFlags & Modifiers.STATIC) != 0){
                                        if (initialized_static_fields == null)
                                                initialized_static_fields = new ArrayList ();
@@ -518,16 +519,11 @@ namespace Mono.CSharp {
 
                        if (fields == null)
                                return true;
-                       
-                       foreach (Field f in fields){
-                               Object init = f.Initializer;
 
-                               Expression e;
-                               if (init is Expression)
-                                       e = (Expression) init;
-                               else {
-                                       e = new ArrayCreation (f.Type, "", (ArrayList)init, f.Location);
-                               }
+                       foreach (Field f in fields){
+                               Expression e = f.GetInitializerExpression (ec);
+                               if (e == null)
+                                       return false;
 
                                Location l = f.Location;
                                FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
@@ -544,7 +540,7 @@ namespace Mono.CSharp {
                                        throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
                                }
                        }
-                       
+
                        return true;
                }
                
@@ -557,8 +553,10 @@ namespace Mono.CSharp {
                        int mods = 0;
 
                        c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
-                                            new ConstructorBaseInitializer (null, new Location (-1)),
-                                            new Location (-1));
+                                            new ConstructorBaseInitializer (
+                                                    null, Parameters.EmptyReadOnlyParameters,
+                                                    Location.Null),
+                                            Location.Null);
                        
                        if (is_static)
                                mods = Modifiers.STATIC;
@@ -958,14 +956,14 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Populates our TypeBuilder with fields and methods
                /// </summary>
-               public override bool Define (TypeContainer parent)
+               public override bool DefineMembers (TypeContainer parent)
                {
                        MemberInfo [] defined_names = null;
 
                        if (interface_order != null){
                                foreach (Interface iface in interface_order)
                                        if ((iface.ModFlags & Modifiers.NEW) == 0)
-                                               iface.Define (this);
+                                               iface.DefineMembers (this);
                                        else
                                                Report1530 (iface.Location);
                        }
@@ -979,7 +977,7 @@ namespace Mono.CSharp {
                                //
                                ptype = TypeBuilder.BaseType;
                                if (ptype != null){
-                                       defined_names = FindMembers (
+                                       defined_names = (MemberInfo []) FindMembers (
                                                ptype, MemberTypes.All & ~MemberTypes.Constructor,
                                                BindingFlags.Public | BindingFlags.Instance |
                                                BindingFlags.Static, null, null);
@@ -1055,6 +1053,17 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public override bool Define (TypeContainer parent)
+               {
+                       if (interface_order != null){
+                               foreach (Interface iface in interface_order)
+                                       if ((iface.ModFlags & Modifiers.NEW) == 0)
+                                               iface.Define (this);
+                       }
+
+                       return true;
+               }
+
                /// <summary>
                ///   This function is based by a delegate to the FindMembers routine
                /// </summary>
@@ -1100,8 +1109,8 @@ namespace Mono.CSharp {
                //
                // Since the whole process is a no-op, it is fine to check for null here.
                //
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
-                                                 MemberFilter filter, object criteria)
+               internal override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                         MemberFilter filter, object criteria)
                {
                        ArrayList members = new ArrayList ();
                        bool priv = (bf & BindingFlags.NonPublic) != 0;
@@ -1273,34 +1282,24 @@ namespace Mono.CSharp {
                        // Lookup members in parent if requested.
                        //
                        if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
-                               MemberInfo [] mi;
-
-                               mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
-                               if (mi != null)
-                                       members.AddRange (mi);
-                       }
-                       
-                       int count = members.Count;
-                       if (count > 0){
-                               MemberInfo [] mi = new MemberInfo [count];
-                               members.CopyTo (mi);
-                               return mi;
+                               MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
+                               members.AddRange (list);
                        }
 
-                       return null;
+                       return new MemberList (members);
                }
 
                
 
-               public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
-                                                        MemberFilter filter, object criteria)
+               public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                     MemberFilter filter, object criteria)
                {
                        TypeContainer tc = TypeManager.LookupTypeContainer (t);
 
                        if (tc != null)
                                return tc.FindMembers (mt, bf, filter, criteria);
                        else
-                               return t.FindMembers (mt, bf, filter, criteria);
+                               return new MemberList (t.FindMembers (mt, bf, filter, criteria));
                }
 
                //
@@ -1651,7 +1650,7 @@ namespace Mono.CSharp {
                //
                public bool AsAccessible (Type parent, int flags)
                {
-                       while (parent.HasElementType)
+                       while (parent.IsArray || parent.IsPointer || parent.IsByRef)
                                parent = parent.GetElementType ();
 
                        AccessLevel level = GetAccessLevel (flags);
@@ -1699,6 +1698,12 @@ namespace Mono.CSharp {
                {
                        Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
                }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return null;
+                       }
+               }
        }
 
        public class Class : TypeContainer {
@@ -2004,7 +2009,7 @@ namespace Mono.CSharp {
 
                        MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
                        if (!IsOperator) {
-                               MemberInfo [] mi_this;
+                               MemberList mi_this;
 
                                mi_this = TypeContainer.FindMembers (
                                        parent.TypeBuilder, MemberTypes.Method,
@@ -2013,7 +2018,7 @@ namespace Mono.CSharp {
                                        BindingFlags.DeclaredOnly,
                                        MethodSignature.method_signature_filter, ms);
 
-                               if (mi_this != null && mi_this.Length > 0) {
+                               if (mi_this.Count > 0) {
                                        Report.Error (111, Location, "Class `" + parent.Name + "' " +
                                                      "already defines a member called `" + Name + "' " +
                                                      "with the same parameter types");
@@ -2029,7 +2034,7 @@ namespace Mono.CSharp {
 
                        // ptype is only null for System.Object while compiling corlib.
                        if (ptype != null){
-                               MemberInfo [] mi, mi_static, mi_instance;
+                               MemberList mi, mi_static, mi_instance;
 
                                mi_static = TypeContainer.FindMembers (
                                        ptype, MemberTypes.Method,
@@ -2042,14 +2047,14 @@ namespace Mono.CSharp {
                                        MethodSignature.inheritable_method_signature_filter,
                                        ms);
 
-                               if (mi_instance != null && mi_instance.Length > 0){
+                               if (mi_instance.Count > 0){
                                        mi = mi_instance;
-                               } else if (mi_static != null && mi_static.Length > 0)
+                               } else if (mi_static.Count > 0)
                                        mi = mi_static;
                                else
                                        mi = null;
 
-                               if (mi != null && mi.Length > 0){
+                               if (mi != null && mi.Count > 0){
                                        parent_method = (MethodInfo) mi [0];
                                        string name = parent_method.DeclaringType.Name + "." +
                                                parent_method.Name;
@@ -2141,12 +2146,15 @@ namespace Mono.CSharp {
        public abstract class ConstructorInitializer {
                ArrayList argument_list;
                ConstructorInfo parent_constructor;
-               Location location;
+               Parameters parameters;
+               Location loc;
                
-               public ConstructorInitializer (ArrayList argument_list, Location location)
+               public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
+                                              Location loc)
                {
                        this.argument_list = argument_list;
-                       this.location = location;
+                       this.parameters = parameters;
+                       this.loc = loc;
                }
 
                public ArrayList Arguments {
@@ -2159,44 +2167,48 @@ namespace Mono.CSharp {
                {
                        Expression parent_constructor_group;
                        Type t;
-                       
+
+                       ec.CurrentBlock = new Block (null, true, parameters);
+
                        if (argument_list != null){
                                foreach (Argument a in argument_list){
-                                       if (!a.Resolve (ec, location))
+                                       if (!a.Resolve (ec, loc))
                                                return false;
                                }
                        }
 
+                       ec.CurrentBlock = null;
+
                        if (this is ConstructorBaseInitializer) {
                                if (ec.ContainerType.BaseType == null)
                                        return true;
 
                                t = ec.ContainerType.BaseType;
                                if (ec.ContainerType.IsValueType) {
-                                       Report.Error (522, location,
+                                       Report.Error (522, loc,
                                                "structs cannot call base class constructors");
                                        return false;
                                }
                        } else
                                t = ec.ContainerType;
-                       
+
                        parent_constructor_group = Expression.MemberLookup (
-                               ec, t, ".ctor", 
+                               ec, t, t, ".ctor", 
                                MemberTypes.Constructor,
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
-                               location);
+                               loc);
                        
                        if (parent_constructor_group == null){
-                               Report.Error (1501, location,
+                               Report.Error (1501, loc,
                                       "Can not find a constructor for this argument list");
                                return false;
                        }
                        
                        parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
-                               (MethodGroupExpr) parent_constructor_group, argument_list, location);
+                               (MethodGroupExpr) parent_constructor_group, argument_list, loc);
                        
                        if (parent_constructor == null){
-                               Report.Error (1501, location,
+                               Report.Error (1501, loc,
                                       "Can not find a constructor for this argument list");
                                return false;
                        }
@@ -2216,13 +2228,15 @@ namespace Mono.CSharp {
        }
 
        public class ConstructorBaseInitializer : ConstructorInitializer {
-               public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+               public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
+                       base (argument_list, pars, l)
                {
                }
        }
 
        public class ConstructorThisInitializer : ConstructorInitializer {
-               public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+               public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
+                       base (argument_list, pars, l)
                {
                }
        }
@@ -2322,7 +2336,8 @@ namespace Mono.CSharp {
 
                        if ((ModFlags & Modifiers.STATIC) == 0){
                                if (parent is Class && Initializer == null)
-                                       Initializer = new ConstructorBaseInitializer (null, parent.Location);
+                                       Initializer = new ConstructorBaseInitializer (
+                                               null, Parameters.EmptyReadOnlyParameters, parent.Location);
 
 
                                //
@@ -2352,6 +2367,12 @@ namespace Mono.CSharp {
 
                        Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
 
+                       // If this is a non-static `struct' constructor and doesn't have any
+                       // initializer, it must initialize all of the struct's fields.
+                       if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
+                           (Initializer == null))
+                               Block.AddThisVariable (parent, Location);
+
                        ec.EmitTopBlock (Block, ParameterInfo, Location);
                }
        }
@@ -3014,7 +3035,6 @@ namespace Mono.CSharp {
        // their common bits.  This is also used to flag usage of the field
        //
        abstract public class FieldBase : MemberBase {
-               public readonly Object Initializer;
                public FieldBuilder  FieldBuilder;
                public Status status;
 
@@ -3028,7 +3048,45 @@ namespace Mono.CSharp {
                                     object init, Attributes attrs, Location loc)
                        : base (type, mod, allowed_mod, name, attrs, loc)
                {
-                       Initializer = init;
+                       this.init = init;
+               }
+
+               //
+               // Whether this field has an initializer.
+               //
+               public bool HasInitializer {
+                       get {
+                               return init != null;
+                       }
+               }
+
+               // Private.
+               readonly Object init;
+               Expression init_expr;
+               bool init_expr_initialized = false;
+
+               //
+               // Resolves and returns the field initializer.
+               //
+               public Expression GetInitializerExpression (EmitContext ec)
+               {
+                       if (init_expr_initialized)
+                               return init_expr;
+
+                       Expression e;
+                       if (init is Expression)
+                               e = (Expression) init;
+                       else
+                               e = new ArrayCreation (Type, "", (ArrayList)init, Location);
+
+                       ec.IsFieldInitializer = true;
+                       e = e.DoResolve (ec);
+                       ec.IsFieldInitializer = false;
+
+                       init_expr = e;
+                       init_expr_initialized = true;
+
+                       return init_expr;
                }
        }
 
@@ -3079,9 +3137,7 @@ namespace Mono.CSharp {
 
                                // ptype is only null for System.Object while compiling corlib.
                                if (ptype != null){
-                                       MemberInfo [] mi;
-                                       
-                                       mi = TypeContainer.FindMembers (
+                                       TypeContainer.FindMembers (
                                                ptype, MemberTypes.Method,
                                                BindingFlags.Public |
                                                BindingFlags.Static | BindingFlags.Instance,
@@ -3186,7 +3242,7 @@ namespace Mono.CSharp {
                                return false;
 
                        MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
-                       MemberInfo [] props_this;
+                       MemberList props_this;
 
                        props_this = TypeContainer.FindMembers (
                                parent.TypeBuilder, MemberTypes.Property,
@@ -3195,7 +3251,7 @@ namespace Mono.CSharp {
                                BindingFlags.DeclaredOnly,
                                MethodSignature.method_signature_filter, ms);
 
-                       if (props_this != null && props_this.Length > 0) {
+                       if (props_this.Count > 0) {
                                Report.Error (111, Location, "Class `" + parent.Name + "' " +
                                              "already defines a member called `" + Name + "' " +
                                              "with the same parameter types");
@@ -3205,13 +3261,13 @@ namespace Mono.CSharp {
                        //
                        // Find properties with the same name on the base class
                        //
-                       MemberInfo [] props;
-                       MemberInfo [] props_static = TypeContainer.FindMembers (
+                       MemberList props;
+                       MemberList 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 (
+                       MemberList props_instance = TypeContainer.FindMembers (
                                parent.TypeBuilder.BaseType, MemberTypes.Property,
                                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
                                MethodSignature.inheritable_property_signature_filter,
@@ -3220,16 +3276,16 @@ namespace Mono.CSharp {
                        //
                        // Find if we have anything
                        //
-                       if (props_static != null && props_static.Length > 0)
+                       if (props_static.Count > 0)
                                props = props_static;
-                       else if (props_instance != null && props_instance.Length > 0)
+                       else if (props_instance.Count > 0)
                                props = props_instance;
                        else
                                props = null;
 
                        //
                        // If we have something on the base.
-                       if (props != null && props.Length > 0){
+                       if (props != null && props.Count > 0){
                                PropertyInfo pi = (PropertyInfo) props [0];
 
                                MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);