Optimized constructor readonly access has to be inside same declarting type
[mono.git] / mcs / mcs / field.cs
index ac051a01691adfb6985a2ddc90a1d80964b20a1c..913f620db21fa8cb9d04b49b9112ed79289e633d 100644 (file)
 
 using System;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+#if STATIC
+using MetaType = IKVM.Reflection.Type;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using MetaType = System.Type;
 using System.Reflection;
 using System.Reflection.Emit;
-using System.Runtime.InteropServices;
+#endif
 
 namespace Mono.CSharp
 {
@@ -147,6 +155,11 @@ namespace Mono.CSharp
                        FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
                }
 
+               public void SetCustomAttribute (MethodSpec ctor, byte[] data)
+               {
+                       FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data);
+               }
+
                protected override bool CheckBase ()
                {
                        if (!base.CheckBase ())
@@ -208,19 +221,13 @@ namespace Mono.CSharp
                public override void Emit ()
                {
                        if (member_type == InternalType.Dynamic) {
-                               PredefinedAttributes.Get.Dynamic.EmitAttribute (FieldBuilder);
-                       } else {
-                               var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
-                               if (trans_flags != null) {
-                                       var pa = PredefinedAttributes.Get.DynamicTransform;
-                                       if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type, 1))) {
-                                               FieldBuilder.SetCustomAttribute (new CustomAttributeBuilder (pa.Constructor, new object[] { trans_flags }));
-                                       }
-                               }
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder);
+                       } else if (!(Parent is CompilerGeneratedClass) && member_type.HasDynamicElement) {
+                               Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
                        }
 
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
-                               PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (FieldBuilder);
+                               Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
 
                        if (OptAttributes != null) {
                                OptAttributes.Emit ();
@@ -268,7 +275,7 @@ namespace Mono.CSharp
                        this.memberType = memberType;
                }
 
-#region Properties
+               #region Properties
 
                public bool IsReadOnly {
                        get {
@@ -330,6 +337,11 @@ namespace Mono.CSharp
                        fs.metaInfo = MemberCache.GetMember (TypeParameterMutator.GetMemberDeclaringType (DeclaringType), this).metaInfo;
                        return fs;
                }
+
+               public override List<TypeSpec> ResolveMissingDependencies ()
+               {
+                       return memberType.ResolveMissingDependencies ();
+               }
        }
 
        /// <summary>
@@ -339,8 +351,6 @@ namespace Mono.CSharp
        {
                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;
 
@@ -357,6 +367,17 @@ namespace Mono.CSharp
                {
                }
 
+               #region Properties
+
+               //
+               // Explicit struct layout set by parent
+               //
+               public CharSet? CharSet {
+                       get; set;
+               }               
+
+               #endregion
+
                public override Constant ConvertInitializer (ResolveContext rc, Constant expr)
                {
                        return expr.ImplicitConversionRequired (rc, TypeManager.int32_type, Location);
@@ -384,11 +405,10 @@ namespace Mono.CSharp
                        
                        // Create nested fixed buffer container
                        string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
-                       fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, Parent.Module.DefaultCharSetType |
+                       fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
                                TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type.GetMetaInfo ());
 
                        fixed_buffer_type.DefineField (FixedElementName, MemberType.GetMetaInfo (), FieldAttributes.Public);
-                       RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
                        
                        FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, ModifiersExtensions.FieldAttr (ModFlags));
                        var element_spec = new FieldSpec (null, this, MemberType, FieldBuilder, ModFlags);
@@ -433,69 +453,65 @@ namespace Mono.CSharp
                                return;
                        }
 
-                       buffer_size *= type_size;
                        EmitFieldSize (buffer_size);
 
