2005-12-23 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / mcs / class.cs
index 2f0396d9af41519759fb6b06440def8f5deff26a..4a723460b316d334c973294378151ef994f5aaa1 100644 (file)
@@ -614,9 +614,6 @@ namespace Mono.CSharp {
 
                        fields.Add (field);
 
-                       if (field.HasInitializer)
-                               RegisterFieldForInitialization (field);
-                       
                        if ((field.ModFlags & Modifiers.STATIC) != 0)
                                return;
 
@@ -864,71 +861,40 @@ namespace Mono.CSharp {
                        }
                }
 
-               public virtual void RegisterFieldForInitialization (FieldMember field)
+               public virtual void RegisterFieldForInitialization (FieldBase field)
                {
                        if ((field.ModFlags & Modifiers.STATIC) != 0){
                                if (initialized_static_fields == null)
-                                       initialized_static_fields = new ArrayList ();
+                                       initialized_static_fields = new ArrayList (4);
 
                                initialized_static_fields.Add (field);
                        } else {
                                if (initialized_fields == null)
-                                       initialized_fields = new ArrayList ();
+                                       initialized_fields = new ArrayList (4);
 
                                initialized_fields.Add (field);
                        }
                }
 
-               bool CanElideInitializer (Type field_type, Constant c)
-               {
-                       if (field_type == c.Type)
-                               return true;
-                       if (TypeManager.IsValueType (field_type) || TypeManager.HasElementType (field_type))
-                               return false;
-                       // Reference type with null initializer.
-                       return c.Type == TypeManager.null_type;
-               }
-
                //
                // Emits the instance field initializers
                //
                public virtual bool EmitFieldInitializers (EmitContext ec)
                {
                        ArrayList fields;
-                       Expression instance_expr;
                        
                        if (ec.IsStatic){
                                fields = initialized_static_fields;
-                               instance_expr = null;
                        } else {
                                fields = initialized_fields;
-                               instance_expr = new This (Location.Null).Resolve (ec);
                        }
 
                        if (fields == null)
                                return true;
 
-                       foreach (FieldMember f in fields){
-                               Expression e = f.GetInitializerExpression (ec);
-                               if (e == null)
-                                       return false;
-
-                               Location l = f.Location;
-                               FieldExpr fe = new FieldExpr (f.FieldBuilder, l, true);
-                               fe.InstanceExpression = instance_expr;
-                               ExpressionStatement a = new Assign (fe, e, l);
-
-                               a = a.ResolveStatement (ec);
-                               if (a == null)
-                                       return false;
-
-                               Constant c = e as Constant;
-                               if (c != null && c.IsDefaultValue && CanElideInitializer (f.MemberType, c))
-                                       continue;
-
-                               a.EmitStatement (ec);
+                       foreach (FieldBase f in fields) {
+                               f.EmitInitializer (ec);
                        }
-
                        return true;
                }
                
@@ -1408,12 +1374,12 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Populates our TypeBuilder with fields and methods
                /// </summary>
-               public override bool DefineMembers (TypeContainer container)
+               public override bool DefineMembers ()
                {
                        if (members_defined)
                                return members_defined_ok;
 
-                       if (!base.DefineMembers (container))
+                       if (!base.DefineMembers ())
                                return false;
 
                        members_defined_ok = DoDefineMembers ();
@@ -1470,7 +1436,7 @@ namespace Mono.CSharp {
 
                        if (parts != null) {
                                foreach (ClassPart part in parts) {
-                                       if (!part.DefineMembers (this))
+                                       if (!part.DefineMembers ())
                                                return false;
                                }
                        }
@@ -1508,7 +1474,7 @@ namespace Mono.CSharp {
                                }
 
                                foreach (Iterator iterator in iterators) {
-                                       if (!iterator.DefineMembers (this))
+                                       if (!iterator.DefineMembers ())
                                                return false;
                                }
                        }
@@ -1579,7 +1545,7 @@ namespace Mono.CSharp {
                {
                        ArrayList members = new ArrayList ();
 
-                       DefineMembers (null);
+                       DefineMembers ();
 
                        if (methods != null) {
                                int len = methods.Count;
@@ -2486,6 +2452,15 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               public virtual void Mark_HasEquals ()
+               {
+                       Methods.HasEquals = true;
+               }
+
+               public virtual void Mark_HasGetHashCode ()
+               {
+                       Methods.HasGetHashCode = true;
+               }
 
                //
                // IMemberContainer
@@ -2750,7 +2725,7 @@ namespace Mono.CSharp {
                }
 
 
-               public override void RegisterFieldForInitialization (FieldMember field)
+               public override void RegisterFieldForInitialization (FieldBase field)
                {
                        PartialContainer.RegisterFieldForInitialization (field);
                }
@@ -2776,6 +2751,15 @@ namespace Mono.CSharp {
                        throw new InternalErrorException ("Should not get here");
                }
 
+               public override void Mark_HasEquals ()
+               {
+                       PartialContainer.Mark_HasEquals ();
+               }
+
+               public override void Mark_HasGetHashCode ()
+               {
+                       PartialContainer.Mark_HasGetHashCode ();
+               }
        }
 
        public abstract class ClassOrStruct : TypeContainer {
@@ -3255,12 +3239,10 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               if (RootContext.WarningLevel > 2) {
-                                       if (Name == "Equals" && Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type)
-                                               Parent.Methods.HasEquals = true;
-                                       else if (Name == "GetHashCode" && Parameters.Empty)
-                                               Parent.Methods.HasGetHashCode = true;
-                               }
+                               if (Name == "Equals" && Parameters.Count == 1 && ParameterTypes [0] == TypeManager.object_type)
+                                       Parent.Mark_HasEquals ();
+                               else if (Name == "GetHashCode" && Parameters.Empty)
+                                       Parent.Mark_HasGetHashCode ();
 
                                if ((ModFlags & Modifiers.OVERRIDE) != 0) {
                                        ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
@@ -3855,7 +3837,7 @@ namespace Mono.CSharp {
                                }
 
                                for (int i = 0; i < ParameterInfo.Count; ++i) {
-                                       if ((ParameterInfo.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
+                                       if ((ParameterInfo.ParameterModifier (i) & Parameter.Modifier.OUTMASK) != 0) {
                                                Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
                                                return;
                                        }
@@ -4460,6 +4442,8 @@ namespace Mono.CSharp {
                public override void Emit ()
                {
                        EmitContext ec = CreateEmitContext (null, null);
+                       if (GetObsoleteAttribute () != null || Parent.GetObsoleteAttribute () != null)
+                               ec.TestObsoleteMethodUsage = false;
 
                        // If this is a non-static `struct' constructor and doesn't have any
                        // initializer, it must initialize all of the struct's fields.
@@ -4508,9 +4492,6 @@ namespace Mono.CSharp {
                                }
                        }
                        if (Initializer != null) {
-                               if (GetObsoleteAttribute () != null || Parent.GetObsoleteAttribute () != null)
-                                       ec.TestObsoleteMethodUsage = false;
-
                                Initializer.Emit (ec);
                        }
                        
@@ -4985,9 +4966,11 @@ namespace Mono.CSharp {
                //
                public string ShortName {
                        get { return MemberName.Name; }
-                       set {
-                               SetMemberName (new MemberName (MemberName.Left, value, Location));
-                       }
+                       set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
+               }
+
+               public new TypeContainer Parent {
+                       get { return (TypeContainer) base.Parent; }
                }
 
                //
@@ -5182,6 +5165,7 @@ namespace Mono.CSharp {
        abstract public class FieldBase : MemberBase {
                public FieldBuilder  FieldBuilder;
                public Status status;
+               protected Expression initializer;
 
                [Flags]
                public enum Status : byte {
@@ -5195,16 +5179,11 @@ namespace Mono.CSharp {
                /// </summary>
                public MemberInfo conflict_symbol;
 
-               //
-               // The constructor is only exposed to our children
-               //
                protected FieldBase (TypeContainer parent, Expression type, int mod,
-                                    int allowed_mod, MemberName name, object init,
-                                    Attributes attrs)
+                                    int allowed_mod, MemberName name, Attributes attrs)
                        : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
                                name, attrs)
                {
-                       this.init = init;
                }
 
                public override AttributeTargets AttributeTargets {
@@ -5231,52 +5210,43 @@ namespace Mono.CSharp {
                        FieldBuilder.SetCustomAttribute (cb);
                }
 
-               //
-               // Whether this field has an initializer.
-               //
-               public bool HasInitializer {
-                       get {
-                               return init != null;
-                       }
-               }
+               public void EmitInitializer (EmitContext ec)
+               {
+                       // Replace DeclSpace because of partial classes
+                       ec.DeclSpace = EmitContext.DeclSpace;
 
-               protected readonly Object init;
+                       ec.IsFieldInitializer = true;
+                       initializer = initializer.Resolve (ec);
+                       ec.IsFieldInitializer = false;
+                       if (initializer == null)
+                               return;
 
-               // Private.
-               Expression init_expr;
-               bool init_expr_initialized = false;
+                       FieldExpr fe = new FieldExpr (FieldBuilder, Location, true);
+                       if ((ModFlags & Modifiers.STATIC) == 0)
+                               fe.InstanceExpression = new This (Location).Resolve (ec);
 
-               //
-               // Resolves and returns the field initializer.
-               //
-               public Expression GetInitializerExpression (EmitContext ec)
-               {
-                       if (init_expr_initialized)
-                               return init_expr;
+                       ExpressionStatement a = new Assign (fe, initializer, Location);
 
-                       Expression e;
-                       if (init is Expression)
-                               e = (Expression) init;
-                       else
-                               e = new ArrayCreation (Type, "", (ArrayList)init, Location);
+                       a = a.ResolveStatement (ec);
+                       if (a == null)
+                               return;
 
-                       // TODO: Any reason why we are using parent EC ?
-                       EmitContext parent_ec = Parent.EmitContext;
+                       Constant c = initializer as Constant;
+                       if (c != null && CanElideInitializer (c))
+                               return;
 
-                       bool old_is_static = parent_ec.IsStatic;
-                       bool old_is_ctor = parent_ec.IsConstructor;
-                       parent_ec.IsStatic = ec.IsStatic;
-                       parent_ec.IsConstructor = ec.IsConstructor;
-                       parent_ec.IsFieldInitializer = true;
-                       e = e.DoResolve (parent_ec);
-                       parent_ec.IsFieldInitializer = false;
-                       parent_ec.IsStatic = old_is_static;
-                       parent_ec.IsConstructor = old_is_ctor;
+                       a.EmitStatement (ec);
+               }
 
-                       init_expr = e;
-                       init_expr_initialized = true;
+               bool CanElideInitializer (Constant c)
+               {
+                       if (MemberType == c.Type)
+                               return c.IsDefaultValue;
 
-                       return init_expr;
+                       if (c.Type == TypeManager.null_type)
+                               return true;
+
+                       return false;
                }
 
                protected override bool CheckBase ()
@@ -5305,6 +5275,15 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               public Expression Initializer {
+                       set {
+                               if (value != null) {
+                                       this.initializer = value;
+                                       Parent.RegisterFieldForInitialization (this);
+                               }
+                       }
+               }
+
                protected virtual bool IsFieldClsCompliant {
                        get {
                                if (FieldBuilder == null)
@@ -5338,11 +5317,11 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class FieldMember: FieldBase
+       public abstract class FieldMember : FieldBase
        {
                protected FieldMember (TypeContainer parent, Expression type, int mod,
-                       int allowed_mod, MemberName name, object init, Attributes attrs)
-                       : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, init, attrs)
+                       int allowed_mod, MemberName name, Attributes attrs)
+                       : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, attrs)
                {
                        if ((mod & Modifiers.ABSTRACT) != 0)
                                Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
@@ -5469,7 +5448,7 @@ namespace Mono.CSharp {
        /// <summary>
        /// Fixed buffer implementation
        /// </summary>
-       public class FixedField: FieldMember, IFixedBuffer
+       public class FixedField : FieldMember, IFixedBuffer
        {
                public const string FixedElementName = "FixedElementField";
                static int GlobalCounter = 0;
@@ -5490,7 +5469,7 @@ namespace Mono.CSharp {
 
                public FixedField (TypeContainer parent, Expression type, int mod, string name,
                        Expression size_expr, Attributes attrs, Location loc):
-                       base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), null, attrs)
+                       base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), attrs)
                {
                        if (RootContext.Version == LanguageVersion.ISO_1)
                                Report.FeatureIsNotStandardized (loc, "fixed size buffers");
@@ -5620,9 +5599,9 @@ namespace Mono.CSharp {
                        Modifiers.READONLY;
 
                public Field (TypeContainer parent, Expression type, int mod, string name,
-                             Object expr_or_array_init, Attributes attrs, Location loc)
+                             Attributes attrs, Location loc)
                        : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
-                               expr_or_array_init, attrs)
+                               attrs)
                {
                }
 
@@ -6133,8 +6112,7 @@ namespace Mono.CSharp {
                                // Setup iterator if we are one
                                //
                                if (yields) {
-                                       Iterator iterator = new Iterator (this,
-                                               Parent, ModFlags);
+                                       Iterator iterator = new Iterator (this, Parent as TypeContainer, ModFlags);
                                        
                                        if (!iterator.DefineIterator ())
                                                return null;
@@ -6647,9 +6625,9 @@ namespace Mono.CSharp {
                static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
 
                public EventProperty (TypeContainer parent, Expression type, int mod_flags,
-                                     bool is_iface, MemberName name, Object init,
+                                     bool is_iface, MemberName name,
                                      Attributes attrs, Accessor add, Accessor remove)
-                       : base (parent, type, mod_flags, is_iface, name, init, attrs)
+                       : base (parent, type, mod_flags, is_iface, name, attrs)
                {
                        Add = new AddDelegateMethod (this, add);
                        Remove = new RemoveDelegateMethod (this, remove);
@@ -6669,15 +6647,15 @@ namespace Mono.CSharp {
        /// <summary>
        /// Event is declared like field.
        /// </summary>
-       public class EventField: Event {
+       public class EventField : Event {
 
                static string[] attribute_targets = new string [] { "event", "field", "method" };
                static string[] attribute_targets_interface = new string[] { "event", "method" };
 
                public EventField (TypeContainer parent, Expression type, int mod_flags,
-                                  bool is_iface, MemberName name, Object init,
+                                  bool is_iface, MemberName name,
                                   Attributes attrs)
-                       : base (parent, type, mod_flags, is_iface, name, init, attrs)
+                       : base (parent, type, mod_flags, is_iface, name, attrs)
                {
                        Add = new AddDelegateMethod (this);
                        Remove = new RemoveDelegateMethod (this);
@@ -6699,6 +6677,22 @@ namespace Mono.CSharp {
                        base.ApplyAttributeBuilder (a, cb);
                }
 
+               public override bool Define()
+               {
+                       if (!base.Define ())
+                               return false;
+
+                       if (initializer != null) {
+                               if (((ModFlags & Modifiers.ABSTRACT) != 0)) {
+                                       Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
+                                               GetSignatureForError ());
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
                public override string[] ValidAttributeTargets {
                        get {
                                return IsInterface ? attribute_targets_interface : attribute_targets;
@@ -6895,11 +6889,11 @@ namespace Mono.CSharp {
                public MethodBuilder AddBuilder, RemoveBuilder;
                Parameters parameters;
 
-               public Event (TypeContainer parent, Expression type, int mod_flags,
-                             bool is_iface, MemberName name, Object init, Attributes attrs)
+               protected Event (TypeContainer parent, Expression type, int mod_flags,
+                             bool is_iface, MemberName name, Attributes attrs)
                        : base (parent, type, mod_flags,
                                is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
-                               name, init, attrs)
+                               name, attrs)
                {
                        IsInterface = is_iface;
                }
@@ -6932,12 +6926,6 @@ namespace Mono.CSharp {
 
                        if (!DoDefine ())
                                return false;
-
-                       if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
-                               Report.Error (74, Location, "`" + GetSignatureForError () +
-                                             "': abstract event cannot have an initializer");
-                               return false;
-                       }
                        
                        if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
                                Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());