2 // attribute.cs: Attributes handling
4 // Author: Ravi Pratap (ravi@ximian.com)
5 // Marek Safar (marek.safar@gmail.com)
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-2013 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 bool ResolveError {
149 return resolve_error;
153 public ATypeNameExpression TypeExpression {
159 void AddModuleCharSet (ResolveContext rc)
161 const string dll_import_char_set = "CharSet";
164 // Only when not customized by user
166 if (HasField (dll_import_char_set))
169 if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
173 if (NamedArguments == null)
174 named_args = new Arguments (1);
176 var value = Constant.CreateConstantFromValue (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
177 NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
180 public Attribute Clone ()
182 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
183 a.pos_args = pos_args;
184 a.named_args = NamedArguments;
189 // When the same attribute is attached to multiple fiels
190 // we use @target field as a list of targets. The attribute
191 // has to be resolved only once but emitted for each target.
193 public void AttachTo (Attributable target, IMemberContext context)
195 if (this.targets == null) {
196 this.targets = new Attributable[] { target };
197 this.context = context;
201 // When re-attaching global attributes
202 if (context is NamespaceContainer) {
203 this.targets[0] = target;
204 this.context = context;
208 // Resize target array
209 Attributable[] new_array = new Attributable [this.targets.Length + 1];
210 targets.CopyTo (new_array, 0);
211 new_array [targets.Length] = target;
212 this.targets = new_array;
214 // No need to update context, different targets cannot have
215 // different contexts, it's enough to remove same attributes
216 // from secondary members.
218 target.OptAttributes = null;
221 public ResolveContext CreateResolveContext ()
223 return new ResolveContext (context, ResolveContext.Options.ConstantScope);
226 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
228 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
229 "must be fields which are not readonly, static, const or read-write properties which are " +
230 "public and not static",
234 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
236 rc.Report.Error (655, name.Location,
237 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
241 public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
243 context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
246 public void Error_MissingGuidAttribute ()
248 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
251 public void Error_MisusedExtensionAttribute ()
253 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
256 public void Error_MisusedDynamicAttribute ()
258 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
261 public void Error_MisusedTupleAttribute ()
263 Report.Error (8138, loc, "Do not use `{0}' directly. Use the tuple syntax instead", GetSignatureForError ());
266 void Error_AttributeEmitError (string inner)
268 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
269 Type.GetSignatureForError (), inner);
272 public void Error_InvalidArgumentValue (TypeSpec attributeType)
274 Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", attributeType.GetSignatureForError ());
277 public void Error_InvalidSecurityParent ()
279 Report.Error (7070, Location,
280 "Security attribute `{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations",
281 Type.GetSignatureForError ());
290 public void SetOwner (Attributable owner)
296 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
298 void ResolveAttributeType (bool comparisonOnly)
300 var resolve_printer = new SessionReportPrinter ();
301 SessionReportPrinter secondary_printer = null;
302 ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
304 bool t1_is_attr = false;
305 bool t2_is_attr = false;
307 ATypeNameExpression expanded = null;
309 // TODO: Additional warnings such as CS0436 are swallowed because we don't
313 t1 = expression.ResolveAsType (context);
314 resolve_printer.EndSession ();
316 if (t1 != null && resolve_printer.ErrorsCount == 0)
317 t1_is_attr = t1.IsAttribute;
322 expanded = (ATypeNameExpression) expression.Clone (null);
323 expanded.Name += "Attribute";
325 secondary_printer = new SessionReportPrinter ();
326 Report.SetPrinter (secondary_printer);
327 t2 = expanded.ResolveAsType (context);
328 secondary_printer.EndSession ();
329 if (t2 != null && secondary_printer.ErrorsCount == 0)
330 t2_is_attr = t2.IsAttribute;
332 secondary_printer.EndSession ();
335 context.Module.Compiler.Report.SetPrinter (prev_recorder);
338 if (t1_is_attr && t2_is_attr && t1 != t2) {
339 if (!comparisonOnly) {
340 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
341 GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
342 resolve_error = true;
361 resolve_error = true;
364 if (resolve_printer.IsEmpty) {
365 Report.SymbolRelatedToPreviousError (t1);
366 Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
368 resolve_printer.Merge (prev_recorder);
375 if (secondary_printer.IsEmpty) {
376 Report.SymbolRelatedToPreviousError (t2);
377 Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
379 secondary_printer.Merge (prev_recorder);
385 resolve_printer.Merge (prev_recorder);
388 public TypeSpec ResolveTypeForComparison ()
390 if (Type == null && !resolve_error)
391 ResolveAttributeType (true);
395 public string GetSignatureForError ()
398 return Type.GetSignatureForError ();
400 return expression.GetSignatureForError ();
403 public bool HasSecurityAttribute {
405 PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
406 return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
410 public bool IsValidSecurityAttribute ()
412 return HasSecurityAttribute && IsSecurityActionValid ();
415 static bool IsValidMethodImplOption (int value)
418 // Allow to use AggressiveInlining on any runtime/corlib
420 MethodImplOptions all = (MethodImplOptions) 256;
421 foreach (MethodImplOptions v in System.Enum.GetValues (typeof (MethodImplOptions))) {
425 return ((MethodImplOptions) value | all) == all;
428 public static bool IsValidArgumentType (TypeSpec t)
431 var ac = (ArrayContainer) t;
438 switch (t.BuiltinType) {
439 case BuiltinTypeSpec.Type.Int:
440 case BuiltinTypeSpec.Type.UInt:
441 case BuiltinTypeSpec.Type.Long:
442 case BuiltinTypeSpec.Type.ULong:
443 case BuiltinTypeSpec.Type.Float:
444 case BuiltinTypeSpec.Type.Double:
445 case BuiltinTypeSpec.Type.Char:
446 case BuiltinTypeSpec.Type.Short:
447 case BuiltinTypeSpec.Type.Bool:
448 case BuiltinTypeSpec.Type.SByte:
449 case BuiltinTypeSpec.Type.Byte:
450 case BuiltinTypeSpec.Type.UShort:
452 case BuiltinTypeSpec.Type.String:
453 case BuiltinTypeSpec.Type.Object:
454 case BuiltinTypeSpec.Type.Dynamic:
455 case BuiltinTypeSpec.Type.Type:
462 // TODO: Don't use this ambiguous value
464 get { return expression.Name; }
467 public Report Report {
468 get { return context.Module.Compiler.Report; }
471 public MethodSpec Resolve ()
476 resolve_error = true;
480 ResolveAttributeType (false);
485 if (Type.IsAbstract) {
486 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
490 Type.CheckObsoleteness (context, expression.StartLocation);
492 ResolveContext rc = null;
495 // Try if the attribute is simple and has been resolved before
496 if (pos_args != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
497 rc = CreateResolveContext ();
498 ctor = ResolveConstructor (rc);
503 if (pos_args == null && ctor.Parameters.IsEmpty)
504 context.Module.AttributeConstructorCache.Add (Type, ctor);
508 // Add [module: DefaultCharSet] to all DllImport import attributes
510 var module = context.Module;
511 if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
513 rc = CreateResolveContext ();
515 AddModuleCharSet (rc);
518 if (NamedArguments != null) {
520 rc = CreateResolveContext ();
522 if (!ResolveNamedArguments (rc))
526 resolve_error = false;
530 MethodSpec ResolveConstructor (ResolveContext ec)
532 if (pos_args != null) {
534 pos_args.Resolve (ec, out dynamic);
536 Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
541 return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
544 bool ResolveNamedArguments (ResolveContext ec)
546 int named_arg_count = NamedArguments.Count;
547 var seen_names = new List<string> (named_arg_count);
549 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
551 foreach (NamedArgument a in NamedArguments) {
552 string name = a.Name;
553 if (seen_names.Contains (name)) {
554 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
558 seen_names.Add (name);
562 Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
564 if (member == null) {
565 member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
567 if (member != null) {
568 // TODO: ec.Report.SymbolRelatedToPreviousError (member);
569 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
575 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
579 if (!(member is PropertyExpr || member is FieldExpr)) {
580 Error_InvalidNamedArgument (ec, a);
584 if (member is PropertyExpr) {
585 var pi = ((PropertyExpr) member).PropertyInfo;
587 if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
588 ec.Report.SymbolRelatedToPreviousError (pi);
589 Error_InvalidNamedArgument (ec, a);
593 if (!IsValidArgumentType (member.Type)) {
594 ec.Report.SymbolRelatedToPreviousError (pi);
595 Error_InvalidNamedArgumentType (ec, a);
599 // if (!context.IsObsolete)
600 pi.CheckObsoleteness (ec, member.StartLocation);
602 pi.MemberDefinition.SetIsAssigned ();
604 var fi = ((FieldExpr) member).Spec;
606 if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
607 Error_InvalidNamedArgument (ec, a);
611 if (!IsValidArgumentType (member.Type)) {
612 ec.Report.SymbolRelatedToPreviousError (fi);
613 Error_InvalidNamedArgumentType (ec, a);
617 // if (!context.IsObsolete)
618 fi.CheckObsoleteness (ec, member.StartLocation);
620 fi.MemberDefinition.SetIsAssigned ();
623 if (a.Type != member.Type) {
624 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
628 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
635 /// Get a string containing a list of valid targets for the attribute 'attr'
637 public string GetValidTargets ()
639 StringBuilder sb = new StringBuilder ();
640 AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
642 if ((targets & AttributeTargets.Assembly) != 0)
643 sb.Append ("assembly, ");
645 if ((targets & AttributeTargets.Module) != 0)
646 sb.Append ("module, ");
648 if ((targets & AttributeTargets.Class) != 0)
649 sb.Append ("class, ");
651 if ((targets & AttributeTargets.Struct) != 0)
652 sb.Append ("struct, ");
654 if ((targets & AttributeTargets.Enum) != 0)
655 sb.Append ("enum, ");
657 if ((targets & AttributeTargets.Constructor) != 0)
658 sb.Append ("constructor, ");
660 if ((targets & AttributeTargets.Method) != 0)
661 sb.Append ("method, ");
663 if ((targets & AttributeTargets.Property) != 0)
664 sb.Append ("property, indexer, ");
666 if ((targets & AttributeTargets.Field) != 0)
667 sb.Append ("field, ");
669 if ((targets & AttributeTargets.Event) != 0)
670 sb.Append ("event, ");
672 if ((targets & AttributeTargets.Interface) != 0)
673 sb.Append ("interface, ");
675 if ((targets & AttributeTargets.Parameter) != 0)
676 sb.Append ("parameter, ");
678 if ((targets & AttributeTargets.Delegate) != 0)
679 sb.Append ("delegate, ");
681 if ((targets & AttributeTargets.ReturnValue) != 0)
682 sb.Append ("return, ");
684 if ((targets & AttributeTargets.GenericParameter) != 0)
685 sb.Append ("type parameter, ");
687 return sb.Remove (sb.Length - 2, 2).ToString ();
690 public AttributeUsageAttribute GetAttributeUsageAttribute ()
693 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
694 // But because a lot of attribute class code must be rewritten will be better to wait...
698 return DefaultUsageAttribute;
700 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
702 var field = GetNamedValue ("AllowMultiple") as BoolConstant;
704 usage_attribute.AllowMultiple = field.Value;
706 field = GetNamedValue ("Inherited") as BoolConstant;
708 usage_attribute.Inherited = field.Value;
710 return usage_attribute;
714 /// Returns custom name of indexer
716 public string GetIndexerAttributeValue ()
719 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
720 // But because a lot of attribute class code must be rewritten will be better to wait...
723 if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
726 return ((Constant) pos_args[0].Expr).GetValue () as string;
730 /// Returns condition of ConditionalAttribute
732 public string GetConditionalAttributeValue ()
735 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
736 // But because a lot of attribute class code must be rewritten will be better to wait...
742 return ((Constant) pos_args[0].Expr).GetValue () as string;
746 /// Creates the instance of ObsoleteAttribute from this attribute instance
748 public ObsoleteAttribute GetObsoleteAttribute ()
751 // corlib only case when obsolete is used before is resolved
752 var c = Type.MemberDefinition as Class;
753 if (c != null && !c.HasMembersDefined)
756 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
757 // But because a lot of attribute class code must be rewritten will be better to wait...
764 if (pos_args == null)
765 return new ObsoleteAttribute ();
767 string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
768 if (pos_args.Count == 1)
769 return new ObsoleteAttribute (msg);
771 return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
775 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
776 /// before ApplyAttribute. We need to resolve the arguments.
777 /// This situation occurs when class deps is differs from Emit order.
779 public bool GetClsCompliantAttributeValue ()
782 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
783 // But because a lot of attribute class code must be rewritten will be better to wait...
789 return ((BoolConstant) pos_args[0].Expr).Value;
792 public TypeSpec GetCoClassAttributeValue ()
800 return GetArgumentType ();
803 public bool CheckTarget ()
805 string[] valid_targets = Owner.ValidAttributeTargets;
806 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
807 Target = Owner.AttributeTargets;
811 // TODO: we can skip the first item
812 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
813 switch (ExplicitTarget) {
814 case "return": Target = AttributeTargets.ReturnValue; return true;
815 case "param": Target = AttributeTargets.Parameter; return true;
816 case "field": Target = AttributeTargets.Field; return true;
817 case "method": Target = AttributeTargets.Method; return true;
818 case "property": Target = AttributeTargets.Property; return true;
819 case "module": Target = AttributeTargets.Module; return true;
821 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
824 StringBuilder sb = new StringBuilder ();
825 foreach (string s in valid_targets) {
829 sb.Remove (sb.Length - 2, 2);
830 Report.Warning (657, 1, Location,
831 "`{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",
832 ExplicitTarget, sb.ToString ());
837 /// Tests permitted SecurityAction for assembly or other types
839 bool IsSecurityActionValid ()
842 var action = GetSecurityActionValue (ref c);
843 bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
846 #pragma warning disable 618
847 case SecurityAction.Demand:
848 case SecurityAction.Assert:
849 case SecurityAction.Deny:
850 case SecurityAction.PermitOnly:
851 case SecurityAction.LinkDemand:
852 case SecurityAction.InheritanceDemand:
857 case SecurityAction.RequestMinimum:
858 case SecurityAction.RequestOptional:
859 case SecurityAction.RequestRefuse:
863 #pragma warning restore 618
865 Report.Error (7048, loc, "First argument of a security attribute `{0}' must be a valid SecurityAction",
866 Type.GetSignatureForError ());
870 Report.Error (7049, c.Location, "Security attribute `{0}' has an invalid SecurityAction value `{1}'",
871 Type.GetSignatureForError (), c.GetValueAsLiteral());
876 case AttributeTargets.Assembly:
877 Report.Error (7050, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to an assembly",
878 c.GetSignatureForError ());
881 Report.Error (7051, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to a type or a method",
882 c.GetSignatureForError ());
889 SecurityAction? GetSecurityActionValue (ref Constant value)
891 if (pos_args == null) {
892 var predefined = context.Module.PredefinedAttributes;
895 // BCL defines System.Security.Permissions.HostProtectionAttribute with parameterless
896 // contructor which should not be valid but it's already part of the framework
898 if (Type == predefined.HostProtection.TypeSpec) {
899 value = new IntConstant (context.Module.Compiler.BuiltinTypes, (int)SecurityAction.LinkDemand, loc);
900 return SecurityAction.LinkDemand;
906 value = (Constant) pos_args [0].Expr;
907 return (SecurityAction) value.GetValue ();
911 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
913 /// <returns></returns>
914 public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
918 if (pos_args != null) {
919 values = new object[pos_args.Count];
920 for (int i = 0; i < values.Length; ++i)
921 values[i] = ((Constant) pos_args[i].Expr).GetValue ();
927 object[] prop_values;
928 if (named_values == null) {
932 prop = new PropertyInfo[named_values.Count];
933 prop_values = new object [named_values.Count];
934 for (int i = 0; i < prop.Length; ++i) {
935 prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
936 prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
940 if (permissions == null)
941 permissions = new SecurityType ();
943 var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
944 permissions.Add (cab);
946 throw new NotSupportedException ();
950 public Constant GetNamedValue (string name)
952 if (named_values == null)
955 for (int i = 0; i < named_values.Count; ++i) {
956 if (named_values [i].Value.Name == name)
957 return named_values [i].Value.Expr as Constant;
963 public CharSet GetCharSetValue ()
965 return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
968 public bool HasField (string fieldName)
970 if (named_values == null)
973 foreach (var na in named_values) {
974 if (na.Value.Name == fieldName)
982 // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
984 public bool IsInternalCall ()
986 return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
989 public MethodImplOptions GetMethodImplOptions ()
991 MethodImplOptions options = 0;
992 if (pos_args.Count == 1) {
993 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
994 } else if (HasField ("Value")) {
995 var named = GetNamedValue ("Value");
996 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
1003 // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
1005 public bool IsExplicitLayoutKind ()
1007 if (pos_args == null || pos_args.Count != 1)
1010 var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
1011 return value == LayoutKind.Explicit;
1014 public Expression GetParameterDefaultValue ()
1016 if (pos_args == null)
1019 return pos_args[0].Expr;
1022 public override bool Equals (object obj)
1024 Attribute a = obj as Attribute;
1028 return Type == a.Type && Target == a.Target;
1031 public override int GetHashCode ()
1033 return Type.GetHashCode () ^ Target.GetHashCode ();
1037 /// Emit attribute for Attributable symbol
1039 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1041 var ctor = Resolve ();
1045 var predefined = context.Module.PredefinedAttributes;
1047 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
1048 if ((usage_attr.ValidOn & Target) == 0) {
1049 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1050 "It is valid on `{1}' declarations only",
1051 GetSignatureForError (), GetValidTargets ());
1056 if (pos_args == null && named_values == null) {
1057 cdata = AttributeEncoder.Empty;
1059 AttributeEncoder encoder = new AttributeEncoder ();
1061 if (pos_args != null) {
1062 var param_types = ctor.Parameters.Types;
1063 for (int j = 0; j < pos_args.Count; ++j) {
1064 var pt = param_types[j];
1065 var arg_expr = pos_args[j].Expr;
1067 if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
1068 string v = ((Constant) arg_expr).GetValue () as string;
1069 if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
1070 context.Module.Compiler.Report.Error (633, arg_expr.Location,
1071 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1074 } else if (Type == predefined.Guid) {
1075 string v = ((StringConstant) arg_expr).Value;
1079 Error_InvalidArgumentValue (Type);
1082 } else if (Type == predefined.AttributeUsage) {
1083 int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
1085 Error_InvalidArgumentValue (Type);
1086 } else if (Type == predefined.MarshalAs) {
1087 if (pos_args.Count == 1) {
1088 var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
1089 if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
1090 Report.Error (7055, pos_args [0].Expr.Location, "Unmanaged type `ByValArray' is only valid for fields");
1093 } else if (Type == predefined.DllImport) {
1094 if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
1095 var value = ((Constant) pos_args[0].Expr).GetValue () as string;
1096 if (string.IsNullOrEmpty (value))
1097 Error_InvalidArgumentValue (Type);
1099 } else if (Type == predefined.MethodImpl) {
1100 if (pos_args.Count == 1) {
1101 var value = (int) ((Constant) arg_expr).GetValueAsLong ();
1103 if (!IsValidMethodImplOption (value)) {
1104 Error_InvalidArgumentValue (Type);
1110 arg_expr.EncodeAttributeValue (context, encoder, pt, pt);
1114 if (named_values != null) {
1115 encoder.Encode ((ushort) named_values.Count);
1116 foreach (var na in named_values) {
1117 if (na.Key is FieldExpr)
1118 encoder.Encode ((byte) 0x53);
1120 encoder.Encode ((byte) 0x54);
1122 encoder.Encode (na.Key.Type);
1123 encoder.Encode (na.Value.Name);
1124 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type, na.Key.Type);
1127 encoder.EncodeEmptyNamedArguments ();
1130 cdata = encoder.ToArray ();
1133 if (!IsConditionallyExcluded (ctor.DeclaringType)) {
1134 if (Type == predefined.TupleElementNames) {
1135 Error_MisusedTupleAttribute ();
1140 foreach (Attributable target in targets)
1141 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1142 } catch (Exception e) {
1143 if (e is BadImageFormat && Report.Errors > 0)
1146 Error_AttributeEmitError (e.Message);
1151 if (!usage_attr.AllowMultiple && allEmitted != null) {
1152 if (allEmitted.ContainsKey (this)) {
1153 var a = allEmitted [this];
1155 a = new List<Attribute> (2);
1156 allEmitted [this] = a;
1160 allEmitted.Add (this, null);
1164 if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1167 // Here we are testing attribute arguments for array usage (error 3016)
1168 if (Owner.IsClsComplianceRequired ()) {
1169 if (pos_args != null)
1170 pos_args.CheckArrayAsAttribute (context.Module.Compiler);
1172 if (NamedArguments == null)
1175 NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1179 bool IsConditionallyExcluded (TypeSpec type)
1182 if (type.IsConditionallyExcluded (context))
1185 type = type.BaseType;
1186 } while (type != null);
1191 private Expression GetValue ()
1193 if (pos_args == null || pos_args.Count < 1)
1196 return pos_args[0].Expr;
1199 public string GetString ()
1201 Expression e = GetValue ();
1202 if (e is StringConstant)
1203 return ((StringConstant)e).Value;
1207 public bool GetBoolean ()
1209 Expression e = GetValue ();
1210 if (e is BoolConstant)
1211 return ((BoolConstant)e).Value;
1215 public TypeSpec GetArgumentType ()
1217 TypeOf e = GetValue () as TypeOf;
1220 return e.TypeArgument;
1224 public class Attributes
1226 public readonly List<Attribute> Attrs;
1228 public Attributes (Attribute a)
1230 Attrs = new List<Attribute> ();
1234 public Attributes (List<Attribute> attrs)
1236 Attrs = attrs ?? new List<Attribute> ();
1239 public void AddAttribute (Attribute attr)
1244 public void AddAttributes (List<Attribute> attrs)
1246 Attrs.AddRange (attrs);
1249 public static void AttachFromPartial (Attributable target, Attributable partialSrc)
1251 if (target.OptAttributes == null) {
1252 target.OptAttributes = partialSrc.OptAttributes;
1254 target.OptAttributes.Attrs.AddRange (partialSrc.OptAttributes.Attrs);
1257 foreach (var attr in partialSrc.OptAttributes.Attrs) {
1258 attr.SetOwner (target);
1262 public void AttachTo (Attributable attributable, IMemberContext context)
1264 foreach (Attribute a in Attrs)
1265 a.AttachTo (attributable, context);
1268 public Attributes Clone ()
1270 var al = new List<Attribute> (Attrs.Count);
1271 foreach (Attribute a in Attrs)
1272 al.Add (a.Clone ());
1274 return new Attributes (al);
1278 /// Checks whether attribute target is valid for the current element
1280 public bool CheckTargets ()
1282 for (int i = 0; i < Attrs.Count; ++i) {
1283 if (!Attrs [i].CheckTarget ())
1284 Attrs.RemoveAt (i--);
1290 public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
1292 var member_explicit_targets = member.ValidAttributeTargets;
1293 for (int i = 0; i < Attrs.Count; ++i) {
1294 var attr = Attrs[0];
1295 if (attr.ExplicitTarget == null)
1299 for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
1300 if (attr.ExplicitTarget == member_explicit_targets[ii]) {
1306 if (ii < 0 || !isGlobal)
1309 member.Module.AddAttribute (attr, currentNamespace);
1315 public bool HasResolveError()
1317 foreach (var a in Attrs) {
1325 public Attribute Search (PredefinedAttribute t)
1327 return Search (null, t);
1330 public Attribute Search (string explicitTarget, PredefinedAttribute t)
1332 foreach (Attribute a in Attrs) {
1333 if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1336 if (a.ResolveTypeForComparison () == t)
1343 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1345 public Attribute[] SearchMulti (PredefinedAttribute t)
1347 List<Attribute> ar = null;
1349 foreach (Attribute a in Attrs) {
1350 if (a.ResolveTypeForComparison () == t) {
1352 ar = new List<Attribute> (Attrs.Count);
1357 return ar == null ? null : ar.ToArray ();
1364 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1366 foreach (Attribute a in Attrs)
1369 if (ld == null || ld.Count == 0)
1372 foreach (var d in ld) {
1373 if (d.Value == null)
1376 Attribute a = d.Key;
1378 foreach (Attribute collision in d.Value)
1379 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1381 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1382 a.GetSignatureForError ());
1386 public bool Contains (PredefinedAttribute t)
1388 return Search (t) != null;
1392 public sealed class AttributeEncoder
1395 public enum EncodedTypeProperties
1399 TypeParameter = 1 << 1
1402 public static readonly byte[] Empty;
1406 const ushort Version = 1;
1408 static AttributeEncoder ()
1410 Empty = new byte[4];
1411 Empty[0] = (byte) Version;
1414 public AttributeEncoder ()
1416 buffer = new byte[32];
1420 public void Encode (bool value)
1422 Encode (value ? (byte) 1 : (byte) 0);
1425 public void Encode (byte value)
1427 if (pos == buffer.Length)
1430 buffer [pos++] = value;
1433 public void Encode (sbyte value)
1435 Encode ((byte) value);
1438 public void Encode (short value)
1440 if (pos + 2 > buffer.Length)
1443 buffer[pos++] = (byte) value;
1444 buffer[pos++] = (byte) (value >> 8);
1447 public void Encode (ushort value)
1449 Encode ((short) value);
1452 public void Encode (int value)
1454 if (pos + 4 > buffer.Length)
1457 buffer[pos++] = (byte) value;
1458 buffer[pos++] = (byte) (value >> 8);
1459 buffer[pos++] = (byte) (value >> 16);
1460 buffer[pos++] = (byte) (value >> 24);
1463 public void Encode (uint value)
1465 Encode ((int) value);
1468 public void Encode (long value)
1470 if (pos + 8 > buffer.Length)
1473 buffer[pos++] = (byte) value;
1474 buffer[pos++] = (byte) (value >> 8);
1475 buffer[pos++] = (byte) (value >> 16);
1476 buffer[pos++] = (byte) (value >> 24);
1477 buffer[pos++] = (byte) (value >> 32);
1478 buffer[pos++] = (byte) (value >> 40);
1479 buffer[pos++] = (byte) (value >> 48);
1480 buffer[pos++] = (byte) (value >> 56);
1483 public void Encode (ulong value)
1485 Encode ((long) value);
1488 public void Encode (float value)
1490 Encode (SingleConverter.SingleToInt32Bits (value));
1493 public void Encode (double value)
1495 Encode (BitConverter.DoubleToInt64Bits (value));
1498 public void Encode (string value)
1500 if (value == null) {
1501 Encode ((byte) 0xFF);
1505 var buf = Encoding.UTF8.GetBytes(value);
1506 WriteCompressedValue (buf.Length);
1508 if (pos + buf.Length > buffer.Length)
1511 Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1515 public EncodedTypeProperties Encode (TypeSpec type)
1517 switch (type.BuiltinType) {
1518 case BuiltinTypeSpec.Type.Bool:
1519 Encode ((byte) 0x02);
1521 case BuiltinTypeSpec.Type.Char:
1522 Encode ((byte) 0x03);
1524 case BuiltinTypeSpec.Type.SByte:
1525 Encode ((byte) 0x04);
1527 case BuiltinTypeSpec.Type.Byte:
1528 Encode ((byte) 0x05);
1530 case BuiltinTypeSpec.Type.Short:
1531 Encode ((byte) 0x06);
1533 case BuiltinTypeSpec.Type.UShort:
1534 Encode ((byte) 0x07);
1536 case BuiltinTypeSpec.Type.Int:
1537 Encode ((byte) 0x08);
1539 case BuiltinTypeSpec.Type.UInt:
1540 Encode ((byte) 0x09);
1542 case BuiltinTypeSpec.Type.Long:
1543 Encode ((byte) 0x0A);
1545 case BuiltinTypeSpec.Type.ULong:
1546 Encode ((byte) 0x0B);
1548 case BuiltinTypeSpec.Type.Float:
1549 Encode ((byte) 0x0C);
1551 case BuiltinTypeSpec.Type.Double:
1552 Encode ((byte) 0x0D);
1554 case BuiltinTypeSpec.Type.String:
1555 Encode ((byte) 0x0E);
1557 case BuiltinTypeSpec.Type.Type:
1558 Encode ((byte) 0x50);
1560 case BuiltinTypeSpec.Type.Object:
1561 Encode ((byte) 0x51);
1563 case BuiltinTypeSpec.Type.Dynamic:
1564 Encode ((byte) 0x51);
1565 return EncodedTypeProperties.DynamicType;
1568 Encode ((byte) 0x1D);
1569 return Encode (TypeManager.GetElementType (type));
1572 if (type.Kind == MemberKind.Enum) {
1573 Encode ((byte) 0x55);
1574 EncodeTypeName (type);
1580 return EncodedTypeProperties.None;
1583 public void EncodeTypeName (TypeSpec type)
1585 var old_type = type.GetMetaInfo ();
1586 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1589 public void EncodeTypeName (TypeContainer type)
1591 Encode (type.GetSignatureForMetadata ());
1596 // Encodes single property named argument per call
1598 public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1600 Encode ((ushort) 1); // length
1601 Encode ((byte) 0x54); // property
1602 Encode (property.MemberType);
1603 Encode (property.Name);
1604 value.EncodeAttributeValue (null, this, property.MemberType, property.MemberType);
1608 // Encodes single field named argument per call
1610 public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1612 Encode ((ushort) 1); // length
1613 Encode ((byte) 0x53); // field
1614 Encode (field.MemberType);
1615 Encode (field.Name);
1616 value.EncodeAttributeValue (null, this, field.MemberType, field.MemberType);
1619 public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1621 Encode ((ushort) members.Length);
1623 for (int i = 0; i < members.Length; ++i)
1625 var member = members[i];
1627 if (member.Kind == MemberKind.Field)
1628 Encode ((byte) 0x53);
1629 else if (member.Kind == MemberKind.Property)
1630 Encode ((byte) 0x54);
1632 throw new NotImplementedException (member.Kind.ToString ());
1634 Encode (member.MemberType);
1635 Encode (member.Name);
1636 values [i].EncodeAttributeValue (null, this, member.MemberType, member.MemberType);
1640 public void EncodeEmptyNamedArguments ()
1642 Encode ((ushort) 0);
1647 int size = System.Math.Max (pos * 4, pos + inc + 2);
1648 Array.Resize (ref buffer, size);
1651 void WriteCompressedValue (int value)
1654 Encode ((byte) value);
1658 if (value < 0x4000) {
1659 Encode ((byte) (0x80 | (value >> 8)));
1660 Encode ((byte) value);
1667 public byte[] ToArray ()
1669 byte[] buf = new byte[pos];
1670 Array.Copy (buffer, buf, pos);
1677 /// Helper class for attribute verification routine.
1679 static class AttributeTester
1682 /// Common method for Obsolete error/warning reporting.
1684 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1687 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1691 if (oa.Message == null || oa.Message.Length == 0) {
1692 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1695 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1700 // Predefined attribute types
1702 public class PredefinedAttributes
1704 // Build-in attributes
1705 public readonly PredefinedAttribute ParamArray;
1706 public readonly PredefinedAttribute Out;
1708 // Optional attributes
1709 public readonly PredefinedAttribute Obsolete;
1710 public readonly PredefinedAttribute DllImport;
1711 public readonly PredefinedAttribute MethodImpl;
1712 public readonly PredefinedAttribute MarshalAs;
1713 public readonly PredefinedAttribute In;
1714 public readonly PredefinedAttribute IndexerName;
1715 public readonly PredefinedAttribute Conditional;
1716 public readonly PredefinedAttribute CLSCompliant;
1717 public readonly PredefinedAttribute Security;
1718 public readonly PredefinedAttribute Required;
1719 public readonly PredefinedAttribute Guid;
1720 public readonly PredefinedAttribute AssemblyCulture;
1721 public readonly PredefinedAttribute AssemblyVersion;
1722 public readonly PredefinedAttribute AssemblyAlgorithmId;
1723 public readonly PredefinedAttribute AssemblyFlags;
1724 public readonly PredefinedAttribute AssemblyFileVersion;
1725 public readonly PredefinedAttribute AssemblyInformationalVersion;
1726 public readonly PredefinedAttribute ComImport;
1727 public readonly PredefinedAttribute CoClass;
1728 public readonly PredefinedAttribute AttributeUsage;
1729 public readonly PredefinedAttribute DefaultParameterValue;
1730 public readonly PredefinedAttribute OptionalParameter;
1731 public readonly PredefinedAttribute UnverifiableCode;
1732 public readonly PredefinedAttribute DefaultCharset;
1733 public readonly PredefinedAttribute TypeForwarder;
1734 public readonly PredefinedAttribute FixedBuffer;
1735 public readonly PredefinedAttribute CompilerGenerated;
1736 public readonly PredefinedAttribute InternalsVisibleTo;
1737 public readonly PredefinedAttribute RuntimeCompatibility;
1738 public readonly PredefinedAttribute DebuggerHidden;
1739 public readonly PredefinedAttribute UnsafeValueType;
1740 public readonly PredefinedAttribute UnmanagedFunctionPointer;
1741 public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
1742 public readonly PredefinedAttribute DebuggerStepThrough;
1743 public readonly PredefinedDebuggableAttribute Debuggable;
1744 public readonly PredefinedAttribute HostProtection;
1747 public readonly PredefinedAttribute Extension;
1750 public readonly PredefinedDynamicAttribute Dynamic;
1753 public readonly PredefinedStateMachineAttribute AsyncStateMachine;
1756 public readonly PredefinedTupleElementNamesAttribute TupleElementNames;
1758 // New in .NET 4.7.1
1759 public readonly PredefinedAttribute IsReadOnly;
1762 // Optional types which are used as types and for member lookup
1764 public readonly PredefinedAttribute DefaultMember;
1765 public readonly PredefinedDecimalAttribute DecimalConstant;
1766 public readonly PredefinedAttribute StructLayout;
1767 public readonly PredefinedAttribute FieldOffset;
1768 public readonly PredefinedAttribute AssemblyProduct;
1769 public readonly PredefinedAttribute AssemblyCompany;
1770 public readonly PredefinedAttribute AssemblyCopyright;
1771 public readonly PredefinedAttribute AssemblyTrademark;
1772 public readonly PredefinedAttribute CallerMemberNameAttribute;
1773 public readonly PredefinedAttribute CallerLineNumberAttribute;
1774 public readonly PredefinedAttribute CallerFilePathAttribute;
1776 public PredefinedAttributes (ModuleContainer module)
1778 ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1779 Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1780 ParamArray.Resolve ();
1783 Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1784 DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1785 MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1786 MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1787 In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1788 IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1789 Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1790 CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1791 Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1792 Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1793 Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1794 AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1795 AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1796 AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1797 AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1798 AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1799 ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1800 CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1801 AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1802 DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1803 OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1804 UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1805 HostProtection = new PredefinedAttribute (module, "System.Security.Permissions", "HostProtectionAttribute");
1807 DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1808 TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1809 FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1810 CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1811 InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1812 RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1813 DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1814 UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1815 UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
1816 DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
1817 DebuggerStepThrough = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerStepThroughAttribute");
1818 Debuggable = new PredefinedDebuggableAttribute (module, "System.Diagnostics", "DebuggableAttribute");
1820 Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1822 Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1824 DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1825 DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1826 StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1827 FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1828 AssemblyProduct = new PredefinedAttribute (module, "System.Reflection", "AssemblyProductAttribute");
1829 AssemblyCompany = new PredefinedAttribute (module, "System.Reflection", "AssemblyCompanyAttribute");
1830 AssemblyCopyright = new PredefinedAttribute (module, "System.Reflection", "AssemblyCopyrightAttribute");
1831 AssemblyTrademark = new PredefinedAttribute (module, "System.Reflection", "AssemblyTrademarkAttribute");
1832 AssemblyInformationalVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyInformationalVersionAttribute");
1834 AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
1836 CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
1837 CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
1838 CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
1840 TupleElementNames = new PredefinedTupleElementNamesAttribute (module, "System.Runtime.CompilerServices", "TupleElementNamesAttribute");
1841 IsReadOnly = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IsReadOnlyAttribute");
1843 // TODO: Should define only attributes which are used for comparison
1844 const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1845 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1847 foreach (var fi in GetType ().GetFields (all_fields)) {
1848 ((PredefinedAttribute) fi.GetValue (this)).Define ();
1853 public class PredefinedAttribute : PredefinedType
1855 protected MethodSpec ctor;
1857 public PredefinedAttribute (ModuleContainer module, string ns, string name)
1858 : base (module, MemberKind.Class, ns, name)
1864 public MethodSpec Constructor {
1872 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1874 return type == pa.type && pa.type != null;
1877 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1879 return type != pa.type;
1882 public override int GetHashCode ()
1884 return base.GetHashCode ();
1887 public override bool Equals (object obj)
1889 throw new NotSupportedException ();
1892 public void EmitAttribute (ConstructorBuilder builder)
1894 if (ResolveBuilder ())
1895 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1898 public void EmitAttribute (MethodBuilder builder)
1900 if (ResolveBuilder ())
1901 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1904 public void EmitAttribute (PropertyBuilder builder)
1906 if (ResolveBuilder ())
1907 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1910 public void EmitAttribute (FieldBuilder builder)
1912 if (ResolveBuilder ())
1913 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1916 public void EmitAttribute (TypeBuilder builder)
1918 if (ResolveBuilder ())
1919 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1922 public void EmitAttribute (AssemblyBuilder builder)
1924 if (ResolveBuilder ())
1925 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1928 public void EmitAttribute (ModuleBuilder builder)
1930 if (ResolveBuilder ())
1931 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1934 public void EmitAttribute (ParameterBuilder builder)
1936 if (ResolveBuilder ())
1937 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1940 ConstructorInfo GetCtorMetaInfo ()
1942 return (ConstructorInfo) ctor.GetMetaInfo ();
1945 public bool ResolveBuilder ()
1951 // Handle all parameter-less attributes as optional
1956 ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1957 return ctor != null;
1961 public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
1963 public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
1964 : base (module, ns, name)
1968 public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
1970 var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
1974 AttributeEncoder encoder = new AttributeEncoder ();
1975 encoder.Encode ((int) state);
1976 encoder.EncodeEmptyNamedArguments ();
1978 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1982 public class PredefinedDebuggableAttribute : PredefinedAttribute
1984 public PredefinedDebuggableAttribute (ModuleContainer module, string ns, string name)
1985 : base (module, ns, name)
1989 public void EmitAttribute (AssemblyBuilder builder, System.Diagnostics.DebuggableAttribute.DebuggingModes modes)
1991 var atype = module.PredefinedAttributes.Debuggable;
1992 if (!atype.Define ())
1995 MethodSpec ctor = null;
1996 foreach (MethodSpec m in MemberCache.FindMembers (atype.TypeSpec, CSharp.Constructor.ConstructorName, true)) {
1997 if (m.Parameters.Count != 1)
2000 if (m.Parameters.Types[0].Kind == MemberKind.Enum) {
2008 AttributeEncoder encoder = new AttributeEncoder ();
2009 encoder.Encode ((int) modes);
2010 encoder.EncodeEmptyNamedArguments ();
2012 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2016 public class PredefinedDecimalAttribute : PredefinedAttribute
2018 public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
2019 : base (module, ns, name)
2023 public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
2025 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
2029 int[] bits = decimal.GetBits (value);
2030 AttributeEncoder encoder = new AttributeEncoder ();
2031 encoder.Encode ((byte) (bits[3] >> 16));
2032 encoder.Encode ((byte) (bits[3] >> 31));
2033 encoder.Encode ((uint) bits[2]);
2034 encoder.Encode ((uint) bits[1]);
2035 encoder.Encode ((uint) bits[0]);
2036 encoder.EncodeEmptyNamedArguments ();
2038 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2041 public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
2043 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
2047 int[] bits = decimal.GetBits (value);
2048 AttributeEncoder encoder = new AttributeEncoder ();
2049 encoder.Encode ((byte) ((bits[3] & 0xFF0000) >> 16)); // Scale
2050 encoder.Encode ((byte) ((bits[3] >> 31) << 7)); // Sign encoded as 0x80 for negative, 0x0 for possitive
2051 encoder.Encode ((uint) bits[2]);
2052 encoder.Encode ((uint) bits[1]);
2053 encoder.Encode ((uint) bits[0]);
2054 encoder.EncodeEmptyNamedArguments ();
2056 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2060 public class PredefinedStateMachineAttribute : PredefinedAttribute
2062 public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
2063 : base (module, ns, name)
2067 public void EmitAttribute (MethodBuilder builder, StateMachine type)
2069 var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
2071 var ctor = predefined_ctor.Get ();
2076 AttributeEncoder encoder = new AttributeEncoder ();
2077 encoder.EncodeTypeName (type);
2078 encoder.EncodeEmptyNamedArguments ();
2080 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2084 public class PredefinedDynamicAttribute : PredefinedAttribute
2088 public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
2089 : base (module, ns, name)
2093 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
2095 if (ResolveTransformationCtor (loc)) {
2096 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2097 builder.SetCustomAttribute (cab);
2101 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
2103 if (ResolveTransformationCtor (loc)) {
2104 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2105 builder.SetCustomAttribute (cab);
2109 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
2111 if (ResolveTransformationCtor (loc)) {
2112 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2113 builder.SetCustomAttribute (cab);
2117 public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
2119 if (ResolveTransformationCtor (loc)) {
2120 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2121 builder.SetCustomAttribute (cab);
2126 // When any element of the type is a dynamic type
2128 // This method builds a transformation array for dynamic types
2129 // used in places where DynamicAttribute cannot be applied to.
2130 // It uses bool flag when type is of dynamic type and each
2131 // section always starts with "false" for some reason.
2133 // LAMESPEC: This should be part of C# specification
2135 // Example: Func<dynamic, int, dynamic[]>
2136 // Transformation: { false, true, false, false, true }
2138 static bool[] GetTransformationFlags (TypeSpec t)
2141 var ac = t as ArrayContainer;
2143 element = GetTransformationFlags (ac.Element);
2144 if (element == null)
2145 return new bool[] { false, false };
2147 bool[] res = new bool[element.Length + 1];
2149 Array.Copy (element, 0, res, 1, element.Length);
2157 List<bool> transform = null;
2158 var targs = t.TypeArguments;
2159 for (int i = 0; i < targs.Length; ++i) {
2160 element = GetTransformationFlags (targs[i]);
2161 if (element != null) {
2162 if (transform == null) {
2163 transform = new List<bool> ();
2164 for (int ii = 0; ii <= i; ++ii)
2165 transform.Add (false);
2168 transform.AddRange (element);
2169 } else if (transform != null) {
2170 transform.Add (false);
2174 if (transform != null)
2175 return transform.ToArray ();
2178 if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
2179 return new bool[] { true };
2184 bool ResolveTransformationCtor (Location loc)
2189 tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
2190 return tctor != null;
2194 public class PredefinedTupleElementNamesAttribute : PredefinedAttribute
2198 public PredefinedTupleElementNamesAttribute (ModuleContainer module, string ns, string name)
2199 : base (module, ns, name)
2203 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
2205 var cab = CreateCustomAttributeBuilder (type, loc);
2207 builder.SetCustomAttribute (cab);
2210 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
2212 var cab = CreateCustomAttributeBuilder (type, loc);
2214 builder.SetCustomAttribute (cab);
2217 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
2219 var cab = CreateCustomAttributeBuilder (type, loc);
2221 builder.SetCustomAttribute (cab);
2224 public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
2226 var cab = CreateCustomAttributeBuilder (type, loc);
2228 builder.SetCustomAttribute (cab);
2231 CustomAttributeBuilder CreateCustomAttributeBuilder (TypeSpec type, Location loc)
2233 if (tctor == null) {
2234 tctor = module.PredefinedMembers.TupleElementNamesAttributeCtor.Resolve (loc);
2239 var names = new List<string> (type.TypeArguments.Length);
2240 BuildStringElements (type, names);
2241 return new CustomAttributeBuilder ((ConstructorInfo)tctor.GetMetaInfo (), new object [] { names.ToArray () });
2245 // Returns an array of names when any element of the type is
2246 // tuple with named element. The array is built for top level
2247 // type therefore it can contain multiple tuple types
2249 // Example: Func<(int, int), int, (int a, int b)[]>
2250 // Output: { null, null, "a", "b" }
2252 static void BuildStringElements (TypeSpec type, List<string> names)
2254 while (type is ArrayContainer) {
2255 type = ((ArrayContainer)type).Element;
2258 var nts = type as NamedTupleSpec;
2260 names.AddRange (nts.Elements);
2262 for (int i = 0; i < type.Arity; ++i) {
2267 foreach (var ta in type.TypeArguments) {
2268 BuildStringElements (ta, names);