2 // attribute.cs: Attribute Handler
4 // Author: Ravi Pratap (ravi@ximian.com)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 // Copyright 2011 Xamarin Inc
15 using System.Collections.Generic;
16 using System.Runtime.InteropServices;
17 using System.Runtime.CompilerServices;
18 using System.Security;
19 using System.Security.Permissions;
24 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
25 using BadImageFormat = IKVM.Reflection.BadImageFormatException;
26 using IKVM.Reflection;
27 using IKVM.Reflection.Emit;
29 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
30 using BadImageFormat = System.BadImageFormatException;
31 using System.Reflection;
32 using System.Reflection.Emit;
35 namespace Mono.CSharp {
38 /// Base class for objects that can have Attributes applied to them.
40 public abstract class Attributable {
42 // Holds all attributes attached to this element
44 protected Attributes attributes;
46 public void AddAttributes (Attributes attrs, IMemberContext context)
51 if (attributes == null)
54 attributes.AddAttributes (attrs.Attrs);
56 attrs.AttachTo (this, context);
59 public Attributes OptAttributes {
69 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
71 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
74 /// Returns one AttributeTarget for this element.
76 public abstract AttributeTargets AttributeTargets { get; }
78 public abstract bool IsClsComplianceRequired ();
81 /// Gets list of valid attribute targets for explicit target declaration.
82 /// The first array item is default target. Don't break this rule.
84 public abstract string[] ValidAttributeTargets { get; }
87 public class Attribute
89 public readonly string ExplicitTarget;
90 public AttributeTargets Target;
91 readonly ATypeNameExpression expression;
93 Arguments pos_args, named_args;
97 readonly bool nameEscaped;
98 readonly Location loc;
102 // An attribute can be attached to multiple targets (e.g. multiple fields)
104 Attributable[] targets;
107 // A member context for the attribute, it's much easier to hold it here
108 // than trying to pull it during resolve
110 IMemberContext context;
112 public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
113 public static readonly object[] EmptyObject = new object [0];
115 List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
117 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
119 this.expression = expr;
122 named_args = args[1];
125 ExplicitTarget = target;
126 this.nameEscaped = nameEscaped;
129 public Location Location {
135 public Arguments NamedArguments {
141 public Arguments PositionalArguments {
147 public ATypeNameExpression TypeExpression {
153 void AddModuleCharSet (ResolveContext rc)
155 const string dll_import_char_set = "CharSet";
158 // Only when not customized by user
160 if (HasField (dll_import_char_set))
163 if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
167 if (NamedArguments == null)
168 named_args = new Arguments (1);
170 var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
171 NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
174 public Attribute Clone ()
176 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
177 a.pos_args = pos_args;
178 a.named_args = NamedArguments;
183 // When the same attribute is attached to multiple fiels
184 // we use @target field as a list of targets. The attribute
185 // has to be resolved only once but emitted for each target.
187 public void AttachTo (Attributable target, IMemberContext context)
189 if (this.targets == null) {
190 this.targets = new Attributable[] { target };
191 this.context = context;
195 // When re-attaching global attributes
196 if (context is NamespaceContainer) {
197 this.targets[0] = target;
198 this.context = context;
202 // Resize target array
203 Attributable[] new_array = new Attributable [this.targets.Length + 1];
204 targets.CopyTo (new_array, 0);
205 new_array [targets.Length] = target;
206 this.targets = new_array;
208 // No need to update context, different targets cannot have
209 // different contexts, it's enough to remove same attributes
210 // from secondary members.
212 target.OptAttributes = null;
215 public ResolveContext CreateResolveContext ()
217 return new ResolveContext (context, ResolveContext.Options.ConstantScope);
220 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
222 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
223 "must be fields which are not readonly, static, const or read-write properties which are " +
224 "public and not static",
228 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
230 rc.Report.Error (655, name.Location,
231 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
235 public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
237 context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
240 public void Error_MissingGuidAttribute ()
242 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
245 public void Error_MisusedExtensionAttribute ()
247 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
250 public void Error_MisusedDynamicAttribute ()
252 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
256 /// This is rather hack. We report many emit attribute error with same error to be compatible with
257 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
259 public void Error_AttributeEmitError (string inner)
261 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
262 TypeManager.CSharpName (Type), inner);
265 public void Error_InvalidSecurityParent ()
267 Error_AttributeEmitError ("it is attached to invalid parent");
277 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
279 void ResolveAttributeType ()
281 SessionReportPrinter resolve_printer = new SessionReportPrinter ();
282 ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
284 bool t1_is_attr = false;
285 bool t2_is_attr = false;
287 ATypeNameExpression expanded = null;
289 // TODO: Additional warnings such as CS0436 are swallowed because we don't
293 t1 = expression.ResolveAsType (context);
295 t1_is_attr = t1.IsAttribute;
297 resolve_printer.EndSession ();
302 expanded = (ATypeNameExpression) expression.Clone (null);
303 expanded.Name += "Attribute";
305 t2 = expanded.ResolveAsType (context);
307 t2_is_attr = t2.IsAttribute;
310 context.Module.Compiler.Report.SetPrinter (prev_recorder);
313 if (t1_is_attr && t2_is_attr && t1 != t2) {
314 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
315 GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
316 resolve_error = true;
330 resolve_error = true;
333 resolve_printer.Merge (prev_recorder);
335 Report.SymbolRelatedToPreviousError (t1);
336 Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
341 Report.SymbolRelatedToPreviousError (t2);
342 Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
346 resolve_printer.Merge (prev_recorder);
349 public TypeSpec ResolveType ()
351 if (Type == null && !resolve_error)
352 ResolveAttributeType ();
356 public string GetSignatureForError ()
359 return TypeManager.CSharpName (Type);
361 return expression.GetSignatureForError ();
364 public bool HasSecurityAttribute {
366 PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
367 return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
371 public bool IsValidSecurityAttribute ()
373 return HasSecurityAttribute && IsSecurityActionValid ();
376 static bool IsValidArgumentType (TypeSpec t)
379 var ac = (ArrayContainer) t;
386 switch (t.BuiltinType) {
387 case BuiltinTypeSpec.Type.Int:
388 case BuiltinTypeSpec.Type.UInt:
389 case BuiltinTypeSpec.Type.Long:
390 case BuiltinTypeSpec.Type.ULong:
391 case BuiltinTypeSpec.Type.Float:
392 case BuiltinTypeSpec.Type.Double:
393 case BuiltinTypeSpec.Type.Char:
394 case BuiltinTypeSpec.Type.Short:
395 case BuiltinTypeSpec.Type.Bool:
396 case BuiltinTypeSpec.Type.SByte:
397 case BuiltinTypeSpec.Type.Byte:
398 case BuiltinTypeSpec.Type.UShort:
400 case BuiltinTypeSpec.Type.String:
401 case BuiltinTypeSpec.Type.Object:
402 case BuiltinTypeSpec.Type.Dynamic:
403 case BuiltinTypeSpec.Type.Type:
410 // TODO: Don't use this ambiguous value
412 get { return expression.Name; }
415 public Report Report {
416 get { return context.Module.Compiler.Report; }
419 public MethodSpec Resolve ()
424 resolve_error = true;
428 ResolveAttributeType ();
433 if (Type.IsAbstract) {
434 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
438 ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
439 if (obsolete_attr != null) {
440 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
443 ResolveContext rc = null;
446 // Try if the attribute is simple and has been resolved before
447 if (pos_args != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
448 rc = CreateResolveContext ();
449 ctor = ResolveConstructor (rc);
454 if (pos_args == null && ctor.Parameters.IsEmpty)
455 context.Module.AttributeConstructorCache.Add (Type, ctor);
459 // Add [module: DefaultCharSet] to all DllImport import attributes
461 var module = context.Module;
462 if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
464 rc = CreateResolveContext ();
466 AddModuleCharSet (rc);
469 if (NamedArguments != null) {
471 rc = CreateResolveContext ();
473 if (!ResolveNamedArguments (rc))
477 resolve_error = false;
481 MethodSpec ResolveConstructor (ResolveContext ec)
483 if (pos_args != null) {
485 pos_args.Resolve (ec, out dynamic);
487 Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
492 return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
495 bool ResolveNamedArguments (ResolveContext ec)
497 int named_arg_count = NamedArguments.Count;
498 var seen_names = new List<string> (named_arg_count);
500 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
502 foreach (NamedArgument a in NamedArguments) {
503 string name = a.Name;
504 if (seen_names.Contains (name)) {
505 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
509 seen_names.Add (name);
513 Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
515 if (member == null) {
516 member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
518 if (member != null) {
519 // TODO: ec.Report.SymbolRelatedToPreviousError (member);
520 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
526 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
530 if (!(member is PropertyExpr || member is FieldExpr)) {
531 Error_InvalidNamedArgument (ec, a);
535 ObsoleteAttribute obsolete_attr;
537 if (member is PropertyExpr) {
538 var pi = ((PropertyExpr) member).PropertyInfo;
540 if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
541 ec.Report.SymbolRelatedToPreviousError (pi);
542 Error_InvalidNamedArgument (ec, a);
546 if (!IsValidArgumentType (member.Type)) {
547 ec.Report.SymbolRelatedToPreviousError (pi);
548 Error_InvalidNamedArgumentType (ec, a);
552 obsolete_attr = pi.GetAttributeObsolete ();
553 pi.MemberDefinition.SetIsAssigned ();
555 var fi = ((FieldExpr) member).Spec;
557 if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
558 Error_InvalidNamedArgument (ec, a);
562 if (!IsValidArgumentType (member.Type)) {
563 ec.Report.SymbolRelatedToPreviousError (fi);
564 Error_InvalidNamedArgumentType (ec, a);
568 obsolete_attr = fi.GetAttributeObsolete ();
569 fi.MemberDefinition.SetIsAssigned ();
572 if (obsolete_attr != null && !context.IsObsolete)
573 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
575 if (a.Type != member.Type) {
576 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
580 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
587 /// Get a string containing a list of valid targets for the attribute 'attr'
589 public string GetValidTargets ()
591 StringBuilder sb = new StringBuilder ();
592 AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
594 if ((targets & AttributeTargets.Assembly) != 0)
595 sb.Append ("assembly, ");
597 if ((targets & AttributeTargets.Module) != 0)
598 sb.Append ("module, ");
600 if ((targets & AttributeTargets.Class) != 0)
601 sb.Append ("class, ");
603 if ((targets & AttributeTargets.Struct) != 0)
604 sb.Append ("struct, ");
606 if ((targets & AttributeTargets.Enum) != 0)
607 sb.Append ("enum, ");
609 if ((targets & AttributeTargets.Constructor) != 0)
610 sb.Append ("constructor, ");
612 if ((targets & AttributeTargets.Method) != 0)
613 sb.Append ("method, ");
615 if ((targets & AttributeTargets.Property) != 0)
616 sb.Append ("property, indexer, ");
618 if ((targets & AttributeTargets.Field) != 0)
619 sb.Append ("field, ");
621 if ((targets & AttributeTargets.Event) != 0)
622 sb.Append ("event, ");
624 if ((targets & AttributeTargets.Interface) != 0)
625 sb.Append ("interface, ");
627 if ((targets & AttributeTargets.Parameter) != 0)
628 sb.Append ("parameter, ");
630 if ((targets & AttributeTargets.Delegate) != 0)
631 sb.Append ("delegate, ");
633 if ((targets & AttributeTargets.ReturnValue) != 0)
634 sb.Append ("return, ");
636 if ((targets & AttributeTargets.GenericParameter) != 0)
637 sb.Append ("type parameter, ");
639 return sb.Remove (sb.Length - 2, 2).ToString ();
642 public AttributeUsageAttribute GetAttributeUsageAttribute ()
645 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
646 // But because a lot of attribute class code must be rewritten will be better to wait...
650 return DefaultUsageAttribute;
652 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
654 var field = GetNamedValue ("AllowMultiple") as BoolConstant;
656 usage_attribute.AllowMultiple = field.Value;
658 field = GetNamedValue ("Inherited") as BoolConstant;
660 usage_attribute.Inherited = field.Value;
662 return usage_attribute;
666 /// Returns custom name of indexer
668 public string GetIndexerAttributeValue ()
671 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
672 // But because a lot of attribute class code must be rewritten will be better to wait...
675 if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
678 return ((Constant) pos_args[0].Expr).GetValue () as string;
682 /// Returns condition of ConditionalAttribute
684 public string GetConditionalAttributeValue ()
687 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
688 // But because a lot of attribute class code must be rewritten will be better to wait...
694 return ((Constant) pos_args[0].Expr).GetValue () as string;
698 /// Creates the instance of ObsoleteAttribute from this attribute instance
700 public ObsoleteAttribute GetObsoleteAttribute ()
703 // corlib only case when obsolete is used before is resolved
704 var c = Type.MemberDefinition as Class;
705 if (c != null && !c.HasMembersDefined)
708 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
709 // But because a lot of attribute class code must be rewritten will be better to wait...
716 if (pos_args == null)
717 return new ObsoleteAttribute ();
719 string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
720 if (pos_args.Count == 1)
721 return new ObsoleteAttribute (msg);
723 return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
727 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
728 /// before ApplyAttribute. We need to resolve the arguments.
729 /// This situation occurs when class deps is differs from Emit order.
731 public bool GetClsCompliantAttributeValue ()
734 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
735 // But because a lot of attribute class code must be rewritten will be better to wait...
741 return ((BoolConstant) pos_args[0].Expr).Value;
744 public TypeSpec GetCoClassAttributeValue ()
752 return GetArgumentType ();
755 public bool CheckTarget ()
757 string[] valid_targets = Owner.ValidAttributeTargets;
758 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
759 Target = Owner.AttributeTargets;
763 // TODO: we can skip the first item
764 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
765 switch (ExplicitTarget) {
766 case "return": Target = AttributeTargets.ReturnValue; return true;
767 case "param": Target = AttributeTargets.Parameter; return true;
768 case "field": Target = AttributeTargets.Field; return true;
769 case "method": Target = AttributeTargets.Method; return true;
770 case "property": Target = AttributeTargets.Property; return true;
771 case "module": Target = AttributeTargets.Module; return true;
773 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
776 StringBuilder sb = new StringBuilder ();
777 foreach (string s in valid_targets) {
781 sb.Remove (sb.Length - 2, 2);
782 Report.Warning (657, 1, Location,
783 "`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'. All attributes in this section will be ignored",
784 ExplicitTarget, sb.ToString ());
789 /// Tests permitted SecurityAction for assembly or other types
791 bool IsSecurityActionValid ()
793 SecurityAction action = GetSecurityActionValue ();
794 bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
797 #pragma warning disable 618
798 case SecurityAction.Demand:
799 case SecurityAction.Assert:
800 case SecurityAction.Deny:
801 case SecurityAction.PermitOnly:
802 case SecurityAction.LinkDemand:
803 case SecurityAction.InheritanceDemand:
808 case SecurityAction.RequestMinimum:
809 case SecurityAction.RequestOptional:
810 case SecurityAction.RequestRefuse:
814 #pragma warning restore 618
817 Error_AttributeEmitError ("SecurityAction is out of range");
821 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
825 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
827 return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
831 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
833 /// <returns></returns>
834 public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
837 object[] values = new object[pos_args.Count];
838 for (int i = 0; i < values.Length; ++i)
839 values[i] = ((Constant) pos_args[i].Expr).GetValue ();
842 object[] prop_values;
843 if (named_values == null) {
847 prop = new PropertyInfo[named_values.Count];
848 prop_values = new object [named_values.Count];
849 for (int i = 0; i < prop.Length; ++i) {
850 prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
851 prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
855 if (permissions == null)
856 permissions = new SecurityType ();
858 var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
859 permissions.Add (cab);
861 throw new NotSupportedException ();
865 public Constant GetNamedValue (string name)
867 if (named_values == null)
870 for (int i = 0; i < named_values.Count; ++i) {
871 if (named_values [i].Value.Name == name)
872 return named_values [i].Value.Expr as Constant;
878 public CharSet GetCharSetValue ()
880 return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
883 public bool HasField (string fieldName)
885 if (named_values == null)
888 foreach (var na in named_values) {
889 if (na.Value.Name == fieldName)
897 // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
899 public bool IsInternalCall ()
901 return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
904 public MethodImplOptions GetMethodImplOptions ()
906 MethodImplOptions options = 0;
907 if (pos_args.Count == 1) {
908 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
909 } else if (HasField ("Value")) {
910 var named = GetNamedValue ("Value");
911 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
918 // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
920 public bool IsExplicitLayoutKind ()
922 if (pos_args == null || pos_args.Count != 1)
925 var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
926 return value == LayoutKind.Explicit;
929 public Expression GetParameterDefaultValue ()
931 if (pos_args == null)
934 return pos_args[0].Expr;
937 public override bool Equals (object obj)
939 Attribute a = obj as Attribute;
943 return Type == a.Type && Target == a.Target;
946 public override int GetHashCode ()
948 return Type.GetHashCode () ^ Target.GetHashCode ();
952 /// Emit attribute for Attributable symbol
954 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
956 var ctor = Resolve ();
960 var predefined = context.Module.PredefinedAttributes;
962 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
963 if ((usage_attr.ValidOn & Target) == 0) {
964 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
965 "It is valid on `{1}' declarations only",
966 GetSignatureForError (), GetValidTargets ());
971 if (pos_args == null && named_values == null) {
972 cdata = AttributeEncoder.Empty;
974 AttributeEncoder encoder = new AttributeEncoder ();
976 if (pos_args != null) {
977 var param_types = ctor.Parameters.Types;
978 for (int j = 0; j < pos_args.Count; ++j) {
979 var pt = param_types[j];
980 var arg_expr = pos_args[j].Expr;
982 if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
983 string v = ((Constant) arg_expr).GetValue () as string;
984 if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
985 context.Module.Compiler.Report.Error (633, arg_expr.Location,
986 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
989 } else if (Type == predefined.Guid) {
991 string v = ((StringConstant) arg_expr).Value;
993 } catch (Exception e) {
994 Error_AttributeEmitError (e.Message);
997 } else if (Type == predefined.AttributeUsage) {
998 int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
1000 context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1001 "System.AttributeUsage");
1003 } else if (Type == predefined.MarshalAs) {
1004 if (pos_args.Count == 1) {
1005 var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
1006 if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
1007 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
1010 } else if (Type == predefined.DllImport) {
1011 if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
1012 var value = ((Constant) pos_args[0].Expr).GetValue () as string;
1013 if (string.IsNullOrEmpty (value))
1014 Error_AttributeEmitError ("DllName cannot be empty or null");
1016 } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
1017 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
1018 Error_AttributeEmitError ("Incorrect argument value.");
1023 arg_expr.EncodeAttributeValue (context, encoder, pt);
1027 if (named_values != null) {
1028 encoder.Encode ((ushort) named_values.Count);
1029 foreach (var na in named_values) {
1030 if (na.Key is FieldExpr)
1031 encoder.Encode ((byte) 0x53);
1033 encoder.Encode ((byte) 0x54);
1035 encoder.Encode (na.Key.Type);
1036 encoder.Encode (na.Value.Name);
1037 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1040 encoder.EncodeEmptyNamedArguments ();
1043 cdata = encoder.ToArray ();
1047 foreach (Attributable target in targets)
1048 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1049 } catch (Exception e) {
1050 if (e is BadImageFormat && Report.Errors > 0)
1053 Error_AttributeEmitError (e.Message);
1057 if (!usage_attr.AllowMultiple && allEmitted != null) {
1058 if (allEmitted.ContainsKey (this)) {
1059 var a = allEmitted [this];
1061 a = new List<Attribute> (2);
1062 allEmitted [this] = a;
1066 allEmitted.Add (this, null);
1070 if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1073 // Here we are testing attribute arguments for array usage (error 3016)
1074 if (Owner.IsClsComplianceRequired ()) {
1075 if (pos_args != null)
1076 pos_args.CheckArrayAsAttribute (context.Module.Compiler);
1078 if (NamedArguments == null)
1081 NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1085 private Expression GetValue ()
1087 if (pos_args == null || pos_args.Count < 1)
1090 return pos_args[0].Expr;
1093 public string GetString ()
1095 Expression e = GetValue ();
1096 if (e is StringConstant)
1097 return ((StringConstant)e).Value;
1101 public bool GetBoolean ()
1103 Expression e = GetValue ();
1104 if (e is BoolConstant)
1105 return ((BoolConstant)e).Value;
1109 public TypeSpec GetArgumentType ()
1111 TypeOf e = GetValue () as TypeOf;
1114 return e.TypeArgument;
1118 public class Attributes
1120 public readonly List<Attribute> Attrs;
1122 public Attributes (Attribute a)
1124 Attrs = new List<Attribute> ();
1128 public Attributes (List<Attribute> attrs)
1133 public void AddAttribute (Attribute attr)
1138 public void AddAttributes (List<Attribute> attrs)
1140 Attrs.AddRange (attrs);
1143 public void AttachTo (Attributable attributable, IMemberContext context)
1145 foreach (Attribute a in Attrs)
1146 a.AttachTo (attributable, context);
1149 public Attributes Clone ()
1151 var al = new List<Attribute> (Attrs.Count);
1152 foreach (Attribute a in Attrs)
1153 al.Add (a.Clone ());
1155 return new Attributes (al);
1159 /// Checks whether attribute target is valid for the current element
1161 public bool CheckTargets ()
1163 for (int i = 0; i < Attrs.Count; ++i) {
1164 if (!Attrs [i].CheckTarget ())
1165 Attrs.RemoveAt (i--);
1171 public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
1173 var member_explicit_targets = member.ValidAttributeTargets;
1174 for (int i = 0; i < Attrs.Count; ++i) {
1175 var attr = Attrs[0];
1176 if (attr.ExplicitTarget == null)
1180 for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
1181 if (attr.ExplicitTarget == member_explicit_targets[ii]) {
1187 if (ii < 0 || !isGlobal)
1190 member.Module.AddAttribute (attr, currentNamespace);
1196 public Attribute Search (PredefinedAttribute t)
1198 return Search (null, t);
1201 public Attribute Search (string explicitTarget, PredefinedAttribute t)
1203 foreach (Attribute a in Attrs) {
1204 if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1207 if (a.ResolveType () == t)
1214 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1216 public Attribute[] SearchMulti (PredefinedAttribute t)
1218 List<Attribute> ar = null;
1220 foreach (Attribute a in Attrs) {
1221 if (a.ResolveType () == t) {
1223 ar = new List<Attribute> (Attrs.Count);
1228 return ar == null ? null : ar.ToArray ();
1235 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1237 foreach (Attribute a in Attrs)
1240 if (ld == null || ld.Count == 0)
1243 foreach (var d in ld) {
1244 if (d.Value == null)
1247 Attribute a = d.Key;
1249 foreach (Attribute collision in d.Value)
1250 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1252 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1253 a.GetSignatureForError ());
1257 public bool Contains (PredefinedAttribute t)
1259 return Search (t) != null;
1263 public sealed class AttributeEncoder
1266 public enum EncodedTypeProperties
1270 TypeParameter = 1 << 1
1273 public static readonly byte[] Empty;
1277 const ushort Version = 1;
1279 static AttributeEncoder ()
1281 Empty = new byte[4];
1282 Empty[0] = (byte) Version;
1285 public AttributeEncoder ()
1287 buffer = new byte[32];
1291 public void Encode (bool value)
1293 Encode (value ? (byte) 1 : (byte) 0);
1296 public void Encode (byte value)
1298 if (pos == buffer.Length)
1301 buffer [pos++] = value;
1304 public void Encode (sbyte value)
1306 Encode ((byte) value);
1309 public void Encode (short value)
1311 if (pos + 2 > buffer.Length)
1314 buffer[pos++] = (byte) value;
1315 buffer[pos++] = (byte) (value >> 8);
1318 public void Encode (ushort value)
1320 Encode ((short) value);
1323 public void Encode (int value)
1325 if (pos + 4 > buffer.Length)
1328 buffer[pos++] = (byte) value;
1329 buffer[pos++] = (byte) (value >> 8);
1330 buffer[pos++] = (byte) (value >> 16);
1331 buffer[pos++] = (byte) (value >> 24);
1334 public void Encode (uint value)
1336 Encode ((int) value);
1339 public void Encode (long value)
1341 if (pos + 8 > buffer.Length)
1344 buffer[pos++] = (byte) value;
1345 buffer[pos++] = (byte) (value >> 8);
1346 buffer[pos++] = (byte) (value >> 16);
1347 buffer[pos++] = (byte) (value >> 24);
1348 buffer[pos++] = (byte) (value >> 32);
1349 buffer[pos++] = (byte) (value >> 40);
1350 buffer[pos++] = (byte) (value >> 48);
1351 buffer[pos++] = (byte) (value >> 56);
1354 public void Encode (ulong value)
1356 Encode ((long) value);
1359 public void Encode (float value)
1361 Encode (SingleConverter.SingleToInt32Bits (value));
1364 public void Encode (double value)
1366 Encode (BitConverter.DoubleToInt64Bits (value));
1369 public void Encode (string value)
1371 if (value == null) {
1372 Encode ((byte) 0xFF);
1376 var buf = Encoding.UTF8.GetBytes(value);
1377 WriteCompressedValue (buf.Length);
1379 if (pos + buf.Length > buffer.Length)
1382 Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1386 public EncodedTypeProperties Encode (TypeSpec type)
1388 switch (type.BuiltinType) {
1389 case BuiltinTypeSpec.Type.Bool:
1390 Encode ((byte) 0x02);
1392 case BuiltinTypeSpec.Type.Char:
1393 Encode ((byte) 0x03);
1395 case BuiltinTypeSpec.Type.SByte:
1396 Encode ((byte) 0x04);
1398 case BuiltinTypeSpec.Type.Byte:
1399 Encode ((byte) 0x05);
1401 case BuiltinTypeSpec.Type.Short:
1402 Encode ((byte) 0x06);
1404 case BuiltinTypeSpec.Type.UShort:
1405 Encode ((byte) 0x07);
1407 case BuiltinTypeSpec.Type.Int:
1408 Encode ((byte) 0x08);
1410 case BuiltinTypeSpec.Type.UInt:
1411 Encode ((byte) 0x09);
1413 case BuiltinTypeSpec.Type.Long:
1414 Encode ((byte) 0x0A);
1416 case BuiltinTypeSpec.Type.ULong:
1417 Encode ((byte) 0x0B);
1419 case BuiltinTypeSpec.Type.Float:
1420 Encode ((byte) 0x0C);
1422 case BuiltinTypeSpec.Type.Double:
1423 Encode ((byte) 0x0D);
1425 case BuiltinTypeSpec.Type.String:
1426 Encode ((byte) 0x0E);
1428 case BuiltinTypeSpec.Type.Type:
1429 Encode ((byte) 0x50);
1431 case BuiltinTypeSpec.Type.Object:
1432 Encode ((byte) 0x51);
1434 case BuiltinTypeSpec.Type.Dynamic:
1435 Encode ((byte) 0x51);
1436 return EncodedTypeProperties.DynamicType;
1439 Encode ((byte) 0x1D);
1440 return Encode (TypeManager.GetElementType (type));
1443 if (type.Kind == MemberKind.Enum) {
1444 Encode ((byte) 0x55);
1445 EncodeTypeName (type);
1451 return EncodedTypeProperties.None;
1454 public void EncodeTypeName (TypeSpec type)
1456 var old_type = type.GetMetaInfo ();
1457 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1460 public void EncodeTypeName (TypeContainer type)
1462 Encode (type.GetSignatureForMetadata ());
1467 // Encodes single property named argument per call
1469 public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1471 Encode ((ushort) 1); // length
1472 Encode ((byte) 0x54); // property
1473 Encode (property.MemberType);
1474 Encode (property.Name);
1475 value.EncodeAttributeValue (null, this, property.MemberType);
1479 // Encodes single field named argument per call
1481 public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1483 Encode ((ushort) 1); // length
1484 Encode ((byte) 0x53); // field
1485 Encode (field.MemberType);
1486 Encode (field.Name);
1487 value.EncodeAttributeValue (null, this, field.MemberType);
1490 public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1492 Encode ((ushort) members.Length);
1494 for (int i = 0; i < members.Length; ++i)
1496 var member = members[i];
1498 if (member.Kind == MemberKind.Field)
1499 Encode ((byte) 0x53);
1500 else if (member.Kind == MemberKind.Property)
1501 Encode ((byte) 0x54);
1503 throw new NotImplementedException (member.Kind.ToString ());
1505 Encode (member.MemberType);
1506 Encode (member.Name);
1507 values [i].EncodeAttributeValue (null, this, member.MemberType);
1511 public void EncodeEmptyNamedArguments ()
1513 Encode ((ushort) 0);
1518 int size = System.Math.Max (pos * 4, pos + inc + 2);
1519 Array.Resize (ref buffer, size);
1522 void WriteCompressedValue (int value)
1525 Encode ((byte) value);
1529 if (value < 0x4000) {
1530 Encode ((byte) (0x80 | (value >> 8)));
1531 Encode ((byte) value);
1538 public byte[] ToArray ()
1540 byte[] buf = new byte[pos];
1541 Array.Copy (buffer, buf, pos);
1548 /// Helper class for attribute verification routine.
1550 static class AttributeTester
1553 /// Common method for Obsolete error/warning reporting.
1555 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1558 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1562 if (oa.Message == null || oa.Message.Length == 0) {
1563 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1566 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1571 // Predefined attribute types
1573 public class PredefinedAttributes
1575 // Build-in attributes
1576 public readonly PredefinedAttribute ParamArray;
1577 public readonly PredefinedAttribute Out;
1579 // Optional attributes
1580 public readonly PredefinedAttribute Obsolete;
1581 public readonly PredefinedAttribute DllImport;
1582 public readonly PredefinedAttribute MethodImpl;
1583 public readonly PredefinedAttribute MarshalAs;
1584 public readonly PredefinedAttribute In;
1585 public readonly PredefinedAttribute IndexerName;
1586 public readonly PredefinedAttribute Conditional;
1587 public readonly PredefinedAttribute CLSCompliant;
1588 public readonly PredefinedAttribute Security;
1589 public readonly PredefinedAttribute Required;
1590 public readonly PredefinedAttribute Guid;
1591 public readonly PredefinedAttribute AssemblyCulture;
1592 public readonly PredefinedAttribute AssemblyVersion;
1593 public readonly PredefinedAttribute AssemblyAlgorithmId;
1594 public readonly PredefinedAttribute AssemblyFlags;
1595 public readonly PredefinedAttribute AssemblyFileVersion;
1596 public readonly PredefinedAttribute ComImport;
1597 public readonly PredefinedAttribute CoClass;
1598 public readonly PredefinedAttribute AttributeUsage;
1599 public readonly PredefinedAttribute DefaultParameterValue;
1600 public readonly PredefinedAttribute OptionalParameter;
1601 public readonly PredefinedAttribute UnverifiableCode;
1602 public readonly PredefinedAttribute DefaultCharset;
1603 public readonly PredefinedAttribute TypeForwarder;
1604 public readonly PredefinedAttribute FixedBuffer;
1605 public readonly PredefinedAttribute CompilerGenerated;
1606 public readonly PredefinedAttribute InternalsVisibleTo;
1607 public readonly PredefinedAttribute RuntimeCompatibility;
1608 public readonly PredefinedAttribute DebuggerHidden;
1609 public readonly PredefinedAttribute UnsafeValueType;
1610 public readonly PredefinedAttribute UnmanagedFunctionPointer;
1611 public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
1614 public readonly PredefinedAttribute Extension;
1617 public readonly PredefinedDynamicAttribute Dynamic;
1620 public readonly PredefinedStateMachineAttribute AsyncStateMachine;
1621 public readonly PredefinedStateMachineAttribute IteratorStateMachine;
1624 // Optional types which are used as types and for member lookup
1626 public readonly PredefinedAttribute DefaultMember;
1627 public readonly PredefinedDecimalAttribute DecimalConstant;
1628 public readonly PredefinedAttribute StructLayout;
1629 public readonly PredefinedAttribute FieldOffset;
1630 public readonly PredefinedAttribute CallerMemberNameAttribute;
1631 public readonly PredefinedAttribute CallerLineNumberAttribute;
1632 public readonly PredefinedAttribute CallerFilePathAttribute;
1634 public PredefinedAttributes (ModuleContainer module)
1636 ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1637 Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1638 ParamArray.Resolve ();
1641 Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1642 DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1643 MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1644 MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1645 In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1646 IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1647 Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1648 CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1649 Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1650 Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1651 Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1652 AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1653 AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1654 AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1655 AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1656 AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1657 ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1658 CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1659 AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1660 DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1661 OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1662 UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1664 DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1665 TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1666 FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1667 CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1668 InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1669 RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1670 DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1671 UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1672 UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
1673 DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
1675 Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1677 Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1679 DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1680 DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1681 StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1682 FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1684 AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
1685 IteratorStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "IteratorStateMachineAttribute") {
1689 CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
1690 CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
1691 CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
1693 // TODO: Should define only attributes which are used for comparison
1694 const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1695 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1697 foreach (var fi in GetType ().GetFields (all_fields)) {
1698 ((PredefinedAttribute) fi.GetValue (this)).Define ();
1703 public class PredefinedAttribute : PredefinedType
1705 protected MethodSpec ctor;
1707 public PredefinedAttribute (ModuleContainer module, string ns, string name)
1708 : base (module, MemberKind.Class, ns, name)
1714 public MethodSpec Constructor {
1722 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1724 return type == pa.type && pa.type != null;
1727 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1729 return type != pa.type;
1732 public override int GetHashCode ()
1734 return base.GetHashCode ();
1737 public override bool Equals (object obj)
1739 throw new NotSupportedException ();
1742 public void EmitAttribute (ConstructorBuilder builder)
1744 if (ResolveBuilder ())
1745 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1748 public void EmitAttribute (MethodBuilder builder)
1750 if (ResolveBuilder ())
1751 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1754 public void EmitAttribute (PropertyBuilder builder)
1756 if (ResolveBuilder ())
1757 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1760 public void EmitAttribute (FieldBuilder builder)
1762 if (ResolveBuilder ())
1763 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1766 public void EmitAttribute (TypeBuilder builder)
1768 if (ResolveBuilder ())
1769 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1772 public void EmitAttribute (AssemblyBuilder builder)
1774 if (ResolveBuilder ())
1775 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1778 public void EmitAttribute (ModuleBuilder builder)
1780 if (ResolveBuilder ())
1781 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1784 public void EmitAttribute (ParameterBuilder builder)
1786 if (ResolveBuilder ())
1787 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1790 ConstructorInfo GetCtorMetaInfo ()
1792 return (ConstructorInfo) ctor.GetMetaInfo ();
1795 public bool ResolveBuilder ()
1801 // Handle all parameter-less attributes as optional
1806 ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1807 return ctor != null;
1811 public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
1813 public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
1814 : base (module, ns, name)
1818 public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
1820 var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
1824 AttributeEncoder encoder = new AttributeEncoder ();
1825 encoder.Encode ((int) state);
1826 encoder.EncodeEmptyNamedArguments ();
1828 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1832 public class PredefinedDecimalAttribute : PredefinedAttribute
1834 public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1835 : base (module, ns, name)
1839 public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1841 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1845 int[] bits = decimal.GetBits (value);
1846 AttributeEncoder encoder = new AttributeEncoder ();
1847 encoder.Encode ((byte) (bits[3] >> 16));
1848 encoder.Encode ((byte) (bits[3] >> 31));
1849 encoder.Encode ((uint) bits[2]);
1850 encoder.Encode ((uint) bits[1]);
1851 encoder.Encode ((uint) bits[0]);
1852 encoder.EncodeEmptyNamedArguments ();
1854 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1857 public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1859 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1863 int[] bits = decimal.GetBits (value);
1864 AttributeEncoder encoder = new AttributeEncoder ();
1865 encoder.Encode ((byte) (bits[3] >> 16));
1866 encoder.Encode ((byte) (bits[3] >> 31));
1867 encoder.Encode ((uint) bits[2]);
1868 encoder.Encode ((uint) bits[1]);
1869 encoder.Encode ((uint) bits[0]);
1870 encoder.EncodeEmptyNamedArguments ();
1872 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1876 public class PredefinedStateMachineAttribute : PredefinedAttribute
1878 public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
1879 : base (module, ns, name)
1883 public bool IsIterator { get; set; }
1885 public void EmitAttribute (MethodBuilder builder, StateMachine type)
1887 var predefined_ctor = IsIterator ?
1888 module.PredefinedMembers.IteratorStateMachineAttributeCtor :
1889 module.PredefinedMembers.AsyncStateMachineAttributeCtor;
1891 var ctor = predefined_ctor.Get ();
1896 AttributeEncoder encoder = new AttributeEncoder ();
1897 encoder.EncodeTypeName (type);
1898 encoder.EncodeEmptyNamedArguments ();
1900 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1904 public class PredefinedDynamicAttribute : PredefinedAttribute
1908 public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
1909 : base (module, ns, name)
1913 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
1915 if (ResolveTransformationCtor (loc)) {
1916 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1917 builder.SetCustomAttribute (cab);
1921 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
1923 if (ResolveTransformationCtor (loc)) {
1924 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1925 builder.SetCustomAttribute (cab);
1929 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
1931 if (ResolveTransformationCtor (loc)) {
1932 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1933 builder.SetCustomAttribute (cab);
1937 public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
1939 if (ResolveTransformationCtor (loc)) {
1940 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1941 builder.SetCustomAttribute (cab);
1946 // When any element of the type is a dynamic type
1948 // This method builds a transformation array for dynamic types
1949 // used in places where DynamicAttribute cannot be applied to.
1950 // It uses bool flag when type is of dynamic type and each
1951 // section always starts with "false" for some reason.
1953 // LAMESPEC: This should be part of C# specification
1955 // Example: Func<dynamic, int, dynamic[]>
1956 // Transformation: { false, true, false, false, true }
1958 static bool[] GetTransformationFlags (TypeSpec t)
1961 var ac = t as ArrayContainer;
1963 element = GetTransformationFlags (ac.Element);
1964 if (element == null)
1967 bool[] res = new bool[element.Length + 1];
1969 Array.Copy (element, 0, res, 1, element.Length);
1977 List<bool> transform = null;
1978 var targs = t.TypeArguments;
1979 for (int i = 0; i < targs.Length; ++i) {
1980 element = GetTransformationFlags (targs[i]);
1981 if (element != null) {
1982 if (transform == null) {
1983 transform = new List<bool> ();
1984 for (int ii = 0; ii <= i; ++ii)
1985 transform.Add (false);
1988 transform.AddRange (element);
1989 } else if (transform != null) {
1990 transform.Add (false);
1994 if (transform != null)
1995 return transform.ToArray ();
1998 if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1999 return new bool[] { true };
2004 bool ResolveTransformationCtor (Location loc)
2009 tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
2010 return tctor != null;