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.
14 using System.Collections.Generic;
15 using System.Runtime.InteropServices;
16 using System.Runtime.CompilerServices;
17 using System.Security;
18 using System.Security.Permissions;
23 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
24 using BadImageFormat = IKVM.Reflection.BadImageFormatException;
25 using IKVM.Reflection;
26 using IKVM.Reflection.Emit;
28 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
29 using BadImageFormat = System.BadImageFormatException;
30 using System.Reflection;
31 using System.Reflection.Emit;
34 namespace Mono.CSharp {
37 /// Base class for objects that can have Attributes applied to them.
39 public abstract class Attributable {
41 // Holds all attributes attached to this element
43 protected Attributes attributes;
45 public void AddAttributes (Attributes attrs, IMemberContext context)
50 if (attributes == null)
53 attributes.AddAttributes (attrs.Attrs);
55 attrs.AttachTo (this, context);
58 public Attributes OptAttributes {
68 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
70 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
73 /// Returns one AttributeTarget for this element.
75 public abstract AttributeTargets AttributeTargets { get; }
77 public abstract bool IsClsComplianceRequired ();
80 /// Gets list of valid attribute targets for explicit target declaration.
81 /// The first array item is default target. Don't break this rule.
83 public abstract string[] ValidAttributeTargets { get; }
86 public class Attribute : Expression
88 public readonly string ExplicitTarget;
89 public AttributeTargets Target;
90 readonly ATypeNameExpression expression;
92 Arguments PosArguments;
93 Arguments NamedArguments;
97 readonly bool nameEscaped;
100 // An attribute can be attached to multiple targets (e.g. multiple fields)
102 Attributable[] targets;
105 // A member context for the attribute, it's much easier to hold it here
106 // than trying to pull it during resolve
108 IMemberContext context;
110 public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
111 public static readonly object[] EmptyObject = new object [0];
113 List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
115 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
117 this.expression = expr;
119 PosArguments = args[0];
120 NamedArguments = args[1];
123 ExplicitTarget = target;
124 this.nameEscaped = nameEscaped;
127 void AddModuleCharSet (ResolveContext rc)
129 const string dll_import_char_set = "CharSet";
132 // Only when not customized by user
134 if (HasField (dll_import_char_set))
137 if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
141 if (NamedArguments == null)
142 NamedArguments = new Arguments (1);
144 var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
145 NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
148 public Attribute Clone ()
150 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
151 a.PosArguments = PosArguments;
152 a.NamedArguments = NamedArguments;
157 // When the same attribute is attached to multiple fiels
158 // we use @target field as a list of targets. The attribute
159 // has to be resolved only once but emitted for each target.
161 public void AttachTo (Attributable target, IMemberContext context)
163 if (this.targets == null) {
164 this.targets = new Attributable[] { target };
165 this.context = context;
169 // When re-attaching global attributes
170 if (context is NamespaceContainer) {
171 this.targets[0] = target;
172 this.context = context;
176 // Resize target array
177 Attributable[] new_array = new Attributable [this.targets.Length + 1];
178 targets.CopyTo (new_array, 0);
179 new_array [targets.Length] = target;
180 this.targets = new_array;
182 // No need to update context, different targets cannot have
183 // different contexts, it's enough to remove same attributes
184 // from secondary members.
186 target.OptAttributes = null;
189 public ResolveContext CreateResolveContext ()
191 return new ResolveContext (context, ResolveContext.Options.ConstantScope);
194 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
196 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
197 "must be fields which are not readonly, static, const or read-write properties which are " +
198 "public and not static",
202 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
204 rc.Report.Error (655, name.Location,
205 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
209 public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
211 context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
214 public void Error_MissingGuidAttribute ()
216 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
219 public void Error_MisusedExtensionAttribute ()
221 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
224 public void Error_MisusedDynamicAttribute ()
226 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
230 /// This is rather hack. We report many emit attribute error with same error to be compatible with
231 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
233 public void Error_AttributeEmitError (string inner)
235 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
236 TypeManager.CSharpName (Type), inner);
239 public void Error_InvalidSecurityParent ()
241 Error_AttributeEmitError ("it is attached to invalid parent");
251 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
253 void ResolveAttributeType ()
255 SessionReportPrinter resolve_printer = new SessionReportPrinter ();
256 ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer);
258 bool t1_is_attr = false;
259 bool t2_is_attr = false;
261 ATypeNameExpression expanded = null;
263 // TODO: Additional warnings such as CS0436 are swallowed because we don't
267 t1 = expression.ResolveAsType (context);
269 t1_is_attr = t1.IsAttribute;
271 resolve_printer.EndSession ();
276 expanded = (ATypeNameExpression) expression.Clone (null);
277 expanded.Name += "Attribute";
279 t2 = expanded.ResolveAsType (context);
281 t2_is_attr = t2.IsAttribute;
284 context.Module.Compiler.Report.SetPrinter (prev_recorder);
287 if (t1_is_attr && t2_is_attr && t1 != t2) {
288 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
289 GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
290 resolve_error = true;
304 resolve_error = true;
307 resolve_printer.Merge (prev_recorder);
309 Report.SymbolRelatedToPreviousError (t1);
310 Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
315 Report.SymbolRelatedToPreviousError (t2);
316 Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
320 resolve_printer.Merge (prev_recorder);
323 public TypeSpec ResolveType ()
325 if (Type == null && !resolve_error)
326 ResolveAttributeType ();
330 public override string GetSignatureForError ()
333 return TypeManager.CSharpName (Type);
335 return expression.GetSignatureForError ();
338 public bool HasSecurityAttribute {
340 PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
341 return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false);
345 public bool IsValidSecurityAttribute ()
347 return HasSecurityAttribute && IsSecurityActionValid ();
350 static bool IsValidArgumentType (TypeSpec t)
353 var ac = (ArrayContainer) t;
360 switch (t.BuiltinType) {
361 case BuiltinTypeSpec.Type.Int:
362 case BuiltinTypeSpec.Type.UInt:
363 case BuiltinTypeSpec.Type.Long:
364 case BuiltinTypeSpec.Type.ULong:
365 case BuiltinTypeSpec.Type.Float:
366 case BuiltinTypeSpec.Type.Double:
367 case BuiltinTypeSpec.Type.Char:
368 case BuiltinTypeSpec.Type.Short:
369 case BuiltinTypeSpec.Type.Bool:
370 case BuiltinTypeSpec.Type.SByte:
371 case BuiltinTypeSpec.Type.Byte:
372 case BuiltinTypeSpec.Type.UShort:
374 case BuiltinTypeSpec.Type.String:
375 case BuiltinTypeSpec.Type.Object:
376 case BuiltinTypeSpec.Type.Dynamic:
377 case BuiltinTypeSpec.Type.Type:
384 // TODO: Don't use this ambiguous value
386 get { return expression.Name; }
389 public Report Report {
390 get { return context.Module.Compiler.Report; }
393 public MethodSpec Resolve ()
398 resolve_error = true;
402 ResolveAttributeType ();
407 if (Type.IsAbstract) {
408 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
412 ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
413 if (obsolete_attr != null) {
414 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
417 ResolveContext rc = null;
420 // Try if the attribute is simple and has been resolved before
421 if (PosArguments != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
422 rc = CreateResolveContext ();
423 ctor = ResolveConstructor (rc);
428 if (PosArguments == null && ctor.Parameters.IsEmpty)
429 context.Module.AttributeConstructorCache.Add (Type, ctor);
433 // Add [module: DefaultCharSet] to all DllImport import attributes
435 var module = context.Module;
436 if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
438 rc = CreateResolveContext ();
440 AddModuleCharSet (rc);
443 if (NamedArguments != null) {
445 rc = CreateResolveContext ();
447 if (!ResolveNamedArguments (rc))
451 resolve_error = false;
455 MethodSpec ResolveConstructor (ResolveContext ec)
457 if (PosArguments != null) {
459 PosArguments.Resolve (ec, out dynamic);
461 Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
466 return ConstructorLookup (ec, Type, ref PosArguments, loc);
469 bool ResolveNamedArguments (ResolveContext ec)
471 int named_arg_count = NamedArguments.Count;
472 var seen_names = new List<string> (named_arg_count);
474 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
476 foreach (NamedArgument a in NamedArguments) {
477 string name = a.Name;
478 if (seen_names.Contains (name)) {
479 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
483 seen_names.Add (name);
487 Expression member = Expression.MemberLookup (ec, false, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
489 if (member == null) {
490 member = Expression.MemberLookup (ec, true, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
492 if (member != null) {
493 // TODO: ec.Report.SymbolRelatedToPreviousError (member);
494 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
500 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
504 if (!(member is PropertyExpr || member is FieldExpr)) {
505 Error_InvalidNamedArgument (ec, a);
509 ObsoleteAttribute obsolete_attr;
511 if (member is PropertyExpr) {
512 var pi = ((PropertyExpr) member).PropertyInfo;
514 if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
515 ec.Report.SymbolRelatedToPreviousError (pi);
516 Error_InvalidNamedArgument (ec, a);
520 if (!IsValidArgumentType (member.Type)) {
521 ec.Report.SymbolRelatedToPreviousError (pi);
522 Error_InvalidNamedArgumentType (ec, a);
526 obsolete_attr = pi.GetAttributeObsolete ();
527 pi.MemberDefinition.SetIsAssigned ();
529 var fi = ((FieldExpr) member).Spec;
531 if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
532 Error_InvalidNamedArgument (ec, a);
536 if (!IsValidArgumentType (member.Type)) {
537 ec.Report.SymbolRelatedToPreviousError (fi);
538 Error_InvalidNamedArgumentType (ec, a);
542 obsolete_attr = fi.GetAttributeObsolete ();
543 fi.MemberDefinition.SetIsAssigned ();
546 if (obsolete_attr != null && !context.IsObsolete)
547 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
549 if (a.Type != member.Type) {
550 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
554 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
561 /// Get a string containing a list of valid targets for the attribute 'attr'
563 public string GetValidTargets ()
565 StringBuilder sb = new StringBuilder ();
566 AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
568 if ((targets & AttributeTargets.Assembly) != 0)
569 sb.Append ("assembly, ");
571 if ((targets & AttributeTargets.Module) != 0)
572 sb.Append ("module, ");
574 if ((targets & AttributeTargets.Class) != 0)
575 sb.Append ("class, ");
577 if ((targets & AttributeTargets.Struct) != 0)
578 sb.Append ("struct, ");
580 if ((targets & AttributeTargets.Enum) != 0)
581 sb.Append ("enum, ");
583 if ((targets & AttributeTargets.Constructor) != 0)
584 sb.Append ("constructor, ");
586 if ((targets & AttributeTargets.Method) != 0)
587 sb.Append ("method, ");
589 if ((targets & AttributeTargets.Property) != 0)
590 sb.Append ("property, indexer, ");
592 if ((targets & AttributeTargets.Field) != 0)
593 sb.Append ("field, ");
595 if ((targets & AttributeTargets.Event) != 0)
596 sb.Append ("event, ");
598 if ((targets & AttributeTargets.Interface) != 0)
599 sb.Append ("interface, ");
601 if ((targets & AttributeTargets.Parameter) != 0)
602 sb.Append ("parameter, ");
604 if ((targets & AttributeTargets.Delegate) != 0)
605 sb.Append ("delegate, ");
607 if ((targets & AttributeTargets.ReturnValue) != 0)
608 sb.Append ("return, ");
610 if ((targets & AttributeTargets.GenericParameter) != 0)
611 sb.Append ("type parameter, ");
613 return sb.Remove (sb.Length - 2, 2).ToString ();
616 public AttributeUsageAttribute GetAttributeUsageAttribute ()
619 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
620 // But because a lot of attribute class code must be rewritten will be better to wait...
624 return DefaultUsageAttribute;
626 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
628 var field = GetNamedValue ("AllowMultiple") as BoolConstant;
630 usage_attribute.AllowMultiple = field.Value;
632 field = GetNamedValue ("Inherited") as BoolConstant;
634 usage_attribute.Inherited = field.Value;
636 return usage_attribute;
640 /// Returns custom name of indexer
642 public string GetIndexerAttributeValue ()
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...
649 if (resolve_error || PosArguments.Count != 1 || !(PosArguments [0].Expr is Constant))
652 return ((Constant) PosArguments [0].Expr).GetValue () as string;
656 /// Returns condition of ConditionalAttribute
658 public string GetConditionalAttributeValue ()
661 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
662 // But because a lot of attribute class code must be rewritten will be better to wait...
668 return ((Constant) PosArguments[0].Expr).GetValue () as string;
672 /// Creates the instance of ObsoleteAttribute from this attribute instance
674 public ObsoleteAttribute GetObsoleteAttribute ()
677 // corlib only case when obsolete is used before is resolved
678 var c = type.MemberDefinition as Class;
679 if (c != null && !c.HasMembersDefined)
682 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
683 // But because a lot of attribute class code must be rewritten will be better to wait...
690 if (PosArguments == null)
691 return new ObsoleteAttribute ();
693 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
694 if (PosArguments.Count == 1)
695 return new ObsoleteAttribute (msg);
697 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
701 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
702 /// before ApplyAttribute. We need to resolve the arguments.
703 /// This situation occurs when class deps is differs from Emit order.
705 public bool GetClsCompliantAttributeValue ()
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...
715 return ((BoolConstant) PosArguments[0].Expr).Value;
718 public TypeSpec GetCoClassAttributeValue ()
726 return GetArgumentType ();
729 public bool CheckTarget ()
731 string[] valid_targets = Owner.ValidAttributeTargets;
732 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
733 Target = Owner.AttributeTargets;
737 // TODO: we can skip the first item
738 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
739 switch (ExplicitTarget) {
740 case "return": Target = AttributeTargets.ReturnValue; return true;
741 case "param": Target = AttributeTargets.Parameter; return true;
742 case "field": Target = AttributeTargets.Field; return true;
743 case "method": Target = AttributeTargets.Method; return true;
744 case "property": Target = AttributeTargets.Property; return true;
745 case "module": Target = AttributeTargets.Module; return true;
747 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
750 StringBuilder sb = new StringBuilder ();
751 foreach (string s in valid_targets) {
755 sb.Remove (sb.Length - 2, 2);
756 Report.Warning (657, 1, Location,
757 "`{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",
758 ExplicitTarget, sb.ToString ());
763 /// Tests permitted SecurityAction for assembly or other types
765 bool IsSecurityActionValid ()
767 SecurityAction action = GetSecurityActionValue ();
768 bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
771 #pragma warning disable 618
772 case SecurityAction.Demand:
773 case SecurityAction.Assert:
774 case SecurityAction.Deny:
775 case SecurityAction.PermitOnly:
776 case SecurityAction.LinkDemand:
777 case SecurityAction.InheritanceDemand:
782 case SecurityAction.RequestMinimum:
783 case SecurityAction.RequestOptional:
784 case SecurityAction.RequestRefuse:
788 #pragma warning restore 618
791 Error_AttributeEmitError ("SecurityAction is out of range");
795 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
799 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
801 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
805 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
807 /// <returns></returns>
808 public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
811 object[] values = new object [PosArguments.Count];
812 for (int i = 0; i < values.Length; ++i)
813 values [i] = ((Constant) PosArguments [i].Expr).GetValue ();
816 object[] prop_values;
817 if (named_values == null) {
821 prop = new PropertyInfo[named_values.Count];
822 prop_values = new object [named_values.Count];
823 for (int i = 0; i < prop.Length; ++i) {
824 prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
825 prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
829 if (permissions == null)
830 permissions = new SecurityType ();
832 var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
833 permissions.Add (cab);
835 throw new NotSupportedException ();
839 public Constant GetNamedValue (string name)
841 if (named_values == null)
844 for (int i = 0; i < named_values.Count; ++i) {
845 if (named_values [i].Value.Name == name)
846 return named_values [i].Value.Expr as Constant;
852 public CharSet GetCharSetValue ()
854 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
857 public bool HasField (string fieldName)
859 if (named_values == null)
862 foreach (var na in named_values) {
863 if (na.Value.Name == fieldName)
871 // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
873 public bool IsInternalCall ()
875 MethodImplOptions options = 0;
876 if (PosArguments.Count == 1) {
877 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
878 } else if (HasField ("Value")) {
879 var named = GetNamedValue ("Value");
880 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
883 return (options & MethodImplOptions.InternalCall) != 0;
887 // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
889 public bool IsExplicitLayoutKind ()
891 if (PosArguments == null || PosArguments.Count != 1)
894 var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
895 return value == LayoutKind.Explicit;
898 public Expression GetParameterDefaultValue ()
900 if (PosArguments == null)
903 return PosArguments[0].Expr;
906 public override bool Equals (object obj)
908 Attribute a = obj as Attribute;
912 return Type == a.Type && Target == a.Target;
915 public override int GetHashCode ()
917 return type.GetHashCode () ^ Target.GetHashCode ();
921 /// Emit attribute for Attributable symbol
923 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
925 var ctor = Resolve ();
929 var predefined = context.Module.PredefinedAttributes;
931 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
932 if ((usage_attr.ValidOn & Target) == 0) {
933 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
934 "It is valid on `{1}' declarations only",
935 GetSignatureForError (), GetValidTargets ());
940 if (PosArguments == null && named_values == null) {
941 cdata = AttributeEncoder.Empty;
943 AttributeEncoder encoder = new AttributeEncoder ();
945 if (PosArguments != null) {
946 var param_types = ctor.Parameters.Types;
947 for (int j = 0; j < PosArguments.Count; ++j) {
948 var pt = param_types[j];
949 var arg_expr = PosArguments[j].Expr;
951 if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
952 string v = ((Constant) arg_expr).GetValue () as string;
953 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
954 context.Module.Compiler.Report.Error (633, arg_expr.Location,
955 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
958 } else if (Type == predefined.Guid) {
960 string v = ((StringConstant) arg_expr).Value;
962 } catch (Exception e) {
963 Error_AttributeEmitError (e.Message);
966 } else if (Type == predefined.AttributeUsage) {
967 int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
969 context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
970 "System.AttributeUsage");
972 } else if (Type == predefined.MarshalAs) {
973 if (PosArguments.Count == 1) {
974 var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
975 if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
976 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
979 } else if (Type == predefined.DllImport) {
980 if (PosArguments.Count == 1 && PosArguments[0].Expr is Constant) {
981 var value = ((Constant) PosArguments[0].Expr).GetValue () as string;
982 if (string.IsNullOrEmpty (value))
983 Error_AttributeEmitError ("DllName cannot be empty");
985 } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
986 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
987 Error_AttributeEmitError ("Incorrect argument value.");
992 arg_expr.EncodeAttributeValue (context, encoder, pt);
996 if (named_values != null) {
997 encoder.Encode ((ushort) named_values.Count);
998 foreach (var na in named_values) {
999 if (na.Key is FieldExpr)
1000 encoder.Encode ((byte) 0x53);
1002 encoder.Encode ((byte) 0x54);
1004 encoder.Encode (na.Key.Type);
1005 encoder.Encode (na.Value.Name);
1006 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1009 encoder.EncodeEmptyNamedArguments ();
1012 cdata = encoder.ToArray ();
1016 foreach (Attributable target in targets)
1017 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1018 } catch (Exception e) {
1019 if (e is BadImageFormat && Report.Errors > 0)
1022 Error_AttributeEmitError (e.Message);
1026 if (!usage_attr.AllowMultiple && allEmitted != null) {
1027 if (allEmitted.ContainsKey (this)) {
1028 var a = allEmitted [this];
1030 a = new List<Attribute> (2);
1031 allEmitted [this] = a;
1035 allEmitted.Add (this, null);
1039 if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1042 // Here we are testing attribute arguments for array usage (error 3016)
1043 if (Owner.IsClsComplianceRequired ()) {
1044 if (PosArguments != null)
1045 PosArguments.CheckArrayAsAttribute (context.Module.Compiler);
1047 if (NamedArguments == null)
1050 NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1054 private Expression GetValue ()
1056 if (PosArguments == null || PosArguments.Count < 1)
1059 return PosArguments [0].Expr;
1062 public string GetString ()
1064 Expression e = GetValue ();
1065 if (e is StringConstant)
1066 return ((StringConstant)e).Value;
1070 public bool GetBoolean ()
1072 Expression e = GetValue ();
1073 if (e is BoolConstant)
1074 return ((BoolConstant)e).Value;
1078 public TypeSpec GetArgumentType ()
1080 TypeOf e = GetValue () as TypeOf;
1083 return e.TypeArgument;
1086 public override Expression CreateExpressionTree (ResolveContext ec)
1088 throw new NotSupportedException ("ET");
1091 protected override Expression DoResolve (ResolveContext ec)
1093 throw new NotImplementedException ();
1096 public override void Emit (EmitContext ec)
1098 throw new NotImplementedException ();
1102 public class Attributes
1104 public readonly List<Attribute> Attrs;
1106 public Attributes (Attribute a)
1108 Attrs = new List<Attribute> ();
1112 public Attributes (List<Attribute> attrs)
1117 public void AddAttribute (Attribute attr)
1122 public void AddAttributes (List<Attribute> attrs)
1124 Attrs.AddRange (attrs);
1127 public void AttachTo (Attributable attributable, IMemberContext context)
1129 foreach (Attribute a in Attrs)
1130 a.AttachTo (attributable, context);
1133 public Attributes Clone ()
1135 var al = new List<Attribute> (Attrs.Count);
1136 foreach (Attribute a in Attrs)
1137 al.Add (a.Clone ());
1139 return new Attributes (al);
1143 /// Checks whether attribute target is valid for the current element
1145 public bool CheckTargets ()
1147 for (int i = 0; i < Attrs.Count; ++i) {
1148 if (!Attrs [i].CheckTarget ())
1149 Attrs.RemoveAt (i--);
1155 public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
1157 var member_explicit_targets = member.ValidAttributeTargets;
1158 for (int i = 0; i < Attrs.Count; ++i) {
1159 var attr = Attrs[0];
1160 if (attr.ExplicitTarget == null)
1164 for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
1165 if (attr.ExplicitTarget == member_explicit_targets[ii]) {
1171 if (ii < 0 || !isGlobal)
1174 member.Module.AddAttribute (attr, currentNamespace);
1180 public Attribute Search (PredefinedAttribute t)
1182 return Search (null, t);
1185 public Attribute Search (string explicitTarget, PredefinedAttribute t)
1187 foreach (Attribute a in Attrs) {
1188 if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1191 if (a.ResolveType () == t)
1198 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1200 public Attribute[] SearchMulti (PredefinedAttribute t)
1202 List<Attribute> ar = null;
1204 foreach (Attribute a in Attrs) {
1205 if (a.ResolveType () == t) {
1207 ar = new List<Attribute> (Attrs.Count);
1212 return ar == null ? null : ar.ToArray ();
1219 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1221 foreach (Attribute a in Attrs)
1224 if (ld == null || ld.Count == 0)
1227 foreach (var d in ld) {
1228 if (d.Value == null)
1231 Attribute a = d.Key;
1233 foreach (Attribute collision in d.Value)
1234 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1236 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1237 a.GetSignatureForError ());
1241 public bool Contains (PredefinedAttribute t)
1243 return Search (t) != null;
1247 public sealed class AttributeEncoder
1250 public enum EncodedTypeProperties
1254 TypeParameter = 1 << 1
1257 public static readonly byte[] Empty;
1261 const ushort Version = 1;
1263 static AttributeEncoder ()
1265 Empty = new byte[4];
1266 Empty[0] = (byte) Version;
1269 public AttributeEncoder ()
1271 buffer = new byte[32];
1275 public void Encode (bool value)
1277 Encode (value ? (byte) 1 : (byte) 0);
1280 public void Encode (byte value)
1282 if (pos == buffer.Length)
1285 buffer [pos++] = value;
1288 public void Encode (sbyte value)
1290 Encode ((byte) value);
1293 public void Encode (short value)
1295 if (pos + 2 > buffer.Length)
1298 buffer[pos++] = (byte) value;
1299 buffer[pos++] = (byte) (value >> 8);
1302 public void Encode (ushort value)
1304 Encode ((short) value);
1307 public void Encode (int value)
1309 if (pos + 4 > buffer.Length)
1312 buffer[pos++] = (byte) value;
1313 buffer[pos++] = (byte) (value >> 8);
1314 buffer[pos++] = (byte) (value >> 16);
1315 buffer[pos++] = (byte) (value >> 24);
1318 public void Encode (uint value)
1320 Encode ((int) value);
1323 public void Encode (long value)
1325 if (pos + 8 > 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);
1332 buffer[pos++] = (byte) (value >> 32);
1333 buffer[pos++] = (byte) (value >> 40);
1334 buffer[pos++] = (byte) (value >> 48);
1335 buffer[pos++] = (byte) (value >> 56);
1338 public void Encode (ulong value)
1340 Encode ((long) value);
1343 public void Encode (float value)
1345 Encode (SingleConverter.SingleToInt32Bits (value));
1348 public void Encode (double value)
1350 Encode (BitConverter.DoubleToInt64Bits (value));
1353 public void Encode (string value)
1355 if (value == null) {
1356 Encode ((byte) 0xFF);
1360 var buf = Encoding.UTF8.GetBytes(value);
1361 WriteCompressedValue (buf.Length);
1363 if (pos + buf.Length > buffer.Length)
1366 Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1370 public EncodedTypeProperties Encode (TypeSpec type)
1372 switch (type.BuiltinType) {
1373 case BuiltinTypeSpec.Type.Bool:
1374 Encode ((byte) 0x02);
1376 case BuiltinTypeSpec.Type.Char:
1377 Encode ((byte) 0x03);
1379 case BuiltinTypeSpec.Type.SByte:
1380 Encode ((byte) 0x04);
1382 case BuiltinTypeSpec.Type.Byte:
1383 Encode ((byte) 0x05);
1385 case BuiltinTypeSpec.Type.Short:
1386 Encode ((byte) 0x06);
1388 case BuiltinTypeSpec.Type.UShort:
1389 Encode ((byte) 0x07);
1391 case BuiltinTypeSpec.Type.Int:
1392 Encode ((byte) 0x08);
1394 case BuiltinTypeSpec.Type.UInt:
1395 Encode ((byte) 0x09);
1397 case BuiltinTypeSpec.Type.Long:
1398 Encode ((byte) 0x0A);
1400 case BuiltinTypeSpec.Type.ULong:
1401 Encode ((byte) 0x0B);
1403 case BuiltinTypeSpec.Type.Float:
1404 Encode ((byte) 0x0C);
1406 case BuiltinTypeSpec.Type.Double:
1407 Encode ((byte) 0x0D);
1409 case BuiltinTypeSpec.Type.String:
1410 Encode ((byte) 0x0E);
1412 case BuiltinTypeSpec.Type.Type:
1413 Encode ((byte) 0x50);
1415 case BuiltinTypeSpec.Type.Object:
1416 Encode ((byte) 0x51);
1418 case BuiltinTypeSpec.Type.Dynamic:
1419 Encode ((byte) 0x51);
1420 return EncodedTypeProperties.DynamicType;
1423 Encode ((byte) 0x1D);
1424 return Encode (TypeManager.GetElementType (type));
1427 if (type.Kind == MemberKind.Enum) {
1428 Encode ((byte) 0x55);
1429 EncodeTypeName (type);
1435 return EncodedTypeProperties.None;
1438 public void EncodeTypeName (TypeSpec type)
1440 var old_type = type.GetMetaInfo ();
1441 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1445 // Encodes single property named argument per call
1447 public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1449 Encode ((ushort) 1); // length
1450 Encode ((byte) 0x54); // property
1451 Encode (property.MemberType);
1452 Encode (property.Name);
1453 value.EncodeAttributeValue (null, this, property.MemberType);
1457 // Encodes single field named argument per call
1459 public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1461 Encode ((ushort) 1); // length
1462 Encode ((byte) 0x53); // field
1463 Encode (field.MemberType);
1464 Encode (field.Name);
1465 value.EncodeAttributeValue (null, this, field.MemberType);
1468 public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1470 Encode ((ushort) members.Length);
1472 for (int i = 0; i < members.Length; ++i)
1474 var member = members[i];
1476 if (member.Kind == MemberKind.Field)
1477 Encode ((byte) 0x53);
1478 else if (member.Kind == MemberKind.Property)
1479 Encode ((byte) 0x54);
1481 throw new NotImplementedException (member.Kind.ToString ());
1483 Encode (member.MemberType);
1484 Encode (member.Name);
1485 values [i].EncodeAttributeValue (null, this, member.MemberType);
1489 public void EncodeEmptyNamedArguments ()
1491 Encode ((ushort) 0);
1496 int size = System.Math.Max (pos * 4, pos + inc + 2);
1497 Array.Resize (ref buffer, size);
1500 void WriteCompressedValue (int value)
1503 Encode ((byte) value);
1507 if (value < 0x4000) {
1508 Encode ((byte) (0x80 | (value >> 8)));
1509 Encode ((byte) value);
1516 public byte[] ToArray ()
1518 byte[] buf = new byte[pos];
1519 Array.Copy (buffer, buf, pos);
1526 /// Helper class for attribute verification routine.
1528 static class AttributeTester
1530 public enum Result {
1537 /// Returns true if parameters of two compared methods are CLS-Compliant.
1538 /// It tests differing only in ref or out, or in array rank.
1540 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1542 TypeSpec [] types_a = pa.Types;
1543 TypeSpec [] types_b = pb.Types;
1544 if (types_a == null || types_b == null)
1547 if (types_a.Length != types_b.Length)
1550 Result result = Result.Ok;
1551 for (int i = 0; i < types_b.Length; ++i) {
1552 TypeSpec aType = types_a [i];
1553 TypeSpec bType = types_b [i];
1555 var ac_a = aType as ArrayContainer;
1556 var ac_b = aType as ArrayContainer;
1558 if (ac_a != null && ac_b != null) {
1559 if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1560 result = Result.RefOutArrayError;
1564 if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1565 result = Result.ArrayArrayError;
1573 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1574 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1575 result = Result.RefOutArrayError;
1581 /// Common method for Obsolete error/warning reporting.
1583 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1586 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1590 if (oa.Message == null || oa.Message.Length == 0) {
1591 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1594 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1599 // Predefined attribute types
1601 public class PredefinedAttributes
1603 // Build-in attributes
1604 public readonly PredefinedAttribute ParamArray;
1605 public readonly PredefinedAttribute Out;
1607 // Optional attributes
1608 public readonly PredefinedAttribute Obsolete;
1609 public readonly PredefinedAttribute DllImport;
1610 public readonly PredefinedAttribute MethodImpl;
1611 public readonly PredefinedAttribute MarshalAs;
1612 public readonly PredefinedAttribute In;
1613 public readonly PredefinedAttribute IndexerName;
1614 public readonly PredefinedAttribute Conditional;
1615 public readonly PredefinedAttribute CLSCompliant;
1616 public readonly PredefinedAttribute Security;
1617 public readonly PredefinedAttribute Required;
1618 public readonly PredefinedAttribute Guid;
1619 public readonly PredefinedAttribute AssemblyCulture;
1620 public readonly PredefinedAttribute AssemblyVersion;
1621 public readonly PredefinedAttribute AssemblyAlgorithmId;
1622 public readonly PredefinedAttribute AssemblyFlags;
1623 public readonly PredefinedAttribute AssemblyFileVersion;
1624 public readonly PredefinedAttribute ComImport;
1625 public readonly PredefinedAttribute CoClass;
1626 public readonly PredefinedAttribute AttributeUsage;
1627 public readonly PredefinedAttribute DefaultParameterValue;
1628 public readonly PredefinedAttribute OptionalParameter;
1629 public readonly PredefinedAttribute UnverifiableCode;
1630 public readonly PredefinedAttribute DefaultCharset;
1631 public readonly PredefinedAttribute TypeForwarder;
1632 public readonly PredefinedAttribute FixedBuffer;
1633 public readonly PredefinedAttribute CompilerGenerated;
1634 public readonly PredefinedAttribute InternalsVisibleTo;
1635 public readonly PredefinedAttribute RuntimeCompatibility;
1636 public readonly PredefinedAttribute DebuggerHidden;
1637 public readonly PredefinedAttribute UnsafeValueType;
1638 public readonly PredefinedAttribute UnmanagedFunctionPointer;
1641 public readonly PredefinedAttribute Extension;
1644 public readonly PredefinedDynamicAttribute Dynamic;
1647 // Optional types which are used as types and for member lookup
1649 public readonly PredefinedAttribute DefaultMember;
1650 public readonly PredefinedDecimalAttribute DecimalConstant;
1651 public readonly PredefinedAttribute StructLayout;
1652 public readonly PredefinedAttribute FieldOffset;
1654 public PredefinedAttributes (ModuleContainer module)
1656 ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1657 Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1658 ParamArray.Resolve ();
1661 Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1662 DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1663 MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1664 MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1665 In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1666 IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1667 Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1668 CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1669 Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1670 Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1671 Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1672 AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1673 AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1674 AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1675 AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1676 AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1677 ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1678 CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1679 AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1680 DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1681 OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1682 UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1684 DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1685 TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1686 FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1687 CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1688 InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1689 RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1690 DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1691 UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1692 UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
1694 Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1696 Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1698 DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1699 DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1700 StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1701 FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1703 // TODO: Should define only attributes which are used for comparison
1704 const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1705 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1707 foreach (var fi in GetType ().GetFields (all_fields)) {
1708 ((PredefinedAttribute) fi.GetValue (this)).Define ();
1713 public class PredefinedAttribute : PredefinedType
1715 protected MethodSpec ctor;
1717 public PredefinedAttribute (ModuleContainer module, string ns, string name)
1718 : base (module, MemberKind.Class, ns, name)
1724 public MethodSpec Constructor {
1732 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1734 return type == pa.type && pa.type != null;
1737 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1739 return type != pa.type;
1742 public override int GetHashCode ()
1744 return base.GetHashCode ();
1747 public override bool Equals (object obj)
1749 throw new NotSupportedException ();
1752 public void EmitAttribute (ConstructorBuilder builder)
1754 if (ResolveBuilder ())
1755 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1758 public void EmitAttribute (MethodBuilder builder)
1760 if (ResolveBuilder ())
1761 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1764 public void EmitAttribute (PropertyBuilder builder)
1766 if (ResolveBuilder ())
1767 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1770 public void EmitAttribute (FieldBuilder builder)
1772 if (ResolveBuilder ())
1773 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1776 public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
1778 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1781 public void EmitAttribute (TypeBuilder builder)
1783 if (ResolveBuilder ())
1784 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1787 public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
1789 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1792 public void EmitAttribute (AssemblyBuilder builder)
1794 if (ResolveBuilder ())
1795 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1798 public void EmitAttribute (ModuleBuilder builder)
1800 if (ResolveBuilder ())
1801 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1804 public void EmitAttribute (ParameterBuilder builder)
1806 if (ResolveBuilder ())
1807 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1810 public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
1812 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1815 ConstructorInfo GetCtorMetaInfo ()
1817 return (ConstructorInfo) ctor.GetMetaInfo ();
1820 public bool ResolveBuilder ()
1826 // Handle all parameter-less attributes as optional
1831 ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1832 return ctor != null;
1836 public class PredefinedDecimalAttribute : PredefinedAttribute
1838 public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1839 : base (module, ns, name)
1843 public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1845 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1849 int[] bits = decimal.GetBits (value);
1850 AttributeEncoder encoder = new AttributeEncoder ();
1851 encoder.Encode ((byte) (bits[3] >> 16));
1852 encoder.Encode ((byte) (bits[3] >> 31));
1853 encoder.Encode ((uint) bits[2]);
1854 encoder.Encode ((uint) bits[1]);
1855 encoder.Encode ((uint) bits[0]);
1856 encoder.EncodeEmptyNamedArguments ();
1858 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1861 public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1863 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1867 int[] bits = decimal.GetBits (value);
1868 AttributeEncoder encoder = new AttributeEncoder ();
1869 encoder.Encode ((byte) (bits[3] >> 16));
1870 encoder.Encode ((byte) (bits[3] >> 31));
1871 encoder.Encode ((uint) bits[2]);
1872 encoder.Encode ((uint) bits[1]);
1873 encoder.Encode ((uint) bits[0]);
1874 encoder.EncodeEmptyNamedArguments ();
1876 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1880 public class PredefinedDynamicAttribute : PredefinedAttribute
1884 public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
1885 : base (module, ns, name)
1889 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
1891 if (ResolveTransformationCtor (loc)) {
1892 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1893 builder.SetCustomAttribute (cab);
1897 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
1899 if (ResolveTransformationCtor (loc)) {
1900 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1901 builder.SetCustomAttribute (cab);
1905 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
1907 if (ResolveTransformationCtor (loc)) {
1908 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1909 builder.SetCustomAttribute (cab);
1913 public void EmitAttribute (TypeBuilder 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);
1922 // When any element of the type is a dynamic type
1924 // This method builds a transformation array for dynamic types
1925 // used in places where DynamicAttribute cannot be applied to.
1926 // It uses bool flag when type is of dynamic type and each
1927 // section always starts with "false" for some reason.
1929 // LAMESPEC: This should be part of C# specification
1931 // Example: Func<dynamic, int, dynamic[]>
1932 // Transformation: { false, true, false, false, true }
1934 static bool[] GetTransformationFlags (TypeSpec t)
1937 var ac = t as ArrayContainer;
1939 element = GetTransformationFlags (ac.Element);
1940 if (element == null)
1943 bool[] res = new bool[element.Length + 1];
1945 Array.Copy (element, 0, res, 1, element.Length);
1953 List<bool> transform = null;
1954 var targs = t.TypeArguments;
1955 for (int i = 0; i < targs.Length; ++i) {
1956 element = GetTransformationFlags (targs[i]);
1957 if (element != null) {
1958 if (transform == null) {
1959 transform = new List<bool> ();
1960 for (int ii = 0; ii <= i; ++ii)
1961 transform.Add (false);
1964 transform.AddRange (element);
1965 } else if (transform != null) {
1966 transform.Add (false);
1970 if (transform != null)
1971 return transform.ToArray ();
1974 if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1975 return new bool[] { true };
1980 bool ResolveTransformationCtor (Location loc)
1985 tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
1986 return tctor != null;