[mcs] Implements C# 7.2 readonly structs
[mono.git] / mcs / mcs / field.cs
index e3555b9383e387f42964b063ba1e7ab232b862ee..86bb028defcb766e3d46d3ff6bed497962cb470b 100644 (file)
@@ -244,6 +244,10 @@ namespace Mono.CSharp
                                Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location);
                        }
 
+                       if (member_type.HasNamedTupleElement) {
+                               Module.PredefinedAttributes.TupleElementNames.EmitAttribute (FieldBuilder, member_type, Location);
+                       }
+
                        if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
                                Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder);
                        if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
@@ -257,7 +261,8 @@ namespace Mono.CSharp
                                Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ());
                        }
 
-                       ConstraintChecker.Check (this, member_type, type_expr.Location);
+                       if (!IsCompilerGenerated)
+                               ConstraintChecker.Check (this, member_type, type_expr.Location);
 
                        base.Emit ();
                }
@@ -311,7 +316,7 @@ namespace Mono.CSharp
                        }
                }
 
-#endregion
+               #endregion
 
                public FieldInfo GetMetaInfo ()
                {
@@ -394,7 +399,7 @@ namespace Mono.CSharp
                //
                // Explicit struct layout set by parent
                //
-               public CharSet? CharSet {
+               public CharSet? CharSetValue {
                        get; set;
                }               
 
@@ -425,7 +430,7 @@ namespace Mono.CSharp
                        }
                        
                        // Create nested fixed buffer container
-                       string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
+                       string name = String.Format ("<{0}>__FixedBuffer{1}", TypeDefinition.FilterNestedName (Name), GlobalCounter++);
                        fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
                                TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit,
                                Compiler.BuiltinTypes.ValueType.GetMetaInfo ());
@@ -493,8 +498,32 @@ namespace Mono.CSharp
                        }
 
                        AttributeEncoder encoder;
+                       MethodSpec ctor;
+
+                       var char_set = CharSetValue ?? Module.DefaultCharSet ?? 0;
+#if STATIC
+                       //
+                       // Set struct layout without resolving StructLayoutAttribute which is not always available
+                       //
 
-                       var ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location);
+                       TypeAttributes attribs = TypeAttributes.SequentialLayout;
+                       switch (char_set) {
+                       case CharSet.None:
+                       case CharSet.Ansi:
+                               attribs |= TypeAttributes.AnsiClass;
+                               break;
+                       case CharSet.Auto:
+                               attribs |= TypeAttributes.AutoClass;
+                               break;
+                       case CharSet.Unicode:
+                               attribs |= TypeAttributes.UnicodeClass;
+                               break;
+                       }
+
+                       fixed_buffer_type.__SetAttributes (fixed_buffer_type.Attributes | attribs);
+                       fixed_buffer_type.__SetLayout (0, buffer_size * type_size);
+#else
+                       ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location);
                        if (ctor == null)
                                return;
 
@@ -503,8 +532,6 @@ namespace Mono.CSharp
                        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 (
@@ -516,7 +543,7 @@ namespace Mono.CSharp
                        );
 
                        fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
-
+#endif
                        //
                        // Don't emit FixedBufferAttribute attribute for private types
                        //
@@ -605,9 +632,23 @@ namespace Mono.CSharp
                        if (TypeSpec.IsReferenceType (MemberType))
                                return true;
 
-                       if (MemberType.IsEnum)
+                       if (MemberType.IsPointer)
                                return true;
 
+                       if (MemberType.IsEnum) {
+                               switch (EnumSpec.GetUnderlyingType (MemberType).BuiltinType) {
+                               case BuiltinTypeSpec.Type.SByte:
+                               case BuiltinTypeSpec.Type.Byte:
+                               case BuiltinTypeSpec.Type.Short:
+                               case BuiltinTypeSpec.Type.UShort:
+                               case BuiltinTypeSpec.Type.Int:
+                               case BuiltinTypeSpec.Type.UInt:
+                                       return true;
+                               default:
+                                       return false;
+                               }
+                       }
+
                        return false;
                }
 
@@ -659,6 +700,16 @@ namespace Mono.CSharp
                        return true;
                }
 
+               protected override void DoMemberTypeIndependentChecks ()
+               {
+                       if ((Parent.PartialContainer.ModFlags & Modifiers.READONLY) != 0 && (ModFlags & (Modifiers.READONLY | Modifiers.STATIC)) == 0) {
+                               Report.Error (8340, Location, "`{0}': Instance fields in readonly structs must be readonly",
+                                       GetSignatureForError ());
+                       }
+
+                       base.DoMemberTypeIndependentChecks ();
+               }
+
                protected override void DoMemberTypeDependentChecks ()
                {
                        if ((ModFlags & Modifiers.BACKING_FIELD) != 0)