2 // attribute.cs: Attribute Handler
4 // Author: Ravi Pratap (ravi@ximian.com)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
13 using System.Diagnostics;
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Runtime.InteropServices;
18 using System.Runtime.CompilerServices;
21 namespace Mono.CSharp {
23 public class Attribute {
24 public readonly string Name;
25 public readonly ArrayList Arguments;
32 // The following are only meaningful when the attribute
33 // being emitted is an AttributeUsage attribute
35 AttributeTargets Targets;
39 bool UsageAttr = false;
41 MethodImplOptions ImplOptions;
42 UnmanagedType UnmanagedType;
43 CustomAttributeBuilder cb;
45 // non-null if named args present after Resolve () is called
46 PropertyInfo [] prop_info_arr;
47 FieldInfo [] field_info_arr;
48 object [] field_values_arr;
49 object [] prop_values_arr;
51 public Attribute (string name, ArrayList args, Location loc)
58 void Error_InvalidNamedArgument (string name)
60 Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
61 "argument. Named attribute arguments must be fields which are not " +
62 "readonly, static or const, or properties with a set accessor which "+
66 static void Error_AttributeArgumentNotValid (Location loc)
68 Report.Error (182, loc,
69 "An attribute argument must be a constant expression, typeof " +
70 "expression or array creation expression");
73 static void Error_AttributeConstructorMismatch (Location loc)
75 Report.Error (-6, loc,
76 "Could not find a constructor for this argument list.");
80 /// Tries to resolve the type of the attribute. Flags an error if it can't.
82 private Type CheckAttributeType (EmitContext ec) {
84 bool isattributeclass = true;
86 t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
88 isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
92 t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
94 if (t.IsSubclassOf (TypeManager.attribute_type))
97 if (!isattributeclass) {
98 Report.Error (616, Location, "'" + Name + "': is not an attribute class");
102 Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
106 246, Location, "Could not find attribute '" + Name + "' (are you" +
107 " missing a using directive or an assembly reference ?)");
111 public Type ResolveType (EmitContext ec)
113 Type = CheckAttributeType (ec);
118 /// Validates the guid string
120 bool ValidateGuid (string guid)
126 Report.Error (647, Location, "Format of GUID is invalid: " + guid);
132 // Given an expression, if the expression is a valid attribute-argument-expression
133 // returns an object that can be used to encode it, or null on failure.
135 public static bool GetAttributeArgumentExpression (Expression e, Location loc, out object result)
138 result = ((Constant) e).GetValue ();
140 } else if (e is TypeOf) {
141 result = ((TypeOf) e).TypeArg;
143 } else if (e is ArrayCreation){
144 result = ((ArrayCreation) e).EncodeAsAttribute ();
147 } else if (e is EmptyCast) {
149 if (((EmptyCast) e).Child is Constant) {
150 result = ((Constant) ((EmptyCast)e).Child).GetValue();
156 Error_AttributeArgumentNotValid (loc);
160 public CustomAttributeBuilder Resolve (EmitContext ec)
163 Type = CheckAttributeType (ec);
167 bool MethodImplAttr = false;
168 bool MarshalAsAttr = false;
169 bool GuidAttr = false;
172 bool DoCompares = true;
175 // If we are a certain special attribute, we
176 // set the information accordingly
179 if (Type == TypeManager.attribute_usage_type)
181 else if (Type == TypeManager.methodimpl_attr_type)
182 MethodImplAttr = true;
183 else if (Type == TypeManager.marshal_as_attr_type)
184 MarshalAsAttr = true;
185 else if (Type == TypeManager.guid_attr_type)
190 // Now we extract the positional and named arguments
192 ArrayList pos_args = new ArrayList ();
193 ArrayList named_args = new ArrayList ();
194 int pos_arg_count = 0;
196 if (Arguments != null) {
197 pos_args = (ArrayList) Arguments [0];
198 if (pos_args != null)
199 pos_arg_count = pos_args.Count;
200 if (Arguments.Count > 1)
201 named_args = (ArrayList) Arguments [1];
204 object [] pos_values = new object [pos_arg_count];
207 // First process positional arguments
211 for (i = 0; i < pos_arg_count; i++) {
212 Argument a = (Argument) pos_args [i];
215 if (!a.Resolve (ec, Location))
221 if (!GetAttributeArgumentExpression (e, Location, out val))
224 pos_values [i] = val;
227 this.Targets = (AttributeTargets) pos_values [0];
228 else if (MethodImplAttr)
229 this.ImplOptions = (MethodImplOptions) pos_values [0];
232 // we will later check the validity of the type
234 if (pos_values [0] is string){
235 if (!ValidateGuid ((string) pos_values [0]))
239 } else if (MarshalAsAttr)
241 (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
246 // Now process named arguments
249 ArrayList field_infos = null;
250 ArrayList prop_infos = null;
251 ArrayList field_values = null;
252 ArrayList prop_values = null;
254 if (named_args.Count > 0) {
255 field_infos = new ArrayList ();
256 prop_infos = new ArrayList ();
257 field_values = new ArrayList ();
258 prop_values = new ArrayList ();
261 for (i = 0; i < named_args.Count; i++) {
262 DictionaryEntry de = (DictionaryEntry) named_args [i];
263 string member_name = (string) de.Key;
264 Argument a = (Argument) de.Value;
267 if (!a.Resolve (ec, Location))
270 Expression member = Expression.MemberLookup (
271 ec, Type, member_name,
272 MemberTypes.Field | MemberTypes.Property,
273 BindingFlags.Public | BindingFlags.Instance,
276 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
277 Error_InvalidNamedArgument (member_name);
282 if (member is PropertyExpr) {
283 PropertyExpr pe = (PropertyExpr) member;
284 PropertyInfo pi = pe.PropertyInfo;
287 Error_InvalidNamedArgument (member_name);
292 object o = ((Constant) e).GetValue ();
296 if (member_name == "AllowMultiple")
297 this.AllowMultiple = (bool) o;
298 if (member_name == "Inherited")
299 this.Inherited = (bool) o;
302 } else if (e is TypeOf) {
303 prop_values.Add (((TypeOf) e).TypeArg);
304 } else if (e is ArrayCreation) {
305 prop_values.Add (((ArrayCreation) e).EncodeAsAttribute());
307 Error_AttributeArgumentNotValid (Location);
313 } else if (member is FieldExpr) {
314 FieldExpr fe = (FieldExpr) member;
315 FieldInfo fi = fe.FieldInfo;
318 Error_InvalidNamedArgument (member_name);
323 // Handle charset here, and set the TypeAttributes
326 object value = ((Constant) e).GetValue ();
328 field_values.Add (value);
329 } else if (e is TypeOf) {
330 field_values.Add (((TypeOf) e).TypeArg);
332 Error_AttributeArgumentNotValid (Location);
336 field_infos.Add (fi);
340 Expression mg = Expression.MemberLookup (
341 ec, Type, ".ctor", MemberTypes.Constructor,
342 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
346 Error_AttributeConstructorMismatch (Location);
350 MethodBase constructor = Invocation.OverloadResolve (
351 ec, (MethodGroupExpr) mg, pos_args, Location);
353 if (constructor == null) {
354 Error_AttributeConstructorMismatch (Location);
359 // Now we perform some checks on the positional args as they
360 // cannot be null for a constructor which expects a parameter
364 ParameterData pd = Invocation.GetParameterData (constructor);
366 int group_in_params_array = Int32.MaxValue;
368 if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
369 group_in_params_array = pc-1;
371 for (int j = 0; j < pos_arg_count; ++j) {
372 Argument a = (Argument) pos_args [j];
374 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
375 Error_AttributeArgumentNotValid (Location);
379 if (j < group_in_params_array)
382 if (j == group_in_params_array){
383 object v = pos_values [j];
384 int count = pos_arg_count - j;
386 object [] array = new object [count];
387 pos_values [j] = array;
390 object [] array = (object []) pos_values [group_in_params_array];
392 array [j - group_in_params_array] = pos_values [j];
397 // Adjust the size of the pos_values if it had params
399 if (group_in_params_array != Int32.MaxValue){
400 int argc = group_in_params_array+1;
401 object [] new_pos_values = new object [argc];
403 for (int p = 0; p < argc; p++)
404 new_pos_values [p] = pos_values [p];
405 pos_values = new_pos_values;
409 if (named_args.Count > 0) {
410 prop_info_arr = new PropertyInfo [prop_infos.Count];
411 field_info_arr = new FieldInfo [field_infos.Count];
412 field_values_arr = new object [field_values.Count];
413 prop_values_arr = new object [prop_values.Count];
415 field_infos.CopyTo (field_info_arr, 0);
416 field_values.CopyTo (field_values_arr, 0);
418 prop_values.CopyTo (prop_values_arr, 0);
419 prop_infos.CopyTo (prop_info_arr, 0);
421 cb = new CustomAttributeBuilder (
422 (ConstructorInfo) constructor, pos_values,
423 prop_info_arr, prop_values_arr,
424 field_info_arr, field_values_arr);
427 cb = new CustomAttributeBuilder (
428 (ConstructorInfo) constructor, pos_values);
429 } catch (NullReferenceException) {
431 // Don't know what to do here
434 -101, Location, "NullReferenceException while trying to create attribute." +
435 "Something's wrong!");
436 } catch (Exception e) {
439 // using System.ComponentModel;
440 // [DefaultValue (CollectionChangeAction.Add)]
441 // class X { static void Main () {} }
445 "The compiler can not encode this attribute in .NET due to\n" +
446 "\ta bug in the .NET runtime. Try the Mono runtime.\nThe error was: " + e.Message);
453 /// Get a string containing a list of valid targets for the attribute 'attr'
455 static string GetValidTargets (Attribute attr)
457 StringBuilder sb = new StringBuilder ();
458 AttributeTargets targets = 0;
460 TypeContainer a = TypeManager.LookupAttr (attr.Type);
464 System.Attribute [] attrs = null;
467 attrs = System.Attribute.GetCustomAttributes (attr.Type);
470 Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
471 " (maybe you forgot to set the usage using the" +
472 " AttributeUsage attribute ?).");
476 foreach (System.Attribute tmp in attrs)
477 if (tmp is AttributeUsageAttribute) {
478 targets = ((AttributeUsageAttribute) tmp).ValidOn;
485 if ((targets & AttributeTargets.Assembly) != 0)
486 sb.Append ("'assembly' ");
488 if ((targets & AttributeTargets.Class) != 0)
489 sb.Append ("'class' ");
491 if ((targets & AttributeTargets.Constructor) != 0)
492 sb.Append ("'constructor' ");
494 if ((targets & AttributeTargets.Delegate) != 0)
495 sb.Append ("'delegate' ");
497 if ((targets & AttributeTargets.Enum) != 0)
498 sb.Append ("'enum' ");
500 if ((targets & AttributeTargets.Event) != 0)
501 sb.Append ("'event' ");
503 if ((targets & AttributeTargets.Field) != 0)
504 sb.Append ("'field' ");
506 if ((targets & AttributeTargets.Interface) != 0)
507 sb.Append ("'interface' ");
509 if ((targets & AttributeTargets.Method) != 0)
510 sb.Append ("'method' ");
512 if ((targets & AttributeTargets.Module) != 0)
513 sb.Append ("'module' ");
515 if ((targets & AttributeTargets.Parameter) != 0)
516 sb.Append ("'parameter' ");
518 if ((targets & AttributeTargets.Property) != 0)
519 sb.Append ("'property' ");
521 if ((targets & AttributeTargets.ReturnValue) != 0)
522 sb.Append ("'return value' ");
524 if ((targets & AttributeTargets.Struct) != 0)
525 sb.Append ("'struct' ");
527 return sb.ToString ();
531 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
534 592, loc, "Attribute '" + a.Name +
535 "' is not valid on this declaration type. " +
536 "It is valid on " + GetValidTargets (a) + "declarations only.");
540 /// Ensure that Attribute 'a' is being applied to the right language element (target)
542 public static bool CheckAttributeTarget (Attribute a, object element)
544 TypeContainer attr = TypeManager.LookupAttr (a.Type);
545 AttributeTargets targets = 0;
548 System.Attribute [] attrs = null;
551 attrs = System.Attribute.GetCustomAttributes (a.Type);
554 Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
555 " (maybe you forgot to set the usage using the" +
556 " AttributeUsage attribute ?).");
560 foreach (System.Attribute tmp in attrs)
561 if (tmp is AttributeUsageAttribute) {
562 targets = ((AttributeUsageAttribute) tmp).ValidOn;
566 targets = attr.Targets;
569 if (element is Class) {
570 if ((targets & AttributeTargets.Class) != 0)
575 } else if (element is Struct) {
576 if ((targets & AttributeTargets.Struct) != 0)
580 } else if (element is Constructor) {
581 if ((targets & AttributeTargets.Constructor) != 0)
585 } else if (element is Delegate) {
586 if ((targets & AttributeTargets.Delegate) != 0)
590 } else if (element is Enum) {
591 if ((targets & AttributeTargets.Enum) != 0)
595 } else if (element is Event || element is InterfaceEvent) {
596 if ((targets & AttributeTargets.Event) != 0)
600 } else if (element is Field || element is FieldBuilder) {
601 if ((targets & AttributeTargets.Field) != 0)
605 } else if (element is Interface) {
606 if ((targets & AttributeTargets.Interface) != 0)
610 } else if (element is Method || element is Operator ||
611 element is InterfaceMethod || element is Accessor) {
612 if ((targets & AttributeTargets.Method) != 0)
616 } else if (element is ParameterBuilder) {
617 if ((targets & AttributeTargets.Parameter) != 0 ||
618 (targets & AttributeTargets.ReturnValue) != 0)
622 } else if (element is Property || element is Indexer ||
623 element is InterfaceProperty || element is InterfaceIndexer || element is InterfaceProperty.PropertyAccessor) {
624 if ((targets & AttributeTargets.Property) != 0)
628 } else if (element is AssemblyClass){
629 if ((targets & AttributeTargets.Assembly) != 0)
633 } else if (element is ModuleClass){
634 if ((targets & AttributeTargets.Module) != 0)
644 // This method should be invoked to pull the IndexerName attribute from an
645 // Indexer if it exists.
647 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
649 if (opt_attrs == null)
651 if (opt_attrs.AttributeSections == null)
654 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
655 if (asec.Attributes == null)
658 foreach (Attribute a in asec.Attributes){
659 if (a.ResolveType (ec) == null)
662 if (a.Type != TypeManager.indexer_name_type)
666 // So we have found an IndexerName, pull the data out.
668 if (a.Arguments == null || a.Arguments [0] == null){
669 Error_AttributeConstructorMismatch (a.Location);
672 ArrayList pos_args = (ArrayList) a.Arguments [0];
673 if (pos_args.Count == 0){
674 Error_AttributeConstructorMismatch (a.Location);
678 Argument arg = (Argument) pos_args [0];
679 if (!arg.Resolve (ec, a.Location))
682 Expression e = arg.Expr;
683 if (!(e is StringConstant)){
684 Error_AttributeConstructorMismatch (a.Location);
689 // Remove the attribute from the list
691 asec.Attributes.Remove (a);
693 return (((StringConstant) e).Value);
700 // This pulls the condition name out of a Conditional attribute
702 public string Conditional_GetConditionName ()
705 // So we have a Conditional, pull the data out.
707 if (Arguments == null || Arguments [0] == null){
708 Error_AttributeConstructorMismatch (Location);
712 ArrayList pos_args = (ArrayList) Arguments [0];
713 if (pos_args.Count != 1){
714 Error_AttributeConstructorMismatch (Location);
718 Argument arg = (Argument) pos_args [0];
719 if (!(arg.Expr is StringConstant)){
720 Error_AttributeConstructorMismatch (Location);
724 return ((StringConstant) arg.Expr).Value;
728 // This pulls the obsolete message and error flag out of an Obsolete attribute
730 public string Obsolete_GetObsoleteMessage (out bool is_error)
734 // So we have an Obsolete, pull the data out.
736 if (Arguments == null || Arguments [0] == null)
739 ArrayList pos_args = (ArrayList) Arguments [0];
740 if (pos_args.Count == 0)
742 else if (pos_args.Count > 2){
743 Error_AttributeConstructorMismatch (Location);
747 Argument arg = (Argument) pos_args [0];
748 if (!(arg.Expr is StringConstant)){
749 Error_AttributeConstructorMismatch (Location);
753 if (pos_args.Count == 2){
754 Argument arg2 = (Argument) pos_args [1];
755 if (!(arg2.Expr is BoolConstant)){
756 Error_AttributeConstructorMismatch (Location);
759 is_error = ((BoolConstant) arg2.Expr).Value;
762 return ((StringConstant) arg.Expr).Value;
765 static object GetFieldValue (Attribute a, string name)
768 if (a.field_info_arr == null)
771 foreach (FieldInfo fi in a.field_info_arr) {
773 return a.field_values_arr [i];
779 static UnmanagedMarshal GetMarshal (Attribute a)
781 object o = GetFieldValue (a, "ArraySubType");
782 UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
784 switch (a.UnmanagedType) {
785 case UnmanagedType.CustomMarshaler:
786 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
787 BindingFlags.Static | BindingFlags.Public);
788 if (define_custom == null)
791 object [] args = new object [4];
792 args [0] = GetFieldValue (a, "MarshalTypeRef");
793 args [1] = GetFieldValue (a, "MarshalCookie");
794 args [2] = GetFieldValue (a, "MarshalType");
795 args [3] = Guid.Empty;
796 return (UnmanagedMarshal) define_custom.Invoke (null, args);
798 case UnmanagedType.LPArray:
799 return UnmanagedMarshal.DefineLPArray (array_sub_type);
801 case UnmanagedType.SafeArray:
802 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
804 case UnmanagedType.ByValArray:
805 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue (a, "SizeConst"));
807 case UnmanagedType.ByValTStr:
808 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue (a, "SizeConst"));
811 return UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
816 /// Applies the attributes specified on target 'kind' to the `builder'.
818 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
819 Attributes opt_attrs)
821 Type attr_type = null;
823 if (opt_attrs == null)
825 if (opt_attrs.AttributeSections == null)
828 ArrayList emitted_attrs = new ArrayList ();
829 ArrayList emitted_targets = new ArrayList ();
831 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
832 string attr_target = asec.Target;
834 if (asec.Attributes == null)
837 if (attr_target == "return" && !(builder is ParameterBuilder))
840 foreach (Attribute a in asec.Attributes) {
841 Location loc = a.Location;
842 CustomAttributeBuilder cb = a.Resolve (ec);
848 if (!(kind is TypeContainer))
849 if (!CheckAttributeTarget (a, kind)) {
850 Error_AttributeNotValidForElement (a, loc);
855 // Perform the check for duplicate attributes
857 if (emitted_attrs.Contains (attr_type) &&
858 emitted_targets.Contains (attr_target) &&
859 !TypeManager.AreMultipleAllowed (attr_type)) {
860 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
864 if (kind is IAttributeSupport) {
865 if (attr_type == TypeManager.methodimpl_attr_type && a.ImplOptions == MethodImplOptions.InternalCall) {
866 ((MethodBuilder) builder).SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
869 IAttributeSupport attributeSupport = kind as IAttributeSupport;
870 attributeSupport.SetCustomAttribute (cb);
873 else if (kind is Method || kind is Operator || kind is InterfaceMethod ||
876 if (attr_type == TypeManager.methodimpl_attr_type) {
877 if (a.ImplOptions == MethodImplOptions.InternalCall)
878 ((MethodBuilder) builder).
879 SetImplementationFlags (
880 MethodImplAttributes.InternalCall |
881 MethodImplAttributes.Runtime);
883 ((MethodBuilder) builder).SetCustomAttribute (cb);
884 } else if (attr_type != TypeManager.dllimport_type){
885 ((MethodBuilder) builder).SetCustomAttribute (cb);
887 } else if (kind is Constructor) {
888 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
889 } else if (kind is Field) {
890 if (attr_type == TypeManager.marshal_as_attr_type) {
891 UnmanagedMarshal marshal = GetMarshal (a);
892 if (marshal == null) {
893 Report.Warning (-24, loc,
894 "The Microsoft Runtime cannot set this marshal info. " +
895 "Please use the Mono runtime instead.");
897 ((FieldBuilder) builder).SetMarshal (marshal);
900 ((FieldBuilder) builder).SetCustomAttribute (cb);
902 } else if (kind is Property || kind is Indexer ||
903 kind is InterfaceProperty || kind is InterfaceIndexer) {
905 if (builder is PropertyBuilder)
906 ((PropertyBuilder) builder).SetCustomAttribute (cb);
908 // This is for the case we are setting attributes on
909 // the get and set accessors
911 else if (builder is MethodBuilder)
912 ((MethodBuilder) builder).SetCustomAttribute (cb);
913 } else if (kind is Event || kind is InterfaceEvent) {
914 ((MyEventBuilder) builder).SetCustomAttribute (cb);
915 } else if (kind is ParameterBuilder) {
917 if (attr_type == TypeManager.marshal_as_attr_type) {
918 UnmanagedMarshal marshal = GetMarshal (a);
919 if (marshal == null) {
920 Report.Warning (-24, loc,
921 "The Microsoft Runtime cannot set this marshal info. " +
922 "Please use the Mono runtime instead.");
924 ((ParameterBuilder) builder).SetMarshal (marshal);
929 ((ParameterBuilder) builder).SetCustomAttribute (cb);
930 } catch (System.ArgumentException) {
931 Report.Warning (-24, loc,
932 "The Microsoft Runtime cannot set attributes \n" +
933 "on the return type of a method. Please use the \n" +
934 "Mono runtime instead.");
938 } else if (kind is Enum) {
939 ((TypeBuilder) builder).SetCustomAttribute (cb);
941 } else if (kind is TypeContainer) {
942 TypeContainer tc = (TypeContainer) kind;
945 tc.Targets = a.Targets;
946 tc.AllowMultiple = a.AllowMultiple;
947 tc.Inherited = a.Inherited;
949 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
952 } else if (attr_type == TypeManager.default_member_type) {
953 if (tc.Indexers != null) {
954 Report.Error (646, loc,
955 "Cannot specify the DefaultMember attribute on" +
956 " a type containing an indexer");
961 if (!CheckAttributeTarget (a, kind)) {
962 Error_AttributeNotValidForElement (a, loc);
968 ((TypeBuilder) builder).SetCustomAttribute (cb);
969 } catch (System.ArgumentException) {
972 "The CharSet named property on StructLayout\n"+
973 "\tdoes not work correctly on Microsoft.NET\n"+
974 "\tYou might want to remove the CharSet declaration\n"+
975 "\tor compile using the Mono runtime instead of the\n"+
976 "\tMicrosoft .NET runtime");
978 } else if (kind is Delegate){
979 if (!CheckAttributeTarget (a, kind)) {
980 Error_AttributeNotValidForElement (a, loc);
984 ((TypeBuilder) builder).SetCustomAttribute (cb);
985 } catch (System.ArgumentException) {
988 "The CharSet named property on StructLayout\n"+
989 "\tdoes not work correctly on Microsoft.NET\n"+
990 "\tYou might want to remove the CharSet declaration\n"+
991 "\tor compile using the Mono runtime instead of the\n"+
992 "\tMicrosoft .NET runtime");
994 } else if (kind is Interface) {
995 Interface iface = (Interface) kind;
997 if ((attr_type == TypeManager.default_member_type) &&
998 (iface.InterfaceIndexers != null)) {
1001 "Cannot specify the DefaultMember attribute on" +
1002 " a type containing an indexer");
1006 if (!CheckAttributeTarget (a, kind)) {
1007 Error_AttributeNotValidForElement (a, loc);
1011 ((TypeBuilder) builder).SetCustomAttribute (cb);
1012 } else if (kind is AssemblyBuilder){
1013 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
1014 } else if (kind is ModuleBuilder) {
1015 ((ModuleBuilder) builder).SetCustomAttribute (cb);
1016 } else if (kind is FieldBuilder) {
1017 if (attr_type == TypeManager.marshal_as_attr_type) {
1018 UnmanagedMarshal marshal = GetMarshal (a);
1019 if (marshal == null) {
1020 Report.Warning (-24, loc,
1021 "The Microsoft Runtime cannot set this marshal info. " +
1022 "Please use the Mono runtime instead.");
1024 ((ParameterBuilder) builder).SetMarshal (marshal);
1027 ((FieldBuilder) builder).SetCustomAttribute (cb);
1030 throw new Exception ("Unknown kind: " + kind);
1033 // Once an attribute type has been emitted once we
1034 // keep track of the info to prevent multiple occurences
1035 // for attributes which do not explicitly allow it
1037 if (!emitted_attrs.Contains (attr_type))
1038 emitted_attrs.Add (attr_type);
1041 // We keep of this target-wise and so emitted targets
1044 if (!emitted_targets.Contains (attr_target))
1045 emitted_targets.Add (attr_target);
1052 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
1053 MethodAttributes flags, Type ret_type, Type [] param_types)
1056 // We extract from the attribute the information we need
1059 if (Arguments == null) {
1060 Console.WriteLine ("Internal error : this is not supposed to happen !");
1064 Type = CheckAttributeType (ec);
1068 ArrayList named_args = new ArrayList ();
1070 ArrayList pos_args = (ArrayList) Arguments [0];
1071 if (Arguments.Count > 1)
1072 named_args = (ArrayList) Arguments [1];
1075 string dll_name = null;
1077 Argument tmp = (Argument) pos_args [0];
1079 if (!tmp.Resolve (ec, Location))
1082 if (tmp.Expr is Constant)
1083 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
1085 Error_AttributeArgumentNotValid (Location);
1089 // Now we process the named arguments
1090 CallingConvention cc = CallingConvention.Winapi;
1091 CharSet charset = CharSet.Ansi;
1092 bool preserve_sig = true;
1094 bool exact_spelling = false;
1096 bool set_last_err = false;
1097 string entry_point = null;
1099 for (int i = 0; i < named_args.Count; i++) {
1101 DictionaryEntry de = (DictionaryEntry) named_args [i];
1103 string member_name = (string) de.Key;
1104 Argument a = (Argument) de.Value;
1106 if (!a.Resolve (ec, Location))
1109 Expression member = Expression.MemberLookup (
1110 ec, Type, member_name,
1111 MemberTypes.Field | MemberTypes.Property,
1112 BindingFlags.Public | BindingFlags.Instance,
1115 if (member == null || !(member is FieldExpr)) {
1116 Error_InvalidNamedArgument (member_name);
1120 if (member is FieldExpr) {
1121 FieldExpr fe = (FieldExpr) member;
1122 FieldInfo fi = fe.FieldInfo;
1124 if (fi.IsInitOnly) {
1125 Error_InvalidNamedArgument (member_name);
1129 if (a.Expr is Constant) {
1130 Constant c = (Constant) a.Expr;
1132 if (member_name == "CallingConvention")
1133 cc = (CallingConvention) c.GetValue ();
1134 else if (member_name == "CharSet")
1135 charset = (CharSet) c.GetValue ();
1136 else if (member_name == "EntryPoint")
1137 entry_point = (string) c.GetValue ();
1138 else if (member_name == "SetLastError")
1139 set_last_err = (bool) c.GetValue ();
1141 else if (member_name == "ExactSpelling")
1142 exact_spelling = (bool) c.GetValue ();
1144 else if (member_name == "PreserveSig")
1145 preserve_sig = (bool) c.GetValue ();
1147 Error_AttributeArgumentNotValid (Location);
1154 if (entry_point == null)
1157 charset = (CharSet)((int)charset | 0x40);
1159 MethodBuilder mb = builder.DefinePInvokeMethod (
1160 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
1161 CallingConventions.Standard,
1168 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
1175 public class AttributeSection {
1176 public readonly string Target;
1177 public readonly ArrayList Attributes;
1179 public AttributeSection (string target, ArrayList attrs)
1187 public class Attributes {
1188 public ArrayList AttributeSections;
1190 public Attributes (AttributeSection a)
1192 AttributeSections = new ArrayList ();
1193 AttributeSections.Add (a);
1197 public void AddAttributeSection (AttributeSection a)
1199 if (a != null && !AttributeSections.Contains (a))
1200 AttributeSections.Add (a);
1203 public bool Contains (Type t)
1205 foreach (AttributeSection attr_section in AttributeSections){
1206 foreach (Attribute a in attr_section.Attributes){
1216 public interface IAttributeSupport {
1217 void SetCustomAttribute (CustomAttributeBuilder customBuilder);