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 IKVM.Reflection;
25 using IKVM.Reflection.Emit;
27 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
28 using System.Reflection;
29 using System.Reflection.Emit;
32 namespace Mono.CSharp {
35 /// Base class for objects that can have Attributes applied to them.
37 public abstract class Attributable {
39 // Holds all attributes attached to this element
41 protected Attributes attributes;
43 public void AddAttributes (Attributes attrs, IMemberContext context)
48 if (attributes == null)
51 throw new NotImplementedException ();
53 attributes.AttachTo (this, context);
56 public Attributes OptAttributes {
66 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
68 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
71 /// Returns one AttributeTarget for this element.
73 public abstract AttributeTargets AttributeTargets { get; }
75 public abstract bool IsClsComplianceRequired ();
78 /// Gets list of valid attribute targets for explicit target declaration.
79 /// The first array item is default target. Don't break this rule.
81 public abstract string[] ValidAttributeTargets { get; }
84 public class Attribute : Expression
86 public readonly string ExplicitTarget;
87 public AttributeTargets Target;
88 readonly ATypeNameExpression expression;
90 Arguments PosArguments;
91 Arguments NamedArguments;
95 readonly bool nameEscaped;
98 // An attribute can be attached to multiple targets (e.g. multiple fields)
100 protected Attributable[] targets;
103 // A member context for the attribute, it's much easier to hold it here
104 // than trying to pull it during resolve
106 IMemberContext context;
108 public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
109 public static readonly object[] EmptyObject = new object [0];
111 List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
113 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
115 this.expression = expr;
117 PosArguments = args [0];
118 NamedArguments = args [1];
121 ExplicitTarget = target;
122 this.nameEscaped = nameEscaped;
125 void AddModuleCharSet (ResolveContext rc)
127 const string dll_import_char_set = "CharSet";
130 // Only when not customized by user
132 if (HasField (dll_import_char_set))
135 if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
139 if (NamedArguments == null)
140 NamedArguments = new Arguments (1);
142 var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
143 NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
146 public Attribute Clone ()
148 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
149 a.PosArguments = PosArguments;
150 a.NamedArguments = NamedArguments;
155 // When the same attribute is attached to multiple fiels
156 // we use @target field as a list of targets. The attribute
157 // has to be resolved only once but emitted for each target.
159 public void AttachTo (Attributable target, IMemberContext context)
161 if (this.targets == null) {
162 this.targets = new Attributable[] { target };
163 this.context = context;
167 // Resize target array
168 Attributable[] new_array = new Attributable [this.targets.Length + 1];
169 targets.CopyTo (new_array, 0);
170 new_array [targets.Length] = target;
171 this.targets = new_array;
173 // No need to update context, different targets cannot have
174 // different contexts, it's enough to remove same attributes
175 // from secondary members.
177 target.OptAttributes = null;
180 public ResolveContext CreateResolveContext ()
182 return new ResolveContext (context, ResolveContext.Options.ConstantScope);
185 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
187 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
188 "must be fields which are not readonly, static, const or read-write properties which are " +
189 "public and not static",
193 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
195 rc.Report.Error (655, name.Location,
196 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
200 public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
202 context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
205 public void Error_MissingGuidAttribute ()
207 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
210 public void Error_MisusedExtensionAttribute ()
212 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
215 public void Error_MisusedDynamicAttribute ()
217 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
221 /// This is rather hack. We report many emit attribute error with same error to be compatible with
222 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
224 public void Error_AttributeEmitError (string inner)
226 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
227 TypeManager.CSharpName (Type), inner);
230 public void Error_InvalidSecurityParent ()
232 Error_AttributeEmitError ("it is attached to invalid parent");
241 TypeSpec ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
243 TypeExpr te = expr.ResolveAsTypeTerminal (context, false);
247 TypeSpec t = te.Type;
251 Report.SymbolRelatedToPreviousError (t);
252 Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
258 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
260 void ResolveAttributeType ()
262 SessionReportPrinter resolve_printer = new SessionReportPrinter ();
263 ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer);
265 bool t1_is_attr = false;
266 bool t2_is_attr = false;
268 ATypeNameExpression expanded = null;
271 t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
276 expanded = (ATypeNameExpression) expression.Clone (null);
277 expanded.Name += "Attribute";
279 t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
282 resolve_printer.EndSession ();
284 context.Module.Compiler.Report.SetPrinter (prev_recorder);
287 if (t1_is_attr && t2_is_attr) {
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_printer.Merge (prev_recorder);
305 resolve_error = true;
308 public TypeSpec ResolveType ()
310 if (Type == null && !resolve_error)
311 ResolveAttributeType ();
315 public override string GetSignatureForError ()
318 return TypeManager.CSharpName (Type);
320 return expression.GetSignatureForError ();
323 public bool HasSecurityAttribute {
325 PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
326 return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false);
330 public bool IsValidSecurityAttribute ()
332 return HasSecurityAttribute && IsSecurityActionValid (false);
335 static bool IsValidArgumentType (TypeSpec t)
338 var ac = (ArrayContainer) t;
345 switch (t.BuiltinType) {
346 case BuiltinTypeSpec.Type.Int:
347 case BuiltinTypeSpec.Type.UInt:
348 case BuiltinTypeSpec.Type.Long:
349 case BuiltinTypeSpec.Type.ULong:
350 case BuiltinTypeSpec.Type.Float:
351 case BuiltinTypeSpec.Type.Double:
352 case BuiltinTypeSpec.Type.Char:
353 case BuiltinTypeSpec.Type.Short:
354 case BuiltinTypeSpec.Type.Bool:
355 case BuiltinTypeSpec.Type.SByte:
356 case BuiltinTypeSpec.Type.Byte:
357 case BuiltinTypeSpec.Type.UShort:
359 case BuiltinTypeSpec.Type.String:
360 case BuiltinTypeSpec.Type.Object:
361 case BuiltinTypeSpec.Type.Dynamic:
362 case BuiltinTypeSpec.Type.Type:
369 // TODO: Don't use this ambiguous value
371 get { return expression.Name; }
374 public Report Report {
375 get { return context.Module.Compiler.Report; }
378 public MethodSpec Resolve ()
383 resolve_error = true;
387 ResolveAttributeType ();
392 if (Type.IsAbstract) {
393 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
397 ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
398 if (obsolete_attr != null) {
399 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
402 ResolveContext rc = null;
405 // Try if the attribute is simple and has been resolved before
406 if (PosArguments != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
407 rc = CreateResolveContext ();
408 ctor = ResolveConstructor (rc);
413 if (PosArguments == null && ctor.Parameters.IsEmpty)
414 context.Module.AttributeConstructorCache.Add (Type, ctor);
418 // Add [module: DefaultCharSet] to all DllImport import attributes
420 var module = context.Module;
421 if (Type == module.PredefinedAttributes.DllImport && module.HasDefaultCharSet) {
423 rc = CreateResolveContext ();
425 AddModuleCharSet (rc);
428 if (NamedArguments != null) {
430 rc = CreateResolveContext ();
432 if (!ResolveNamedArguments (rc))
436 resolve_error = false;
440 MethodSpec ResolveConstructor (ResolveContext ec)
442 if (PosArguments != null) {
444 PosArguments.Resolve (ec, out dynamic);
446 Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
451 return ConstructorLookup (ec, Type, ref PosArguments, loc);
454 bool ResolveNamedArguments (ResolveContext ec)
456 int named_arg_count = NamedArguments.Count;
457 var seen_names = new List<string> (named_arg_count);
459 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
461 foreach (NamedArgument a in NamedArguments) {
462 string name = a.Name;
463 if (seen_names.Contains (name)) {
464 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
468 seen_names.Add (name);
472 Expression member = Expression.MemberLookup (ec, false, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
474 if (member == null) {
475 member = Expression.MemberLookup (ec, true, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
477 if (member != null) {
478 // TODO: ec.Report.SymbolRelatedToPreviousError (member);
479 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
485 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
489 if (!(member is PropertyExpr || member is FieldExpr)) {
490 Error_InvalidNamedArgument (ec, a);
494 ObsoleteAttribute obsolete_attr;
496 if (member is PropertyExpr) {
497 var pi = ((PropertyExpr) member).PropertyInfo;
499 if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
500 ec.Report.SymbolRelatedToPreviousError (pi);
501 Error_InvalidNamedArgument (ec, a);
505 if (!IsValidArgumentType (member.Type)) {
506 ec.Report.SymbolRelatedToPreviousError (pi);
507 Error_InvalidNamedArgumentType (ec, a);
511 obsolete_attr = pi.GetAttributeObsolete ();
512 pi.MemberDefinition.SetIsAssigned ();
514 var fi = ((FieldExpr) member).Spec;
516 if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
517 Error_InvalidNamedArgument (ec, a);
521 if (!IsValidArgumentType (member.Type)) {
522 ec.Report.SymbolRelatedToPreviousError (fi);
523 Error_InvalidNamedArgumentType (ec, a);
527 obsolete_attr = fi.GetAttributeObsolete ();
528 fi.MemberDefinition.SetIsAssigned ();
531 if (obsolete_attr != null && !context.IsObsolete)
532 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
534 if (a.Type != member.Type) {
535 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
539 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
546 /// Get a string containing a list of valid targets for the attribute 'attr'
548 public string GetValidTargets ()
550 StringBuilder sb = new StringBuilder ();
551 AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
553 if ((targets & AttributeTargets.Assembly) != 0)
554 sb.Append ("assembly, ");
556 if ((targets & AttributeTargets.Module) != 0)
557 sb.Append ("module, ");
559 if ((targets & AttributeTargets.Class) != 0)
560 sb.Append ("class, ");
562 if ((targets & AttributeTargets.Struct) != 0)
563 sb.Append ("struct, ");
565 if ((targets & AttributeTargets.Enum) != 0)
566 sb.Append ("enum, ");
568 if ((targets & AttributeTargets.Constructor) != 0)
569 sb.Append ("constructor, ");
571 if ((targets & AttributeTargets.Method) != 0)
572 sb.Append ("method, ");
574 if ((targets & AttributeTargets.Property) != 0)
575 sb.Append ("property, indexer, ");
577 if ((targets & AttributeTargets.Field) != 0)
578 sb.Append ("field, ");
580 if ((targets & AttributeTargets.Event) != 0)
581 sb.Append ("event, ");
583 if ((targets & AttributeTargets.Interface) != 0)
584 sb.Append ("interface, ");
586 if ((targets & AttributeTargets.Parameter) != 0)
587 sb.Append ("parameter, ");
589 if ((targets & AttributeTargets.Delegate) != 0)
590 sb.Append ("delegate, ");
592 if ((targets & AttributeTargets.ReturnValue) != 0)
593 sb.Append ("return, ");
595 if ((targets & AttributeTargets.GenericParameter) != 0)
596 sb.Append ("type parameter, ");
598 return sb.Remove (sb.Length - 2, 2).ToString ();
601 public AttributeUsageAttribute GetAttributeUsageAttribute ()
604 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
605 // But because a lot of attribute class code must be rewritten will be better to wait...
609 return DefaultUsageAttribute;
611 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
613 var field = GetNamedValue ("AllowMultiple") as BoolConstant;
615 usage_attribute.AllowMultiple = field.Value;
617 field = GetNamedValue ("Inherited") as BoolConstant;
619 usage_attribute.Inherited = field.Value;
621 return usage_attribute;
625 /// Returns custom name of indexer
627 public string GetIndexerAttributeValue ()
630 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
631 // But because a lot of attribute class code must be rewritten will be better to wait...
637 return ((Constant) PosArguments [0].Expr).GetValue () as string;
641 /// Returns condition of ConditionalAttribute
643 public string GetConditionalAttributeValue ()
646 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
647 // But because a lot of attribute class code must be rewritten will be better to wait...
653 return ((Constant) PosArguments[0].Expr).GetValue () as string;
657 /// Creates the instance of ObsoleteAttribute from this attribute instance
659 public ObsoleteAttribute GetObsoleteAttribute ()
662 // corlib only case when obsolete is used before is resolved
663 var c = type.MemberDefinition as Class;
664 if (c != null && !c.HasMembersDefined)
667 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
668 // But because a lot of attribute class code must be rewritten will be better to wait...
675 if (PosArguments == null)
676 return new ObsoleteAttribute ();
678 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
679 if (PosArguments.Count == 1)
680 return new ObsoleteAttribute (msg);
682 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
686 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
687 /// before ApplyAttribute. We need to resolve the arguments.
688 /// This situation occurs when class deps is differs from Emit order.
690 public bool GetClsCompliantAttributeValue ()
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...
700 return ((BoolConstant) PosArguments[0].Expr).Value;
703 public TypeSpec GetCoClassAttributeValue ()
711 return GetArgumentType ();
714 public bool CheckTarget ()
716 string[] valid_targets = Owner.ValidAttributeTargets;
717 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
718 Target = Owner.AttributeTargets;
722 // TODO: we can skip the first item
723 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
724 switch (ExplicitTarget) {
725 case "return": Target = AttributeTargets.ReturnValue; return true;
726 case "param": Target = AttributeTargets.Parameter; return true;
727 case "field": Target = AttributeTargets.Field; return true;
728 case "method": Target = AttributeTargets.Method; return true;
729 case "property": Target = AttributeTargets.Property; return true;
730 case "module": Target = AttributeTargets.Module; return true;
732 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
735 StringBuilder sb = new StringBuilder ();
736 foreach (string s in valid_targets) {
740 sb.Remove (sb.Length - 2, 2);
741 Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
742 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
747 /// Tests permitted SecurityAction for assembly or other types
749 protected virtual bool IsSecurityActionValid (bool for_assembly)
751 SecurityAction action = GetSecurityActionValue ();
754 #pragma warning disable 618
755 case SecurityAction.Demand:
756 case SecurityAction.Assert:
757 case SecurityAction.Deny:
758 case SecurityAction.PermitOnly:
759 case SecurityAction.LinkDemand:
760 case SecurityAction.InheritanceDemand:
765 case SecurityAction.RequestMinimum:
766 case SecurityAction.RequestOptional:
767 case SecurityAction.RequestRefuse:
771 #pragma warning restore 618
774 Error_AttributeEmitError ("SecurityAction is out of range");
778 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
782 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
784 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
788 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
790 /// <returns></returns>
791 public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
794 object[] values = new object [PosArguments.Count];
795 for (int i = 0; i < values.Length; ++i)
796 values [i] = ((Constant) PosArguments [i].Expr).GetValue ();
799 object[] prop_values;
800 if (named_values == null) {
804 prop = new PropertyInfo[named_values.Count];
805 prop_values = new object [named_values.Count];
806 for (int i = 0; i < prop.Length; ++i) {
807 prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
808 prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
812 if (permissions == null)
813 permissions = new SecurityType ();
815 var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
816 permissions.Add (cab);
818 throw new NotSupportedException ();
822 public Constant GetNamedValue (string name)
824 if (named_values == null)
827 for (int i = 0; i < named_values.Count; ++i) {
828 if (named_values [i].Value.Name == name)
829 return named_values [i].Value.Expr as Constant;
835 public CharSet GetCharSetValue ()
837 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
840 public bool HasField (string fieldName)
842 if (named_values == null)
845 foreach (var na in named_values) {
846 if (na.Value.Name == fieldName)
854 // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
856 public bool IsInternalCall ()
858 MethodImplOptions options = 0;
859 if (PosArguments.Count == 1) {
860 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
861 } else if (HasField ("Value")) {
862 var named = GetNamedValue ("Value");
863 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
866 return (options & MethodImplOptions.InternalCall) != 0;
870 // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
872 public bool IsExplicitLayoutKind ()
874 if (PosArguments == null || PosArguments.Count != 1)
877 var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
878 return value == LayoutKind.Explicit;
881 public Expression GetParameterDefaultValue ()
883 if (PosArguments == null)
886 return PosArguments[0].Expr;
889 public override bool Equals (object obj)
891 Attribute a = obj as Attribute;
895 return Type == a.Type && Target == a.Target;
898 public override int GetHashCode ()
900 return type.GetHashCode () ^ Target.GetHashCode ();
904 /// Emit attribute for Attributable symbol
906 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
908 var ctor = Resolve ();
912 var predefined = context.Module.PredefinedAttributes;
914 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
915 if ((usage_attr.ValidOn & Target) == 0) {
916 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
917 "It is valid on `{1}' declarations only",
918 GetSignatureForError (), GetValidTargets ());
923 if (PosArguments == null && named_values == null) {
924 cdata = AttributeEncoder.Empty;
926 AttributeEncoder encoder = new AttributeEncoder ();
928 if (PosArguments != null) {
929 var param_types = ctor.Parameters.Types;
930 for (int j = 0; j < PosArguments.Count; ++j) {
931 var pt = param_types[j];
932 var arg_expr = PosArguments[j].Expr;
934 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
935 string v = ((StringConstant) arg_expr).Value;
936 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
937 context.Module.Compiler.Report.Error (633, arg_expr.Location,
938 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
940 } else if (Type == predefined.Guid) {
942 string v = ((StringConstant) arg_expr).Value;
944 } catch (Exception e) {
945 Error_AttributeEmitError (e.Message);
948 } else if (Type == predefined.AttributeUsage) {
949 int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
951 context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
952 "System.AttributeUsage");
954 } else if (Type == predefined.MarshalAs) {
955 if (PosArguments.Count == 1) {
956 var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
957 if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
958 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
961 } else if (Type == predefined.DllImport) {
962 if (PosArguments.Count == 1) {
963 var value = ((Constant) PosArguments[0].Expr).GetValue () as string;
964 if (string.IsNullOrEmpty (value))
965 Error_AttributeEmitError ("DllName cannot be empty");
967 } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
968 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
969 Error_AttributeEmitError ("Incorrect argument value.");
974 arg_expr.EncodeAttributeValue (context, encoder, pt);
978 if (named_values != null) {
979 encoder.Encode ((ushort) named_values.Count);
980 foreach (var na in named_values) {
981 if (na.Key is FieldExpr)
982 encoder.Encode ((byte) 0x53);
984 encoder.Encode ((byte) 0x54);
986 encoder.Encode (na.Key.Type);
987 encoder.Encode (na.Value.Name);
988 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
991 encoder.EncodeEmptyNamedArguments ();
994 cdata = encoder.ToArray ();
998 foreach (Attributable target in targets)
999 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1000 } catch (Exception e) {
1001 Error_AttributeEmitError (e.Message);
1005 if (!usage_attr.AllowMultiple && allEmitted != null) {
1006 if (allEmitted.ContainsKey (this)) {
1007 var a = allEmitted [this];
1009 a = new List<Attribute> (2);
1010 allEmitted [this] = a;
1014 allEmitted.Add (this, null);
1018 if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1021 // Here we are testing attribute arguments for array usage (error 3016)
1022 if (Owner.IsClsComplianceRequired ()) {
1023 if (PosArguments != null)
1024 PosArguments.CheckArrayAsAttribute (context.Module.Compiler);
1026 if (NamedArguments == null)
1029 NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1033 private Expression GetValue ()
1035 if (PosArguments == null || PosArguments.Count < 1)
1038 return PosArguments [0].Expr;
1041 public string GetString ()
1043 Expression e = GetValue ();
1044 if (e is StringConstant)
1045 return ((StringConstant)e).Value;
1049 public bool GetBoolean ()
1051 Expression e = GetValue ();
1052 if (e is BoolConstant)
1053 return ((BoolConstant)e).Value;
1057 public TypeSpec GetArgumentType ()
1059 TypeOf e = GetValue () as TypeOf;
1062 return e.TypeArgument;
1065 public override Expression CreateExpressionTree (ResolveContext ec)
1067 throw new NotSupportedException ("ET");
1070 protected override Expression DoResolve (ResolveContext ec)
1072 throw new NotImplementedException ();
1075 public override void Emit (EmitContext ec)
1077 throw new NotImplementedException ();
1083 /// For global attributes (assembly, module) we need special handling.
1084 /// Attributes can be located in the several files
1086 public class GlobalAttribute : Attribute
1088 public GlobalAttribute (string target, ATypeNameExpression expression, Arguments[] args, Location loc, bool nameEscaped)
1089 : base (target, expression, args, loc, nameEscaped)
1093 protected override bool IsSecurityActionValid (bool for_assembly)
1095 return base.IsSecurityActionValid (true);
1099 public class Attributes {
1100 public readonly List<Attribute> Attrs;
1102 public Attributes (Attribute a)
1104 Attrs = new List<Attribute> ();
1108 public Attributes (List<Attribute> attrs)
1113 public void AddAttributes (List<Attribute> attrs)
1115 Attrs.AddRange (attrs);
1118 public void AttachTo (Attributable attributable, IMemberContext context)
1120 foreach (Attribute a in Attrs)
1121 a.AttachTo (attributable, context);
1124 public Attributes Clone ()
1126 var al = new List<Attribute> (Attrs.Count);
1127 foreach (Attribute a in Attrs)
1128 al.Add (a.Clone ());
1130 return new Attributes (al);
1134 /// Checks whether attribute target is valid for the current element
1136 public bool CheckTargets ()
1138 foreach (Attribute a in Attrs) {
1139 if (!a.CheckTarget ())
1145 public Attribute Search (PredefinedAttribute t)
1147 return Search (null, t);
1150 public Attribute Search (string explicitTarget, PredefinedAttribute t)
1152 foreach (Attribute a in Attrs) {
1153 if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1156 if (a.ResolveType () == t)
1163 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1165 public Attribute[] SearchMulti (PredefinedAttribute t)
1167 List<Attribute> ar = null;
1169 foreach (Attribute a in Attrs) {
1170 if (a.ResolveType () == t) {
1172 ar = new List<Attribute> (Attrs.Count);
1177 return ar == null ? null : ar.ToArray ();
1184 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1186 foreach (Attribute a in Attrs)
1189 if (ld == null || ld.Count == 0)
1192 foreach (var d in ld) {
1193 if (d.Value == null)
1196 Attribute a = d.Key;
1198 foreach (Attribute collision in d.Value)
1199 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1201 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1202 a.GetSignatureForError ());
1206 public bool Contains (PredefinedAttribute t)
1208 return Search (t) != null;
1212 public sealed class AttributeEncoder
1215 public enum EncodedTypeProperties
1219 TypeParameter = 1 << 1
1222 public static readonly byte[] Empty;
1226 const ushort Version = 1;
1228 static AttributeEncoder ()
1230 Empty = new byte[4];
1231 Empty[0] = (byte) Version;
1234 public AttributeEncoder ()
1236 buffer = new byte[32];
1240 public void Encode (bool value)
1242 Encode (value ? (byte) 1 : (byte) 0);
1245 public void Encode (byte value)
1247 if (pos == buffer.Length)
1250 buffer [pos++] = value;
1253 public void Encode (sbyte value)
1255 Encode ((byte) value);
1258 public void Encode (short value)
1260 if (pos + 2 > buffer.Length)
1263 buffer[pos++] = (byte) value;
1264 buffer[pos++] = (byte) (value >> 8);
1267 public void Encode (ushort value)
1269 Encode ((short) value);
1272 public void Encode (int value)
1274 if (pos + 4 > buffer.Length)
1277 buffer[pos++] = (byte) value;
1278 buffer[pos++] = (byte) (value >> 8);
1279 buffer[pos++] = (byte) (value >> 16);
1280 buffer[pos++] = (byte) (value >> 24);
1283 public void Encode (uint value)
1285 Encode ((int) value);
1288 public void Encode (long value)
1290 if (pos + 8 > buffer.Length)
1293 buffer[pos++] = (byte) value;
1294 buffer[pos++] = (byte) (value >> 8);
1295 buffer[pos++] = (byte) (value >> 16);
1296 buffer[pos++] = (byte) (value >> 24);
1297 buffer[pos++] = (byte) (value >> 32);
1298 buffer[pos++] = (byte) (value >> 40);
1299 buffer[pos++] = (byte) (value >> 48);
1300 buffer[pos++] = (byte) (value >> 56);
1303 public void Encode (ulong value)
1305 Encode ((long) value);
1308 public void Encode (float value)
1310 Encode (SingleConverter.SingleToInt32Bits (value));
1313 public void Encode (double value)
1315 Encode (BitConverter.DoubleToInt64Bits (value));
1318 public void Encode (string value)
1320 if (value == null) {
1321 Encode ((byte) 0xFF);
1325 var buf = Encoding.UTF8.GetBytes(value);
1326 WriteCompressedValue (buf.Length);
1328 if (pos + buf.Length > buffer.Length)
1331 Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1335 public EncodedTypeProperties Encode (TypeSpec type)
1337 switch (type.BuiltinType) {
1338 case BuiltinTypeSpec.Type.Bool:
1339 Encode ((byte) 0x02);
1341 case BuiltinTypeSpec.Type.Char:
1342 Encode ((byte) 0x03);
1344 case BuiltinTypeSpec.Type.SByte:
1345 Encode ((byte) 0x04);
1347 case BuiltinTypeSpec.Type.Byte:
1348 Encode ((byte) 0x05);
1350 case BuiltinTypeSpec.Type.Short:
1351 Encode ((byte) 0x06);
1353 case BuiltinTypeSpec.Type.UShort:
1354 Encode ((byte) 0x07);
1356 case BuiltinTypeSpec.Type.Int:
1357 Encode ((byte) 0x08);
1359 case BuiltinTypeSpec.Type.UInt:
1360 Encode ((byte) 0x09);
1362 case BuiltinTypeSpec.Type.Long:
1363 Encode ((byte) 0x0A);
1365 case BuiltinTypeSpec.Type.ULong:
1366 Encode ((byte) 0x0B);
1368 case BuiltinTypeSpec.Type.Float:
1369 Encode ((byte) 0x0C);
1371 case BuiltinTypeSpec.Type.Double:
1372 Encode ((byte) 0x0D);
1374 case BuiltinTypeSpec.Type.String:
1375 Encode ((byte) 0x0E);
1377 case BuiltinTypeSpec.Type.Type:
1378 Encode ((byte) 0x50);
1380 case BuiltinTypeSpec.Type.Object:
1381 Encode ((byte) 0x51);
1383 case BuiltinTypeSpec.Type.Dynamic:
1384 Encode ((byte) 0x51);
1385 return EncodedTypeProperties.DynamicType;
1388 Encode ((byte) 0x1D);
1389 return Encode (TypeManager.GetElementType (type));
1392 if (type.Kind == MemberKind.Enum) {
1393 Encode ((byte) 0x55);
1394 EncodeTypeName (type);
1400 return EncodedTypeProperties.None;
1403 public void EncodeTypeName (TypeSpec type)
1405 var old_type = type.GetMetaInfo ();
1406 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1410 // Encodes single property named argument per call
1412 public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1414 Encode ((ushort) 1); // length
1415 Encode ((byte) 0x54); // property
1416 Encode (property.MemberType);
1417 Encode (property.Name);
1418 value.EncodeAttributeValue (null, this, property.MemberType);
1422 // Encodes single field named argument per call
1424 public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1426 Encode ((ushort) 1); // length
1427 Encode ((byte) 0x53); // field
1428 Encode (field.MemberType);
1429 Encode (field.Name);
1430 value.EncodeAttributeValue (null, this, field.MemberType);
1433 public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1435 Encode ((ushort) members.Length);
1437 for (int i = 0; i < members.Length; ++i)
1439 var member = members[i];
1441 if (member.Kind == MemberKind.Field)
1442 Encode ((byte) 0x53);
1443 else if (member.Kind == MemberKind.Property)
1444 Encode ((byte) 0x54);
1446 throw new NotImplementedException (member.Kind.ToString ());
1448 Encode (member.MemberType);
1449 Encode (member.Name);
1450 values [i].EncodeAttributeValue (null, this, member.MemberType);
1454 public void EncodeEmptyNamedArguments ()
1456 Encode ((ushort) 0);
1461 int size = System.Math.Max (pos * 4, pos + inc + 2);
1462 Array.Resize (ref buffer, size);
1465 void WriteCompressedValue (int value)
1468 Encode ((byte) value);
1472 if (value < 0x4000) {
1473 Encode ((byte) (0x80 | (value >> 8)));
1474 Encode ((byte) value);
1481 public byte[] ToArray ()
1483 byte[] buf = new byte[pos];
1484 Array.Copy (buffer, buf, pos);
1491 /// Helper class for attribute verification routine.
1493 static class AttributeTester
1495 public enum Result {
1502 /// Returns true if parameters of two compared methods are CLS-Compliant.
1503 /// It tests differing only in ref or out, or in array rank.
1505 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1507 TypeSpec [] types_a = pa.Types;
1508 TypeSpec [] types_b = pb.Types;
1509 if (types_a == null || types_b == null)
1512 if (types_a.Length != types_b.Length)
1515 Result result = Result.Ok;
1516 for (int i = 0; i < types_b.Length; ++i) {
1517 TypeSpec aType = types_a [i];
1518 TypeSpec bType = types_b [i];
1520 var ac_a = aType as ArrayContainer;
1521 var ac_b = aType as ArrayContainer;
1523 if (ac_a != null && ac_b != null) {
1524 if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1525 result = Result.RefOutArrayError;
1529 if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1530 result = Result.ArrayArrayError;
1538 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1539 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1540 result = Result.RefOutArrayError;
1546 /// Common method for Obsolete error/warning reporting.
1548 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1551 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1555 if (oa.Message == null || oa.Message.Length == 0) {
1556 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1559 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1564 // Predefined attribute types
1566 public class PredefinedAttributes
1568 // Build-in attributes
1569 public readonly PredefinedAttribute ParamArray;
1570 public readonly PredefinedAttribute Out;
1572 // Optional attributes
1573 public readonly PredefinedAttribute Obsolete;
1574 public readonly PredefinedAttribute DllImport;
1575 public readonly PredefinedAttribute MethodImpl;
1576 public readonly PredefinedAttribute MarshalAs;
1577 public readonly PredefinedAttribute In;
1578 public readonly PredefinedAttribute IndexerName;
1579 public readonly PredefinedAttribute Conditional;
1580 public readonly PredefinedAttribute CLSCompliant;
1581 public readonly PredefinedAttribute Security;
1582 public readonly PredefinedAttribute Required;
1583 public readonly PredefinedAttribute Guid;
1584 public readonly PredefinedAttribute AssemblyCulture;
1585 public readonly PredefinedAttribute AssemblyVersion;
1586 public readonly PredefinedAttribute AssemblyAlgorithmId;
1587 public readonly PredefinedAttribute AssemblyFlags;
1588 public readonly PredefinedAttribute AssemblyFileVersion;
1589 public readonly PredefinedAttribute ComImport;
1590 public readonly PredefinedAttribute CoClass;
1591 public readonly PredefinedAttribute AttributeUsage;
1592 public readonly PredefinedAttribute DefaultParameterValue;
1593 public readonly PredefinedAttribute OptionalParameter;
1594 public readonly PredefinedAttribute UnverifiableCode;
1597 public readonly PredefinedAttribute DefaultCharset;
1598 public readonly PredefinedAttribute TypeForwarder;
1599 public readonly PredefinedAttribute FixedBuffer;
1600 public readonly PredefinedAttribute CompilerGenerated;
1601 public readonly PredefinedAttribute InternalsVisibleTo;
1602 public readonly PredefinedAttribute RuntimeCompatibility;
1603 public readonly PredefinedAttribute DebuggerHidden;
1604 public readonly PredefinedAttribute UnsafeValueType;
1607 public readonly PredefinedAttribute Extension;
1610 public readonly PredefinedDynamicAttribute Dynamic;
1613 // Optional types which are used as types and for member lookup
1615 public readonly PredefinedAttribute DefaultMember;
1616 public readonly PredefinedDecimalAttribute DecimalConstant;
1617 public readonly PredefinedAttribute StructLayout;
1618 public readonly PredefinedAttribute FieldOffset;
1620 public PredefinedAttributes (ModuleContainer module)
1622 ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1623 Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1624 ParamArray.Resolve (Location.Null);
1625 Out.Resolve (Location.Null);
1627 Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1628 DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1629 MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1630 MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1631 In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1632 IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1633 Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1634 CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1635 Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1636 Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1637 Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1638 AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1639 AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1640 AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1641 AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1642 AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1643 ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1644 CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1645 AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1646 DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1647 OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1648 UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1650 DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1651 TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1652 FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1653 CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1654 InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1655 RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1656 DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1657 UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1659 Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1661 Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1663 DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1664 DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1665 StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1666 FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1668 // TODO: Should define only attributes which are used for comparison
1669 const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1670 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1672 foreach (var fi in GetType ().GetFields (all_fields)) {
1673 ((PredefinedAttribute) fi.GetValue (this)).Define ();
1678 public class PredefinedAttribute : PredefinedType
1680 protected MethodSpec ctor;
1682 public PredefinedAttribute (ModuleContainer module, string ns, string name)
1683 : base (module, MemberKind.Class, ns, name)
1689 public MethodSpec Constructor {
1697 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1699 return type == pa.type && pa.type != null;
1702 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1704 return type != pa.type;
1707 public override int GetHashCode ()
1709 return base.GetHashCode ();
1712 public override bool Equals (object obj)
1714 throw new NotSupportedException ();
1717 public void EmitAttribute (ConstructorBuilder builder)
1719 if (ResolveBuilder ())
1720 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1723 public void EmitAttribute (MethodBuilder builder)
1725 if (ResolveBuilder ())
1726 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1729 public void EmitAttribute (PropertyBuilder builder)
1731 if (ResolveBuilder ())
1732 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1735 public void EmitAttribute (FieldBuilder builder)
1737 if (ResolveBuilder ())
1738 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1741 public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
1743 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1746 public void EmitAttribute (TypeBuilder builder)
1748 if (ResolveBuilder ())
1749 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1752 public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
1754 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1757 public void EmitAttribute (AssemblyBuilder builder)
1759 if (ResolveBuilder ())
1760 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1763 public void EmitAttribute (ModuleBuilder builder)
1765 if (ResolveBuilder ())
1766 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1769 public void EmitAttribute (ParameterBuilder builder)
1771 if (ResolveBuilder ())
1772 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1775 public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
1777 builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1780 ConstructorInfo GetCtorMetaInfo ()
1782 return (ConstructorInfo) ctor.GetMetaInfo ();
1785 public bool ResolveBuilder ()
1791 // Handle all parameter-less attributes as optional
1796 ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1797 return ctor != null;
1801 public class PredefinedDecimalAttribute : PredefinedAttribute
1803 public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1804 : base (module, ns, name)
1808 public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1810 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1814 int[] bits = decimal.GetBits (value);
1815 AttributeEncoder encoder = new AttributeEncoder ();
1816 encoder.Encode ((byte) (bits[3] >> 16));
1817 encoder.Encode ((byte) (bits[3] >> 31));
1818 encoder.Encode ((uint) bits[2]);
1819 encoder.Encode ((uint) bits[1]);
1820 encoder.Encode ((uint) bits[0]);
1821 encoder.EncodeEmptyNamedArguments ();
1823 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1826 public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1828 var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1832 int[] bits = decimal.GetBits (value);
1833 AttributeEncoder encoder = new AttributeEncoder ();
1834 encoder.Encode ((byte) (bits[3] >> 16));
1835 encoder.Encode ((byte) (bits[3] >> 31));
1836 encoder.Encode ((uint) bits[2]);
1837 encoder.Encode ((uint) bits[1]);
1838 encoder.Encode ((uint) bits[0]);
1839 encoder.EncodeEmptyNamedArguments ();
1841 builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1845 public class PredefinedDynamicAttribute : PredefinedAttribute
1849 public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
1850 : base (module, ns, name)
1854 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
1856 if (ResolveTransformationCtor (loc)) {
1857 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1858 builder.SetCustomAttribute (cab);
1862 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
1864 if (ResolveTransformationCtor (loc)) {
1865 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1866 builder.SetCustomAttribute (cab);
1870 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
1872 if (ResolveTransformationCtor (loc)) {
1873 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1874 builder.SetCustomAttribute (cab);
1878 public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
1880 if (ResolveTransformationCtor (loc)) {
1881 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1882 builder.SetCustomAttribute (cab);
1887 // When any element of the type is a dynamic type
1889 // This method builds a transformation array for dynamic types
1890 // used in places where DynamicAttribute cannot be applied to.
1891 // It uses bool flag when type is of dynamic type and each
1892 // section always starts with "false" for some reason.
1894 // LAMESPEC: This should be part of C# specification
1896 // Example: Func<dynamic, int, dynamic[]>
1897 // Transformation: { false, true, false, false, true }
1899 static bool[] GetTransformationFlags (TypeSpec t)
1902 var ac = t as ArrayContainer;
1904 element = GetTransformationFlags (ac.Element);
1905 if (element == null)
1908 bool[] res = new bool[element.Length + 1];
1910 Array.Copy (element, 0, res, 1, element.Length);
1918 List<bool> transform = null;
1919 var targs = t.TypeArguments;
1920 for (int i = 0; i < targs.Length; ++i) {
1921 element = GetTransformationFlags (targs[i]);
1922 if (element != null) {
1923 if (transform == null) {
1924 transform = new List<bool> ();
1925 for (int ii = 0; ii <= i; ++ii)
1926 transform.Add (false);
1929 transform.AddRange (element);
1930 } else if (transform != null) {
1931 transform.Add (false);
1935 if (transform != null)
1936 return transform.ToArray ();
1939 if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
1940 return new bool[] { true };
1945 bool ResolveTransformationCtor (Location loc)
1950 tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
1951 return tctor != null;