[System.ServiceModel] Changed test port from 8080 to 30158
[mono.git] / mcs / mcs / attribute.cs
index 4fbc993a55a882591eb2192cfbe79fa163027afe..7318f2605931c273b9f8f094e0a7dcaed9ab672c 100644 (file)
@@ -1,14 +1,14 @@
 //
-// attribute.cs: Attribute Handler
+// attribute.cs: Attributes handling
 //
 // Author: Ravi Pratap (ravi@ximian.com)
-//         Marek Safar (marek.safar@seznam.cz)
+//         Marek Safar (marek.safar@gmail.com)
 //
 // Dual licensed under the terms of the MIT X11 or GNU GPL
 //
 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
 // Copyright 2003-2008 Novell, Inc.
-// Copyright 2011 Xamarin Inc
+// Copyright 2011-2013 Xamarin Inc
 //
 
 using System;
@@ -173,7 +173,7 @@ namespace Mono.CSharp {
                        if (NamedArguments == null)
                                named_args = new Arguments (1);
 
-                       var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
+                       var value = Constant.CreateConstantFromValue (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
                        NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
                }
 
@@ -258,19 +258,22 @@ namespace Mono.CSharp {
                        Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
                }
 
-               /// <summary>
-               /// This is rather hack. We report many emit attribute error with same error to be compatible with
-               /// csc. But because csc has to report them this way because error came from ilasm we needn't.
-               /// </summary>
-               public void Error_AttributeEmitError (string inner)
+               void Error_AttributeEmitError (string inner)
                {
                        Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
-                                     TypeManager.CSharpName (Type), inner);
+                                     Type.GetSignatureForError (), inner);
+               }
+
+               public void Error_InvalidArgumentValue (TypeSpec attributeType)
+               {
+                       Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", attributeType.GetSignatureForError ());
                }
 
                public void Error_InvalidSecurityParent ()
                {
-                       Error_AttributeEmitError ("it is attached to invalid parent");
+                       Report.Error (7070, Location,
+                               "Security attribute `{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations",
+                               Type.GetSignatureForError ());
                }
 
                Attributable Owner {
@@ -284,7 +287,8 @@ namespace Mono.CSharp {
                /// </summary>
                void ResolveAttributeType (bool comparisonOnly)
                {
-                       SessionReportPrinter resolve_printer = new SessionReportPrinter ();
+                       var resolve_printer = new SessionReportPrinter ();
+                       SessionReportPrinter secondary_printer = null;
                        ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
 
                        bool t1_is_attr = false;
@@ -297,20 +301,25 @@ namespace Mono.CSharp {
 
                        try {
                                t1 = expression.ResolveAsType (context);
-                               if (t1 != null)
-                                       t1_is_attr = t1.IsAttribute;
-
                                resolve_printer.EndSession ();
 
+                               if (t1 != null && resolve_printer.ErrorsCount == 0)
+                                       t1_is_attr = t1.IsAttribute;
+
                                if (nameEscaped) {
                                        t2 = null;
                                } else {
                                        expanded = (ATypeNameExpression) expression.Clone (null);
                                        expanded.Name += "Attribute";
 
+                                       secondary_printer = new SessionReportPrinter ();
+                                       Report.SetPrinter (secondary_printer);
                                        t2 = expanded.ResolveAsType (context);
-                                       if (t2 != null)
+                                       secondary_printer.EndSession ();
+                                       if (t2 != null && secondary_printer.ErrorsCount == 0)
                                                t2_is_attr = t2.IsAttribute;
+
+                                       secondary_printer.EndSession ();
                                }
                        } finally {
                                context.Module.Compiler.Report.SetPrinter (prev_recorder);
@@ -341,17 +350,25 @@ namespace Mono.CSharp {
 
                        resolve_error = true;
 
-                       if (t1 != null) {
-                               resolve_printer.Merge (prev_recorder);
+                       if (t1 != null) {       
+                               if (resolve_printer.IsEmpty) {
+                                       Report.SymbolRelatedToPreviousError (t1);
+                                       Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
+                               } else {
+                                       resolve_printer.Merge (prev_recorder);
+                               }
 
-                               Report.SymbolRelatedToPreviousError (t1);
-                               Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
                                return;
                        }
 
                        if (t2 != null) {
-                               Report.SymbolRelatedToPreviousError (t2);
-                               Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+                               if (secondary_printer.IsEmpty) {
+                                       Report.SymbolRelatedToPreviousError (t2);
+                                       Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+                               } else {
+                                       secondary_printer.Merge (prev_recorder);
+                               }
+
                                return;
                        }
 
@@ -368,7 +385,7 @@ namespace Mono.CSharp {
                public string GetSignatureForError ()
                {
                        if (Type != null)
-                               return TypeManager.CSharpName (Type);
+                               return Type.GetSignatureForError ();
 
                        return expression.GetSignatureForError ();
                }
@@ -385,7 +402,20 @@ namespace Mono.CSharp {
                        return HasSecurityAttribute && IsSecurityActionValid ();
                }
 
-               static bool IsValidArgumentType (TypeSpec t)
+               static bool IsValidMethodImplOption (int value)
+               {
+                       //
+                       // Allow to use AggressiveInlining on any runtime/corlib
+                       //
+                       MethodImplOptions all = (MethodImplOptions) 256;
+                       foreach (MethodImplOptions v in System.Enum.GetValues (typeof (MethodImplOptions))) {
+                               all |= v;
+                       }
+
+                       return ((MethodImplOptions) value | all) == all;
+               }
+
+               public static bool IsValidArgumentType (TypeSpec t)
                {
                        if (t.IsArray) {
                                var ac = (ArrayContainer) t;
@@ -449,7 +479,7 @@ namespace Mono.CSharp {
 
                        ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
                        if (obsolete_attr != null) {
-                               AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
+                               AttributeTester.Report_ObsoleteMessage (obsolete_attr, Type.GetSignatureForError (), Location, Report);
                        }
 
                        ResolveContext rc = null;
@@ -804,6 +834,7 @@ namespace Mono.CSharp {
                {
                        SecurityAction action = GetSecurityActionValue ();
                        bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
+                       var c = (Constant)pos_args [0].Expr;
 
                        switch (action) {
 #pragma warning disable 618
@@ -826,11 +857,22 @@ namespace Mono.CSharp {
 #pragma warning restore 618
 
                        default:
-                               Error_AttributeEmitError ("SecurityAction is out of range");
+                               Report.Error (7049, c.Location, "Security attribute `{0}' has an invalid SecurityAction value `{1}'",
+                                       Type.GetSignatureForError (), c.GetValueAsLiteral());
                                return false;
                        }
 
-                       Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
+                       switch (Target) {
+                       case AttributeTargets.Assembly:
+                               Report.Error (7050, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to an assembly",
+                                       c.GetSignatureForError ());
+                               break;
+                       default:
+                               Report.Error (7051, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to a type or a method",
+                                       c.GetSignatureForError ());
+                               break;
+                       }
+
                        return false;
                }
 
@@ -999,40 +1041,42 @@ namespace Mono.CSharp {
                                                                        return;
                                                                }
                                                        } else if (Type == predefined.Guid) {
+                                                               string v = ((StringConstant) arg_expr).Value;
                                                                try {
-                                                                       string v = ((StringConstant) arg_expr).Value;
                                                                        new Guid (v);
-                                                               } catch (Exception e) {
-                                                                       Error_AttributeEmitError (e.Message);
+                                                               } catch {
+                                                                       Error_InvalidArgumentValue (Type);
                                                                        return;
                                                                }
                                                        } else if (Type == predefined.AttributeUsage) {
                                                                int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
-                                                               if (v == 0) {
-                                                                       context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
-                                                                               "System.AttributeUsage");
-                                                               }
+                                                               if (v == 0)
+                                                                       Error_InvalidArgumentValue (Type);
                                                        } else if (Type == predefined.MarshalAs) {
                                                                if (pos_args.Count == 1) {
                                                                        var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
                                                                        if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
-                                                                               Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
+                                                                               Report.Error (7055, pos_args [0].Expr.Location, "Unmanaged type `ByValArray' is only valid for fields");
                                                                        }
                                                                }
                                                        } else if (Type == predefined.DllImport) {
                                                                if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
                                                                        var value = ((Constant) pos_args[0].Expr).GetValue () as string;
                                                                        if (string.IsNullOrEmpty (value))
-                                                                               Error_AttributeEmitError ("DllName cannot be empty or null");
+                                                                               Error_InvalidArgumentValue (Type);
+                                                               }
+                                                       } else if (Type == predefined.MethodImpl) {
+                                                               if (pos_args.Count == 1) {
+                                                                       var value = (int) ((Constant) arg_expr).GetValueAsLong ();
+
+                                                                       if (!IsValidMethodImplOption (value)) {
+                                                                               Error_InvalidArgumentValue (Type);
+                                                                       }
                                                                }
-                                                       } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
-                                                               !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
-                                                               Error_AttributeEmitError ("Incorrect argument value.");
-                                                               return;
                                                        }
                                                }
 
-                                               arg_expr.EncodeAttributeValue (context, encoder, pt);
+                                               arg_expr.EncodeAttributeValue (context, encoder, pt, pt);
                                        }
                                }
 
@@ -1046,7 +1090,7 @@ namespace Mono.CSharp {
 
                                                encoder.Encode (na.Key.Type);
                                                encoder.Encode (na.Value.Name);
-                                               na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
+                                               na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type, na.Key.Type);
                                        }
                                } else {
                                        encoder.EncodeEmptyNamedArguments ();
@@ -1055,15 +1099,17 @@ namespace Mono.CSharp {
                                cdata = encoder.ToArray ();
                        }
 
-                       try {
-                               foreach (Attributable target in targets)
-                                       target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
-                       } catch (Exception e) {
-                               if (e is BadImageFormat && Report.Errors > 0)
-                                       return;
+                       if (!ctor.DeclaringType.IsConditionallyExcluded (context)) {
+                               try {
+                                       foreach (Attributable target in targets)
+                                               target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
+                               } catch (Exception e) {
+                                       if (e is BadImageFormat && Report.Errors > 0)
+                                               return;
 
-                               Error_AttributeEmitError (e.Message);
-                               return;
+                                       Error_AttributeEmitError (e.Message);
+                                       return;
+                               }
                        }
 
                        if (!usage_attr.AllowMultiple && allEmitted != null) {
@@ -1139,7 +1185,7 @@ namespace Mono.CSharp {
 
                public Attributes (List<Attribute> attrs)
                {
-                       Attrs = attrs;
+                       Attrs = attrs ?? new List<Attribute> ();
                }
 
                public void AddAttribute (Attribute attr)
@@ -1494,7 +1540,7 @@ namespace Mono.CSharp {
                        Encode ((byte) 0x54); // property
                        Encode (property.MemberType);
                        Encode (property.Name);
-                       value.EncodeAttributeValue (null, this, property.MemberType);
+                       value.EncodeAttributeValue (null, this, property.MemberType, property.MemberType);
                }
 
                //
@@ -1506,7 +1552,7 @@ namespace Mono.CSharp {
                        Encode ((byte) 0x53); // field
                        Encode (field.MemberType);
                        Encode (field.Name);
-                       value.EncodeAttributeValue (null, this, field.MemberType);
+                       value.EncodeAttributeValue (null, this, field.MemberType, field.MemberType);
                }
 
                public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
@@ -1526,7 +1572,7 @@ namespace Mono.CSharp {
 
                                Encode (member.MemberType);
                                Encode (member.Name);
-                               values [i].EncodeAttributeValue (null, this, member.MemberType);
+                               values [i].EncodeAttributeValue (null, this, member.MemberType, member.MemberType);
                        }
                }
 
@@ -1631,6 +1677,8 @@ namespace Mono.CSharp {
                public readonly PredefinedAttribute UnsafeValueType;
                public readonly PredefinedAttribute UnmanagedFunctionPointer;
                public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
+               public readonly PredefinedAttribute DebuggerStepThrough;
+               public readonly PredefinedDebuggableAttribute Debuggable;
 
                // New in .NET 3.5
                public readonly PredefinedAttribute Extension;
@@ -1640,7 +1688,6 @@ namespace Mono.CSharp {
 
                // New in .NET 4.5
                public readonly PredefinedStateMachineAttribute AsyncStateMachine;
-               public readonly PredefinedStateMachineAttribute IteratorStateMachine;
 
                //
                // Optional types which are used as types and for member lookup
@@ -1649,6 +1696,11 @@ namespace Mono.CSharp {
                public readonly PredefinedDecimalAttribute DecimalConstant;
                public readonly PredefinedAttribute StructLayout;
                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;
                public readonly PredefinedAttribute CallerLineNumberAttribute;
                public readonly PredefinedAttribute CallerFilePathAttribute;
@@ -1693,6 +1745,8 @@ namespace Mono.CSharp {
                        UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
                        UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
                        DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
+                       DebuggerStepThrough = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerStepThroughAttribute");
+                       Debuggable = new PredefinedDebuggableAttribute (module, "System.Diagnostics", "DebuggableAttribute");
 
                        Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
 
@@ -1702,11 +1756,13 @@ namespace Mono.CSharp {
                        DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
                        StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
                        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");
 
                        AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
-                       IteratorStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "IteratorStateMachineAttribute") {
-                               IsIterator = true
-                       };
 
                        CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
                        CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
@@ -1822,7 +1878,7 @@ namespace Mono.CSharp {
                        //
                        // Handle all parameter-less attributes as optional
                        //
-                       if (!IsDefined)
+                       if (!Define ())
                                return false;
 
                        ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
@@ -1851,6 +1907,40 @@ namespace Mono.CSharp {
                }
        }
 
+       public class PredefinedDebuggableAttribute : PredefinedAttribute
+       {
+               public PredefinedDebuggableAttribute (ModuleContainer module, string ns, string name)
+                       : base (module, ns, name)
+               {
+               }
+
+               public void EmitAttribute (AssemblyBuilder builder, System.Diagnostics.DebuggableAttribute.DebuggingModes modes)
+               {
+                       var atype = module.PredefinedAttributes.Debuggable;
+                       if (!atype.Define ())
+                               return;
+
+                       MethodSpec ctor = null;
+                       foreach (MethodSpec m in MemberCache.FindMembers (atype.TypeSpec, CSharp.Constructor.ConstructorName, true)) {
+                               if (m.Parameters.Count != 1)
+                                       continue;
+
+                               if (m.Parameters.Types[0].Kind == MemberKind.Enum) {
+                                       ctor = m;
+                               }
+                       }
+
+                       if (ctor == null)
+                               return;
+
+                       AttributeEncoder encoder = new AttributeEncoder ();
+                       encoder.Encode ((int) modes);
+                       encoder.EncodeEmptyNamedArguments ();
+
+                       builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+               }
+       }
+
        public class PredefinedDecimalAttribute : PredefinedAttribute
        {
                public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
@@ -1902,13 +1992,9 @@ namespace Mono.CSharp {
                {
                }
 
-               public bool IsIterator { get; set; }
-
                public void EmitAttribute (MethodBuilder builder, StateMachine type)
                {
-                       var predefined_ctor = IsIterator ?
-                               module.PredefinedMembers.IteratorStateMachineAttributeCtor :
-                               module.PredefinedMembers.AsyncStateMachineAttributeCtor;
+                       var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
 
                        var ctor = predefined_ctor.Get ();
 
@@ -1984,7 +2070,7 @@ namespace Mono.CSharp {
                        if (ac != null) {
                                element = GetTransformationFlags (ac.Element);
                                if (element == null)
-                                       return null;
+                                       return new bool[] { false, false };
 
                                bool[] res = new bool[element.Length + 1];
                                res[0] = false;