[mcs] Implements C# 7.2 readonly structs
[mono.git] / mcs / mcs / attribute.cs
index 7318f2605931c273b9f8f094e0a7dcaed9ab672c..3ff2d68ccb5ad38964c23c0890f4372c9a4406ef 100644 (file)
@@ -258,6 +258,11 @@ namespace Mono.CSharp {
                        Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
                }
 
+               public void Error_MisusedTupleAttribute ()
+               {
+                       Report.Error (8138, loc, "Do not use `{0}' directly. Use the tuple syntax instead", GetSignatureForError ());
+               }
+
                void Error_AttributeEmitError (string inner)
                {
                        Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
@@ -282,6 +287,11 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void SetOwner (Attributable owner)
+               {
+                       targets [0] = owner;
+               }
+
                /// <summary>
                ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
                /// </summary>
@@ -477,10 +487,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
-                       if (obsolete_attr != null) {
-                               AttributeTester.Report_ObsoleteMessage (obsolete_attr, Type.GetSignatureForError (), Location, Report);
-                       }
+                       Type.CheckObsoleteness (context, expression.StartLocation);
 
                        ResolveContext rc = null;
 
@@ -574,8 +581,6 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               ObsoleteAttribute obsolete_attr;
-
                                if (member is PropertyExpr) {
                                        var pi = ((PropertyExpr) member).PropertyInfo;
 
@@ -591,7 +596,9 @@ namespace Mono.CSharp {
                                                return false;
                                        }
 
-                                       obsolete_attr = pi.GetAttributeObsolete ();
+//                                     if (!context.IsObsolete)
+                                               pi.CheckObsoleteness (ec, member.StartLocation);
+                                       
                                        pi.MemberDefinition.SetIsAssigned ();
                                } else {
                                        var fi = ((FieldExpr) member).Spec;
@@ -607,13 +614,12 @@ namespace Mono.CSharp {
                                                return false;
                                        }
 
-                                       obsolete_attr = fi.GetAttributeObsolete ();
+//                                     if (!context.IsObsolete)
+                                               fi.CheckObsoleteness (ec, member.StartLocation);
+
                                        fi.MemberDefinition.SetIsAssigned ();
                                }
 
-                               if (obsolete_attr != null && !context.IsObsolete)
-                                       AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
-
                                if (a.Type != member.Type) {
                                        a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
                                }
@@ -832,9 +838,9 @@ namespace Mono.CSharp {
                /// </summary>
                bool IsSecurityActionValid ()
                {
-                       SecurityAction action = GetSecurityActionValue ();
+                       Constant c = null;
+                       var action = GetSecurityActionValue (ref c);
                        bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
-                       var c = (Constant)pos_args [0].Expr;
 
                        switch (action) {
 #pragma warning disable 618
@@ -855,6 +861,10 @@ namespace Mono.CSharp {
                                        return true;
                                break;
 #pragma warning restore 618
+                       case null:
+                               Report.Error (7048, loc, "First argument of a security attribute `{0}' must be a valid SecurityAction",
+                                       Type.GetSignatureForError ());
+                               return false;
 
                        default:
                                Report.Error (7049, c.Location, "Security attribute `{0}' has an invalid SecurityAction value `{1}'",
@@ -876,9 +886,25 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               System.Security.Permissions.SecurityAction GetSecurityActionValue ()
+               SecurityAction? GetSecurityActionValue (ref Constant value)
                {
-                       return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
+                       if (pos_args == null) {
+                               var predefined = context.Module.PredefinedAttributes;
+
+                               //
+                               // BCL defines System.Security.Permissions.HostProtectionAttribute with parameterless
+                               // contructor which should not be valid but it's already part of the framework
+                               //
+                               if (Type == predefined.HostProtection.TypeSpec) {
+                                       value = new IntConstant (context.Module.Compiler.BuiltinTypes, (int)SecurityAction.LinkDemand, loc);
+                                       return SecurityAction.LinkDemand;
+                               }
+
+                               return null;
+                       }
+
+                       value = (Constant) pos_args [0].Expr;
+                       return (SecurityAction) value.GetValue ();
                }
 
                /// <summary>
@@ -888,9 +914,14 @@ namespace Mono.CSharp {
                public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
                {
 #if STATIC
-                       object[] values = new object[pos_args.Count];
-                       for (int i = 0; i < values.Length; ++i)
-                               values[i] = ((Constant) pos_args[i].Expr).GetValue ();
+                       object[] values;
+                       if (pos_args != null) {
+                               values = new object[pos_args.Count];
+                               for (int i = 0; i < values.Length; ++i)
+                                       values[i] = ((Constant) pos_args[i].Expr).GetValue ();
+                       } else {
+                               values = null;
+                       }
 
                        PropertyInfo[] prop;
                        object[] prop_values;
@@ -1099,7 +1130,12 @@ namespace Mono.CSharp {
                                cdata = encoder.ToArray ();
                        }
 
-                       if (!ctor.DeclaringType.IsConditionallyExcluded (context)) {
+                       if (!IsConditionallyExcluded (ctor.DeclaringType)) {
+                               if (Type == predefined.TupleElementNames) {
+                                       Error_MisusedTupleAttribute ();
+                                       return;
+                               }
+
                                try {
                                        foreach (Attributable target in targets)
                                                target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
@@ -1140,6 +1176,18 @@ namespace Mono.CSharp {
                        }
                }
 
+               bool IsConditionallyExcluded (TypeSpec type)
+               {
+                       do {
+                               if (type.IsConditionallyExcluded (context))
+                                       return true;
+
+                               type = type.BaseType;
+                       } while (type != null);
+
+                       return false;
+               }
+
                private Expression GetValue () 
                {
                        if (pos_args == null || pos_args.Count < 1)
@@ -1198,6 +1246,19 @@ namespace Mono.CSharp {
                        Attrs.AddRange (attrs);
                }
 
+               public static void AttachFromPartial (Attributable target, Attributable partialSrc)
+               {
+                       if (target.OptAttributes == null) {
+                               target.OptAttributes = partialSrc.OptAttributes;
+                       } else {
+                               target.OptAttributes.Attrs.AddRange (partialSrc.OptAttributes.Attrs);
+                       }
+
+                       foreach (var attr in partialSrc.OptAttributes.Attrs) {
+                               attr.SetOwner (target);
+                       }
+               }
+
                public void AttachTo (Attributable attributable, IMemberContext context)
                {
                        foreach (Attribute a in Attrs)
@@ -1661,6 +1722,7 @@ namespace Mono.CSharp {
                public readonly PredefinedAttribute AssemblyAlgorithmId;
                public readonly PredefinedAttribute AssemblyFlags;
                public readonly PredefinedAttribute AssemblyFileVersion;
+               public readonly PredefinedAttribute AssemblyInformationalVersion;
                public readonly PredefinedAttribute ComImport;
                public readonly PredefinedAttribute CoClass;
                public readonly PredefinedAttribute AttributeUsage;
@@ -1679,6 +1741,7 @@ namespace Mono.CSharp {
                public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
                public readonly PredefinedAttribute DebuggerStepThrough;
                public readonly PredefinedDebuggableAttribute Debuggable;
+               public readonly PredefinedAttribute HostProtection;
 
                // New in .NET 3.5
                public readonly PredefinedAttribute Extension;
@@ -1689,6 +1752,12 @@ namespace Mono.CSharp {
                // New in .NET 4.5
                public readonly PredefinedStateMachineAttribute AsyncStateMachine;
 
+               // New in .NET 4.7
+               public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
+
+               // New in .NET 4.7.1
+               public readonly PredefinedAttribute IsReadOnly;
+
                //
                // Optional types which are used as types and for member lookup
                //
@@ -1698,7 +1767,6 @@ namespace Mono.CSharp {
                public readonly PredefinedAttribute FieldOffset;
                public readonly PredefinedAttribute AssemblyProduct;
                public readonly PredefinedAttribute AssemblyCompany;
-               public readonly PredefinedAttribute AssemblyDescription;
                public readonly PredefinedAttribute AssemblyCopyright;
                public readonly PredefinedAttribute AssemblyTrademark;
                public readonly PredefinedAttribute CallerMemberNameAttribute;
@@ -1734,6 +1802,7 @@ namespace Mono.CSharp {
                        DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
                        OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
                        UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
+                       HostProtection = new PredefinedAttribute (module, "System.Security.Permissions", "HostProtectionAttribute");
 
                        DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
                        TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
@@ -1758,9 +1827,9 @@ namespace Mono.CSharp {
                        FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
                        AssemblyProduct = new PredefinedAttribute (module, "System.Reflection", "AssemblyProductAttribute");
                        AssemblyCompany = new PredefinedAttribute (module, "System.Reflection", "AssemblyCompanyAttribute");
-                       AssemblyDescription = new PredefinedAttribute (module, "System.Reflection", "AssemblyDescriptionAttribute");
                        AssemblyCopyright = new PredefinedAttribute (module, "System.Reflection", "AssemblyCopyrightAttribute");
                        AssemblyTrademark = new PredefinedAttribute (module, "System.Reflection", "AssemblyTrademarkAttribute");
+                       AssemblyInformationalVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyInformationalVersionAttribute");
 
                        AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
 
@@ -1768,6 +1837,9 @@ namespace Mono.CSharp {
                        CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
                        CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
 
+                       TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
+                       IsReadOnly = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IsReadOnlyAttribute");
+
                        // TODO: Should define only attributes which are used for comparison
                        const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
                                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
@@ -1974,8 +2046,8 @@ namespace Mono.CSharp {
 
                        int[] bits = decimal.GetBits (value);
                        AttributeEncoder encoder = new AttributeEncoder ();
-                       encoder.Encode ((byte) (bits[3] >> 16));
-                       encoder.Encode ((byte) (bits[3] >> 31));
+                       encoder.Encode ((byte) ((bits[3] & 0xFF0000) >> 16)); // Scale
+                       encoder.Encode ((byte) ((bits[3] >> 31) << 7)); // Sign encoded as 0x80 for negative, 0x0 for possitive
                        encoder.Encode ((uint) bits[2]);
                        encoder.Encode ((uint) bits[1]);
                        encoder.Encode ((uint) bits[0]);
@@ -2118,4 +2190,83 @@ namespace Mono.CSharp {
                        return tctor != null;
                }
        }
+
+       public class PredefinedTupleElementNamesAttribute : PredefinedAttribute
+       {
+               MethodSpec tctor;
+
+               public PredefinedTupleElementNamesAttribute (ModuleContainer module, string ns, string name)
+                       : base (module, ns, name)
+               {
+               }
+
+               public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
+               {
+                       var cab = CreateCustomAttributeBuilder (type, loc);
+                       if (cab != null)
+                               builder.SetCustomAttribute (cab);
+               }
+
+               CustomAttributeBuilder CreateCustomAttributeBuilder (TypeSpec type, Location loc)
+               {
+                       if (tctor == null) {
+                               tctor = module.PredefinedMembers.TupleElementNamesAttributeCtor.Resolve (loc);
+                               if (tctor == null)
+                                       return null;
+                       }
+
+                       var names = new List<string> (type.TypeArguments.Length);
+                       BuildStringElements (type, names);
+                       return new CustomAttributeBuilder ((ConstructorInfo)tctor.GetMetaInfo (), new object [] { names.ToArray () });
+               }
+
+               //
+               // Returns an array of names when any element of the type is
+               // tuple with named element. The array is built for top level
+               // type therefore it can contain multiple tuple types
+               //
+               // Example: Func<(int, int), int, (int a, int b)[]>
+               // Output: { null, null, "a", "b" }
+               //
+               static void BuildStringElements (TypeSpec type, List<string> names)
+               {
+                       while (type is ArrayContainer) {
+                               type = ((ArrayContainer)type).Element;
+                       }
+
+                       var nts = type as NamedTupleSpec;
+                       if (nts != null) {
+                               names.AddRange (nts.Elements);
+                       } else {
+                               for (int i = 0; i < type.Arity; ++i) {
+                                       names.Add (null);
+                               }
+                       }
+
+                       foreach (var ta in type.TypeArguments) {
+                               BuildStringElements (ta, names);
+                       }
+               }
+       }
 }