-                       PredefinedAttributes.Get.UnsafeValueType.EmitAttribute (fixed_buffer_type);
+#if STATIC
+                       if (Module.HasDefaultCharSet)
+                               fixed_buffer_type.__SetAttributes (fixed_buffer_type.Attributes | Module.DefaultCharSetType);
+#endif
+
+                       Module.PredefinedAttributes.UnsafeValueType.EmitAttribute (fixed_buffer_type);
+                       Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (fixed_buffer_type);
+                       fixed_buffer_type.CreateType ();
 
                        base.Emit ();
                }
 
                void EmitFieldSize (int buffer_size)
                {
-                       CustomAttributeBuilder cab;
                        PredefinedAttribute pa;
+                       AttributeEncoder encoder;
 
-                       pa = PredefinedAttributes.Get.StructLayout;
-                       if (pa.Constructor == null &&
-                               !pa.ResolveConstructor (Location, TypeManager.short_type))
-                                       return;
+                       pa = Module.PredefinedAttributes.StructLayout;
+                       if (pa.Constructor == null && !pa.ResolveConstructor (Location, TypeManager.short_type))
+                               return;
 
-                       // TODO: It's not cleared
-                       if (fi == null) {
-                               var field = (FieldSpec) MemberCache.FindMember (pa.Type, MemberFilter.Field ("Size", null), BindingRestriction.DeclaredOnly);
-                               fi = new FieldInfo[] { field.GetMetaInfo () };
-                       }
+                       var char_set_type = Module.PredefinedTypes.CharSet.Resolve (Location);
+                       if (char_set_type == null)
+                               return;
+
+                       var field_size = pa.GetField ("Size", TypeManager.int32_type, Location);
+                       var field_charset = pa.GetField ("CharSet", char_set_type, Location);
+                       if (field_size == null || field_charset == null)
+                               return;
+
+                       var char_set = CharSet ?? Module.DefaultCharSet ?? 0;
+
+                       encoder = new AttributeEncoder ();
+                       encoder.Encode ((short)LayoutKind.Sequential);
+                       encoder.EncodeNamedArguments (
+                               new [] { field_size, field_charset },
+                               new Constant [] { new IntConstant (buffer_size, Location), new IntConstant ((int) char_set, Location) }
+                       );
+
+                       pa.EmitAttribute (fixed_buffer_type, encoder);
 
-                       object[] fi_val = new object[] { buffer_size };
-                       cab = new CustomAttributeBuilder (pa.Constructor,
-                               ctor_args, fi, fi_val);
-                       fixed_buffer_type.SetCustomAttribute (cab);
-                       
                        //
                        // Don't emit FixedBufferAttribute attribute for private types
                        //
                        if ((ModFlags & Modifiers.PRIVATE) != 0)
                                return;
 
-                       pa = PredefinedAttributes.Get.FixedBuffer;
-                       if (pa.Constructor == null &&
-                               !pa.ResolveConstructor (Location, TypeManager.type_type, TypeManager.int32_type))
+                       pa = Module.PredefinedAttributes.FixedBuffer;
+                       if (pa.Constructor == null && !pa.ResolveConstructor (Location, TypeManager.type_type, TypeManager.int32_type))
                                return;
 
-                       cab = new CustomAttributeBuilder (pa.Constructor, new object[] { MemberType.GetMetaInfo (), buffer_size });
-                       FieldBuilder.SetCustomAttribute (cab);
-               }
+                       encoder = new AttributeEncoder ();
+                       encoder.EncodeTypeName (MemberType);
+                       encoder.Encode (buffer_size);
+                       encoder.EncodeEmptyNamedArguments ();
 
-               public void SetCharSet (TypeAttributes ta)
-               {
-                       TypeAttributes cta = fixed_buffer_type.Attributes;
-                       if ((cta & TypeAttributes.UnicodeClass) != (ta & TypeAttributes.UnicodeClass))
-                               SetTypeBuilderCharSet ((cta & ~TypeAttributes.AutoClass) | TypeAttributes.UnicodeClass);
-                       else if ((cta & TypeAttributes.AutoClass) != (ta & TypeAttributes.AutoClass))
-                               SetTypeBuilderCharSet ((cta & ~TypeAttributes.UnicodeClass) | TypeAttributes.AutoClass);
-                       else if (cta == 0 && ta != 0)
-                               SetTypeBuilderCharSet (cta & ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass));
-               }
-
-               void SetTypeBuilderCharSet (TypeAttributes ta)
-               {
-                       MethodInfo mi = typeof (TypeBuilder).GetMethod ("SetCharSet", BindingFlags.Instance | BindingFlags.NonPublic);
-                       if (mi == null) {
-                               Report.RuntimeMissingSupport (Location, "TypeBuilder::SetCharSet");
-                       } else {
-                               mi.Invoke (fixed_buffer_type, new object [] { ta });
-                       }
+                       pa.EmitAttribute (FieldBuilder, encoder);
                }
        }
 
@@ -573,14 +589,11 @@ namespace Mono.CSharp
                        if (!base.Define ())
                                return false;
 
-                       Type[] required_modifier = null;
+                       MetaType[] required_modifier = null;
                        if ((ModFlags & Modifiers.VOLATILE) != 0) {
-                               if (TypeManager.isvolatile_type == null)
-                                       TypeManager.isvolatile_type = TypeManager.CoreLookupType (Compiler,
-                                               "System.Runtime.CompilerServices", "IsVolatile", MemberKind.Class, true);
-
-                               if (TypeManager.isvolatile_type != null)
-                                       required_modifier = new Type[] { TypeManager.isvolatile_type.GetMetaInfo () };
+                               var mod = Module.PredefinedTypes.IsVolatile.Resolve (Location);
+                               if (mod != null)
+                                       required_modifier = new MetaType[] { mod.GetMetaInfo () };
                        }
 
                        FieldBuilder = Parent.TypeBuilder.DefineField (