**** Merged r40732-r40872 from MCS ****
[mono.git] / mcs / gmcs / class.cs
index 4162d78065bf9d763a790e028271cc3e087aa921..568fe966540b13b7a4cb02e3f7b72e9a2108d128 100644 (file)
@@ -581,7 +581,7 @@ namespace Mono.CSharp {
                        interfaces.Add (iface);
                }
 
-               public void AddField (Field field)
+               public void AddField (FieldMember field)
                {
                        if (!AddToMemberContainer (field))
                                return;
@@ -866,6 +866,14 @@ namespace Mono.CSharp {
                                if (a == null)
                                        return false;
 
+                               if (RootContext.Optimize) {
+                                       Constant c = e as Constant;
+                                       if (c != null) {
+                                               if (c.IsDefaultValue)
+                                                       continue;
+                                       }
+                               }
+
                                a.EmitStatement (ec);
                        }
 
@@ -1254,14 +1262,18 @@ namespace Mono.CSharp {
                                        CurrentTypeParameters [i - offset].DefineConstraints ();
 
                                current_type = new ConstructedType (Name, TypeParameters, Location);
-                       }
 
-                       if (IsGeneric) {
-                               foreach (TypeParameter type_param in TypeParameters)
+                               foreach (TypeParameter type_param in TypeParameters) {
                                        if (!type_param.DefineType (ec)) {
                                                error = true;
                                                return null;
                                        }
+                               }
+
+                               if (!CheckConstraints (ec)) {
+                                       error = true;
+                                       return null;
+                               }
                        }
 
                        if ((Kind == Kind.Struct) && TypeManager.value_type == null)
@@ -1377,6 +1389,11 @@ namespace Mono.CSharp {
                        return TypeBuilder;
                }
 
+               protected virtual bool CheckConstraints (EmitContext ec)
+               {
+                       return true;
+               }
+
                protected virtual bool DefineNestedTypes ()
                {
                        if (Interfaces != null) {
@@ -1461,15 +1478,6 @@ namespace Mono.CSharp {
 
                protected virtual bool DoDefineMembers ()
                {
-                       //
-                       // We need to be able to use the member cache while we are checking/defining
-                       //
-                       if (TypeBuilder.BaseType != null)
-                               base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
-
-                       if (TypeBuilder.IsInterface)
-                               base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
-
                        if (IsTopLevel) {
                                if ((ModFlags & Modifiers.NEW) != 0)
                                        Error_KeywordNotAllowed (Location);
@@ -1497,7 +1505,7 @@ namespace Mono.CSharp {
                        DefineContainerMembers (constants);
                        DefineContainerMembers (fields);
 
-                       if ((Kind == Kind.Class) && !(this is ClassPart) && !(this is StaticClass)){
+                       if ((Kind == Kind.Class) && !(this is ClassPart)){
                                if ((instance_constructors == null) &&
                                    !(this is StaticClass)) {
                                        if (default_constructor == null)
@@ -1762,7 +1770,7 @@ namespace Mono.CSharp {
                                if (fields != null) {
                                        int len = fields.Count;
                                        for (int i = 0; i < len; i++) {
-                                               Field f = (Field) fields [i];
+                                               FieldMember f = (FieldMember) fields [i];
                                                
                                                if ((f.ModFlags & modflags) == 0)
                                                        continue;
@@ -1790,6 +1798,10 @@ namespace Mono.CSharp {
                                                        continue;
 
                                                FieldBuilder fb = con.FieldBuilder;
+                                               if (fb == null) {
+                                                       if (con.Define ())
+                                                               fb = con.FieldBuilder;
+                                               }
                                                if (fb != null && filter (fb, criteria) == true) {
                                                        if (members == null)
                                                                members = new ArrayList ();
@@ -1977,6 +1989,9 @@ namespace Mono.CSharp {
                                                        continue;
 
                                                TypeBuilder tb = t.TypeBuilder;
+                                               if (tb == null)
+                                                       tb = t.DefineType ();
+
                                                if (tb != null && (filter (tb, criteria) == true)) {
                                                        if (members == null)
                                                                members = new ArrayList ();
@@ -2216,7 +2231,7 @@ namespace Mono.CSharp {
                        }
                        
                        if (fields != null)
-                               foreach (Field f in fields)
+                               foreach (FieldMember f in fields)
                                        f.Emit ();
 
                        if (events != null){
@@ -2579,6 +2594,12 @@ namespace Mono.CSharp {
 
                public virtual MemberCache BaseCache {
                        get {
+                               if (base_cache != null)
+                                       return base_cache;
+                               if (TypeBuilder.BaseType != null)
+                                       base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
+                               if (TypeBuilder.IsInterface)
+                                       base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
                                return base_cache;
                        }
                }
@@ -2629,6 +2650,30 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               if (pc.IsGeneric) {
+                                       if (pc.CountTypeParameters != member_name.CountTypeArguments) {
+                                               Report.Error (
+                                                       264, loc, "Partial declarations of `{0}' " +
+                                                       "must have the same type parameter names in " +
+                                                       "the same order", member_name.GetTypeName ());
+                                               return null;
+                                       }
+
+                                       string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
+                                       string[] names = member_name.TypeArguments.GetDeclarations ();
+
+                                       for (int i = 0; i < pc.CountTypeParameters; i++) {
+                                               if (pc_names [i] == names [i])
+                                                       continue;
+
+                                               Report.Error (
+                                                       264, loc, "Partial declarations of `{0}' " +
+                                                       "must have the same type parameter names in " +
+                                                       "the same order", member_name.GetTypeName ());
+                                               return null;
+                                       }
+                               }
+
                                return pc;
                        }
 
@@ -2636,6 +2681,8 @@ namespace Mono.CSharp {
                        RootContext.Tree.RecordDecl (full_name, pc);
                        parent.AddType (pc);
                        pc.Register ();
+                       // This is needed to define our type parameters; we define the constraints later.
+                       pc.SetParameterInfo (null);
                        return pc;
                }
 
@@ -2706,6 +2753,78 @@ namespace Mono.CSharp {
                        return PendingImplementation.GetPendingImplementations (this);
                }
 
+               ArrayList constraints_lists;
+
+               public void UpdateConstraints (ArrayList constraints_list)
+               {
+                       //
+                       // This is called for each ClassPart in a partial generic type declaration.
+                       //
+                       // If no constraints were specified for the part, just return.
+                       // Otherwise, if we're called with constraints for the first time, they become
+                       // the type's constraint.  If we're called with constraints again, we just
+                       // store them somewhere so we can later check whether there are no conflicts.
+                       //
+                       if (constraints_list == null)
+                               return;
+
+                       if (constraints_lists != null) {
+                               constraints_lists.Add (constraints_list);
+                               return;
+                       }
+
+                       DoUpdateConstraints (null, constraints_list, false);
+
+                       constraints_lists = new ArrayList ();
+               }
+
+               protected bool DoUpdateConstraints (EmitContext ec, ArrayList constraints_list, bool check)
+               {
+                       for (int i = 0; i < TypeParameters.Length; i++) {
+                               string name = TypeParameters [i].Name;
+
+                               Constraints constraints = null;
+                               if (constraints_list != null) {
+                                       foreach (Constraints constraint in constraints_list) {
+                                               if (constraint.TypeParameter == name) {
+                                                       constraints = constraint;
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               if (!TypeParameters [i].UpdateConstraints (ec, constraints, check)) {
+                                       Report.Error (265, Location, "Partial declarations of `{0}' have " +
+                                                     "inconsistent constraints for type parameter `{1}'.",
+                                                     MemberName.GetTypeName (), name);
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               protected override bool CheckConstraints (EmitContext ec)
+               {
+                       if (constraints_lists == null)
+                               return true;
+
+                       //
+                       // If constraints were specified in more than one part of a
+                       // partial generic type definition, they must be identical.
+                       //
+                       // Note that we must resolve them and then compute the fully
+                       // resolved types since different parts may have different
+                       // `using' aliases.  See gen-129.cs for an example.
+
+                       foreach (ArrayList constraints_list in constraints_lists) {
+                               if (!DoUpdateConstraints (ec, constraints_list, true))
+                                       return false;
+                       }
+
+                       return true;
+               }
+
                public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
                                          Location l)
                {
@@ -2758,6 +2877,11 @@ namespace Mono.CSharp {
                                interface_type, full, name, loc);
                }
 
+               public override void SetParameterInfo (ArrayList constraints_list)
+               {
+                       PartialContainer.UpdateConstraints (constraints_list);
+               }
+
                public override MemberCache BaseCache {
                        get {
                                return PartialContainer.BaseCache;
@@ -3442,7 +3566,7 @@ namespace Mono.CSharp {
 
                protected override bool CheckGenericOverride (MethodInfo method, string name)
                {
-                       ParameterData pd = Invocation.GetParameterData (method);
+                       ParameterData pd = TypeManager.GetParameterData (method);
 
                        for (int i = 0; i < ParameterTypes.Length; i++) {
                                GenericConstraints ogc = pd.GenericConstraints (i);
@@ -5549,9 +5673,9 @@ namespace Mono.CSharp {
                        }
 
                        if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
-                               Report.SymbolRelatedToPreviousError (conflict_symbol);
-                               Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
-                       }
+                               Report.SymbolRelatedToPreviousError (conflict_symbol);
+                               Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+                       }
 
                        return true;
                }
@@ -5577,6 +5701,15 @@ namespace Mono.CSharp {
                        return TypeManager.GetFullNameSignature (FieldBuilder);
                }
 
+               protected virtual bool IsFieldClsCompliant {
+                       get {
+                               if (FieldBuilder == null)
+                                       return true;
+
+                               return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
+                       }
+               }
+
                public override string[] ValidAttributeTargets {
                        get {
                                return attribute_targets;
@@ -5588,11 +5721,7 @@ namespace Mono.CSharp {
                        if (!base.VerifyClsCompliance (ds))
                                return false;
 
-                       if (FieldBuilder == null) {
-                               return true;
-                       }
-
-                       if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
+                       if (!IsFieldClsCompliant) {
                                Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
                        }
                        return true;
@@ -5650,13 +5779,13 @@ namespace Mono.CSharp {
                        
                        MemberType = texpr.Type;
 
+                       ec.InUnsafe = old_unsafe;
+
                        if (MemberType == TypeManager.void_type) {
                                Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
                                return false;
                        }
 
-                       ec.InUnsafe = old_unsafe;
-
                        if (!CheckBase ())
                                return false;
                        
@@ -5679,6 +5808,11 @@ namespace Mono.CSharp {
 
                public override void Emit ()
                {
+                       if (OptAttributes != null) {
+                               EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
+                               OptAttributes.Emit (ec, this);
+                       }
+
                        if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
                                Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
                        }
@@ -5694,6 +5828,163 @@ namespace Mono.CSharp {
                }
        }
 
+       interface IFixedBuffer
+       {
+               FieldInfo Element { get; }
+               Type ElementType { get; }
+       }
+
+       public class FixedFieldExternal: IFixedBuffer
+       {
+               FieldInfo element_field;
+
+               public FixedFieldExternal (FieldInfo fi)
+               {
+                       element_field = fi.FieldType.GetField (FixedField.FixedElementName);
+               }
+
+               #region IFixedField Members
+
+               public FieldInfo Element {
+                       get {
+                               return element_field;
+                       }
+               }
+
+               public Type ElementType {
+                       get {
+                               return element_field.FieldType;
+                       }
+               }
+
+               #endregion
+       }
+
+       /// <summary>
+       /// Fixed buffer implementation
+       /// </summary>
+       public class FixedField: FieldMember, IFixedBuffer
+       {
+               public const string FixedElementName = "FixedElementField";
+               static int GlobalCounter = 0;
+               static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
+               static FieldInfo[] fi;
+
+               TypeBuilder fixed_buffer_type;
+               FieldBuilder element;
+               Expression size_expr;
+               int buffer_size;
+
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE;
+
+               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), null, attrs, loc)
+               {
+                       if (RootContext.Version == LanguageVersion.ISO_1)
+                               Report.FeatureIsNotStandardized (loc, "fixed sized buffers");
+
+                       this.size_expr = size_expr;
+               }
+
+               public override bool Define()
+               {
+#if !NET_2_0
+                       if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
+                               Report.Warning (-23, Location, "Only not private or internal fixed sized buffers are supported by .NET 1.x");
+#endif
+
+                       if (Parent.Kind != Kind.Struct) {
+                               Report.Error (1642, Location, "Fixed buffer fields may only be members of structs");
+                               return false;
+                       }
+
+                       if (!base.Define ())
+                               return false;
+
+                       if (!MemberType.IsPrimitive) {
+                               Report.Error (1663, Location, "Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double");
+                               return false;
+                       }
+
+                       Expression e = size_expr.Resolve (Parent.EmitContext);
+                       if (e == null)
+                               return false;
+
+                       Constant c = e as Constant;
+                       if (c == null) {
+                               Report.Error (133, Location, "The expression being assigned to '{0}' must be constant", GetSignatureForError ());
+                               return false;
+                       }
+
+                       buffer_size = (int)c.GetValue ();
+                       if (buffer_size <= 0) {
+                               Report.Error (1665, Location, "Fixed sized buffer '{0}' must have a length greater than zero", GetSignatureForError ());
+                               return false;
+                       }
+                       buffer_size *= Expression.GetTypeSize (MemberType);
+
+                       // Define nested
+                       string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
+
+                       fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
+                               TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
+                       element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
+                       RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
+
+                       FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
+                       TypeManager.RegisterFieldBase (FieldBuilder, this);
+
+                       return true;
+               }
+
+               public override void Emit()
+               {
+                       if (fi == null)
+                               fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
+
+                       object[] fi_val = new object[1];
+                       fi_val [0] = buffer_size;
+
+                       CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor, 
+                               ctor_args, fi, fi_val);
+                       fixed_buffer_type.SetCustomAttribute (cab);
+
+#if NET_2_0
+                       cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
+                       FieldBuilder.SetCustomAttribute (cab);
+#endif
+                       base.Emit ();
+               }
+
+               protected override bool IsFieldClsCompliant {
+                       get {
+                               return false;
+                       }
+               }
+
+               #region IFixedField Members
+
+               public FieldInfo Element {
+                       get {
+                               return element;
+                       }
+               }
+
+               public Type ElementType {
+                       get {
+                               return MemberType;
+                       }
+               }
+
+               #endregion
+       }
+
        //
        // The Field class is used to represents class/struct fields during parsing.
        //
@@ -5794,18 +6085,6 @@ namespace Mono.CSharp {
 
                        return true;
                }
-
-               public override void Emit ()
-               {
-                       if (OptAttributes != null) {
-                               EmitContext ec = new EmitContext (
-                                       Parent, Location, null, FieldBuilder.FieldType,
-                                       ModFlags);
-                               OptAttributes.Emit (ec, this);
-               }
-
-                       base.Emit ();
-               }
        }
 
        //