Merge branch 'master' into msbuilddll2
[mono.git] / mcs / mcs / attribute.cs
index 4fbc993a55a882591eb2192cfbe79fa163027afe..2152674d2da63e7d766bea3b3f36bde38a0a0b18 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));
                }
 
@@ -265,7 +265,7 @@ namespace Mono.CSharp {
                public 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_InvalidSecurityParent ()
@@ -284,7 +284,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 +298,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 +347,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 +382,7 @@ namespace Mono.CSharp {
                public string GetSignatureForError ()
                {
                        if (Type != null)
-                               return TypeManager.CSharpName (Type);
+                               return Type.GetSignatureForError ();
 
                        return expression.GetSignatureForError ();
                }
@@ -385,6 +399,19 @@ namespace Mono.CSharp {
                        return HasSecurityAttribute && IsSecurityActionValid ();
                }
 
+               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;
+               }
+
                static bool IsValidArgumentType (TypeSpec t)
                {
                        if (t.IsArray) {
@@ -449,7 +476,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;
@@ -1025,10 +1052,14 @@ namespace Mono.CSharp {
                                                                        if (string.IsNullOrEmpty (value))
                                                                                Error_AttributeEmitError ("DllName cannot be empty or null");
                                                                }
-                                                       } 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;
+                                                       } else if (Type == predefined.MethodImpl) {
+                                                               if (pos_args.Count == 1) {
+                                                                       var value = (int) ((Constant) arg_expr).GetValueAsLong ();
+
+                                                                       if (!IsValidMethodImplOption (value)) {
+                                                                               Error_AttributeEmitError ("Incorrect argument value");
+                                                                       }
+                                                               }
                                                        }
                                                }
 
@@ -1055,15 +1086,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 +1172,7 @@ namespace Mono.CSharp {
 
                public Attributes (List<Attribute> attrs)
                {
-                       Attrs = attrs;
+                       Attrs = attrs ?? new List<Attribute> ();
                }
 
                public void AddAttribute (Attribute attr)
@@ -1631,6 +1664,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 +1675,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 +1683,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 +1732,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 +1743,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 +1865,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 +1894,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 +1979,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 +2057,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;