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) {
624 if ((targets & AttributeTargets.Property) != 0)
628 } else if (element is AssemblyBuilder){
629 if ((targets & AttributeTargets.Assembly) != 0)
639 // This method should be invoked to pull the IndexerName attribute from an
640 // Indexer if it exists.
642 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
644 if (opt_attrs == null)
646 if (opt_attrs.AttributeSections == null)
649 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
650 if (asec.Attributes == null)
653 foreach (Attribute a in asec.Attributes){
654 if (a.ResolveType (ec) == null)
657 if (a.Type != TypeManager.indexer_name_type)
661 // So we have found an IndexerName, pull the data out.
663 if (a.Arguments == null || a.Arguments [0] == null){
664 Error_AttributeConstructorMismatch (a.Location);
667 ArrayList pos_args = (ArrayList) a.Arguments [0];
668 if (pos_args.Count == 0){
669 Error_AttributeConstructorMismatch (a.Location);
673 Argument arg = (Argument) pos_args [0];
674 if (!arg.Resolve (ec, a.Location))
677 Expression e = arg.Expr;
678 if (!(e is StringConstant)){
679 Error_AttributeConstructorMismatch (a.Location);
684 // Remove the attribute from the list
686 asec.Attributes.Remove (a);
688 return (((StringConstant) e).Value);
695 // This pulls the condition name out of a Conditional attribute
697 public string Conditional_GetConditionName ()
700 // So we have a Conditional, pull the data out.
702 if (Arguments == null || Arguments [0] == null){
703 Error_AttributeConstructorMismatch (Location);
707 ArrayList pos_args = (ArrayList) Arguments [0];
708 if (pos_args.Count != 1){
709 Error_AttributeConstructorMismatch (Location);
713 Argument arg = (Argument) pos_args [0];
714 if (!(arg.Expr is StringConstant)){
715 Error_AttributeConstructorMismatch (Location);
719 return ((StringConstant) arg.Expr).Value;
723 // This pulls the obsolete message and error flag out of an Obsolete attribute
725 public string Obsolete_GetObsoleteMessage (out bool is_error)
729 // So we have an Obsolete, pull the data out.
731 if (Arguments == null || Arguments [0] == null)
734 ArrayList pos_args = (ArrayList) Arguments [0];
735 if (pos_args.Count == 0)
737 else if (pos_args.Count > 2){
738 Error_AttributeConstructorMismatch (Location);
742 Argument arg = (Argument) pos_args [0];
743 if (!(arg.Expr is StringConstant)){
744 Error_AttributeConstructorMismatch (Location);
748 if (pos_args.Count == 2){
749 Argument arg2 = (Argument) pos_args [1];
750 if (!(arg2.Expr is BoolConstant)){
751 Error_AttributeConstructorMismatch (Location);
754 is_error = ((BoolConstant) arg2.Expr).Value;
757 return ((StringConstant) arg.Expr).Value;
760 static object GetFieldValue (Attribute a, string name)
763 if (a.field_info_arr == null)
766 foreach (FieldInfo fi in a.field_info_arr) {
768 return a.field_values_arr [i];
774 static UnmanagedMarshal GetMarshal (Attribute a)
776 object o = GetFieldValue (a, "ArraySubType");
777 UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
779 switch (a.UnmanagedType) {
780 case UnmanagedType.CustomMarshaler:
781 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
782 BindingFlags.Static | BindingFlags.Public);
783 if (define_custom == null)
786 object [] args = new object [4];
787 args [0] = GetFieldValue (a, "MarshalTypeRef");
788 args [1] = GetFieldValue (a, "MarshalCookie");
789 args [2] = GetFieldValue (a, "MarshalType");
790 args [3] = Guid.Empty;
791 return (UnmanagedMarshal) define_custom.Invoke (null, args);
793 case UnmanagedType.LPArray:
794 return UnmanagedMarshal.DefineLPArray (array_sub_type);
796 case UnmanagedType.SafeArray:
797 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
799 case UnmanagedType.ByValArray:
800 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue (a, "SizeConst"));
802 case UnmanagedType.ByValTStr:
803 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue (a, "SizeConst"));
806 return UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
811 /// Applies the attributes specified on target 'kind' to the `builder'.
813 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
814 Attributes opt_attrs)
816 Type attr_type = null;
818 if (opt_attrs == null)
820 if (opt_attrs.AttributeSections == null)
823 ArrayList emitted_attrs = new ArrayList ();
824 ArrayList emitted_targets = new ArrayList ();
826 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
827 string attr_target = asec.Target;
829 if (asec.Attributes == null)
832 if (attr_target == "assembly" && !(builder is AssemblyBuilder))
835 if (attr_target == "return" && !(builder is ParameterBuilder))
838 foreach (Attribute a in asec.Attributes) {
839 Location loc = a.Location;
840 CustomAttributeBuilder cb = a.Resolve (ec);
846 if (!(kind is TypeContainer))
847 if (!CheckAttributeTarget (a, kind)) {
848 Error_AttributeNotValidForElement (a, loc);
853 // Perform the check for duplicate attributes
855 if (emitted_attrs.Contains (attr_type) &&
856 emitted_targets.Contains (attr_target) &&
857 !TypeManager.AreMultipleAllowed (attr_type)) {
858 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
862 if (kind is Method || kind is Operator || kind is InterfaceMethod ||
864 if (attr_type == TypeManager.methodimpl_attr_type) {
865 if (a.ImplOptions == MethodImplOptions.InternalCall)
866 ((MethodBuilder) builder).
867 SetImplementationFlags (
868 MethodImplAttributes.InternalCall |
869 MethodImplAttributes.Runtime);
871 ((MethodBuilder) builder).SetCustomAttribute (cb);
872 } else if (attr_type != TypeManager.dllimport_type){
873 ((MethodBuilder) builder).SetCustomAttribute (cb);
875 } else if (kind is Constructor) {
876 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
877 } else if (kind is Field) {
878 if (attr_type == TypeManager.marshal_as_attr_type) {
879 UnmanagedMarshal marshal = GetMarshal (a);
880 if (marshal == null) {
881 Report.Warning (-24, loc,
882 "The Microsoft Runtime cannot set this marshal info. " +
883 "Please use the Mono runtime instead.");
885 ((FieldBuilder) builder).SetMarshal (marshal);
888 ((FieldBuilder) builder).SetCustomAttribute (cb);
890 } else if (kind is Property || kind is Indexer ||
891 kind is InterfaceProperty || kind is InterfaceIndexer) {
893 if (builder is PropertyBuilder)
894 ((PropertyBuilder) builder).SetCustomAttribute (cb);
896 // This is for the case we are setting attributes on
897 // the get and set accessors
899 else if (builder is MethodBuilder)
900 ((MethodBuilder) builder).SetCustomAttribute (cb);
901 } else if (kind is Event || kind is InterfaceEvent) {
902 ((MyEventBuilder) builder).SetCustomAttribute (cb);
903 } else if (kind is ParameterBuilder) {
905 if (attr_type == TypeManager.marshal_as_attr_type) {
906 UnmanagedMarshal marshal = GetMarshal (a);
907 if (marshal == null) {
908 Report.Warning (-24, loc,
909 "The Microsoft Runtime cannot set this marshal info. " +
910 "Please use the Mono runtime instead.");
912 ((ParameterBuilder) builder).SetMarshal (marshal);
917 ((ParameterBuilder) builder).SetCustomAttribute (cb);
918 } catch (System.ArgumentException) {
919 Report.Warning (-24, loc,
920 "The Microsoft Runtime cannot set attributes \n" +
921 "on the return type of a method. Please use the \n" +
922 "Mono runtime instead.");
926 } else if (kind is Enum) {
927 ((TypeBuilder) builder).SetCustomAttribute (cb);
929 } else if (kind is TypeContainer) {
930 TypeContainer tc = (TypeContainer) kind;
933 tc.Targets = a.Targets;
934 tc.AllowMultiple = a.AllowMultiple;
935 tc.Inherited = a.Inherited;
937 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
940 } else if (attr_type == TypeManager.default_member_type) {
941 if (tc.Indexers != null) {
942 Report.Error (646, loc,
943 "Cannot specify the DefaultMember attribute on" +
944 " a type containing an indexer");
949 if (!CheckAttributeTarget (a, kind)) {
950 Error_AttributeNotValidForElement (a, loc);
956 ((TypeBuilder) builder).SetCustomAttribute (cb);
957 } catch (System.ArgumentException) {
960 "The CharSet named property on StructLayout\n"+
961 "\tdoes not work correctly on Microsoft.NET\n"+
962 "\tYou might want to remove the CharSet declaration\n"+
963 "\tor compile using the Mono runtime instead of the\n"+
964 "\tMicrosoft .NET runtime");
966 } else if (kind is Delegate){
967 if (!CheckAttributeTarget (a, kind)) {
968 Error_AttributeNotValidForElement (a, loc);
972 ((TypeBuilder) builder).SetCustomAttribute (cb);
973 } catch (System.ArgumentException) {
976 "The CharSet named property on StructLayout\n"+
977 "\tdoes not work correctly on Microsoft.NET\n"+
978 "\tYou might want to remove the CharSet declaration\n"+
979 "\tor compile using the Mono runtime instead of the\n"+
980 "\tMicrosoft .NET runtime");
982 } else if (kind is Interface) {
983 Interface iface = (Interface) kind;
985 if ((attr_type == TypeManager.default_member_type) &&
986 (iface.InterfaceIndexers != null)) {
989 "Cannot specify the DefaultMember attribute on" +
990 " a type containing an indexer");
994 if (!CheckAttributeTarget (a, kind)) {
995 Error_AttributeNotValidForElement (a, loc);
999 ((TypeBuilder) builder).SetCustomAttribute (cb);
1000 } else if (kind is AssemblyBuilder){
1001 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
1002 } else if (kind is ModuleBuilder) {
1003 ((ModuleBuilder) builder).SetCustomAttribute (cb);
1004 } else if (kind is FieldBuilder) {
1005 if (attr_type == TypeManager.marshal_as_attr_type) {
1006 UnmanagedMarshal marshal = GetMarshal (a);
1007 if (marshal == null) {
1008 Report.Warning (-24, loc,
1009 "The Microsoft Runtime cannot set this marshal info. " +
1010 "Please use the Mono runtime instead.");
1012 ((ParameterBuilder) builder).SetMarshal (marshal);
1015 ((FieldBuilder) builder).SetCustomAttribute (cb);
1018 throw new Exception ("Unknown kind: " + kind);
1021 // Once an attribute type has been emitted once we
1022 // keep track of the info to prevent multiple occurences
1023 // for attributes which do not explicitly allow it
1025 if (!emitted_attrs.Contains (attr_type))
1026 emitted_attrs.Add (attr_type);
1029 // We keep of this target-wise and so emitted targets
1032 if (!emitted_targets.Contains (attr_target))
1033 emitted_targets.Add (attr_target);
1040 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
1041 MethodAttributes flags, Type ret_type, Type [] param_types)
1044 // We extract from the attribute the information we need
1047 if (Arguments == null) {
1048 Console.WriteLine ("Internal error : this is not supposed to happen !");
1052 Type = CheckAttributeType (ec);
1056 ArrayList named_args = new ArrayList ();
1058 ArrayList pos_args = (ArrayList) Arguments [0];
1059 if (Arguments.Count > 1)
1060 named_args = (ArrayList) Arguments [1];
1063 string dll_name = null;
1065 Argument tmp = (Argument) pos_args [0];
1067 if (!tmp.Resolve (ec, Location))
1070 if (tmp.Expr is Constant)
1071 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
1073 Error_AttributeArgumentNotValid (Location);
1077 // Now we process the named arguments
1078 CallingConvention cc = CallingConvention.Winapi;
1079 CharSet charset = CharSet.Ansi;
1080 bool preserve_sig = true;
1082 bool exact_spelling = false;
1084 bool set_last_err = false;
1085 string entry_point = null;
1087 for (int i = 0; i < named_args.Count; i++) {
1089 DictionaryEntry de = (DictionaryEntry) named_args [i];
1091 string member_name = (string) de.Key;
1092 Argument a = (Argument) de.Value;
1094 if (!a.Resolve (ec, Location))
1097 Expression member = Expression.MemberLookup (
1098 ec, Type, member_name,
1099 MemberTypes.Field | MemberTypes.Property,
1100 BindingFlags.Public | BindingFlags.Instance,
1103 if (member == null || !(member is FieldExpr)) {
1104 Error_InvalidNamedArgument (member_name);
1108 if (member is FieldExpr) {
1109 FieldExpr fe = (FieldExpr) member;
1110 FieldInfo fi = fe.FieldInfo;
1112 if (fi.IsInitOnly) {
1113 Error_InvalidNamedArgument (member_name);
1117 if (a.Expr is Constant) {
1118 Constant c = (Constant) a.Expr;
1120 if (member_name == "CallingConvention")
1121 cc = (CallingConvention) c.GetValue ();
1122 else if (member_name == "CharSet")
1123 charset = (CharSet) c.GetValue ();
1124 else if (member_name == "EntryPoint")
1125 entry_point = (string) c.GetValue ();
1126 else if (member_name == "SetLastError")
1127 set_last_err = (bool) c.GetValue ();
1129 else if (member_name == "ExactSpelling")
1130 exact_spelling = (bool) c.GetValue ();
1132 else if (member_name == "PreserveSig")
1133 preserve_sig = (bool) c.GetValue ();
1135 Error_AttributeArgumentNotValid (Location);
1142 if (entry_point == null)
1145 charset = (CharSet)((int)charset | 0x40);
1147 MethodBuilder mb = builder.DefinePInvokeMethod (
1148 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
1149 CallingConventions.Standard,
1156 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
1163 public class AttributeSection {
1164 public readonly string Target;
1165 public readonly ArrayList Attributes;
1167 public AttributeSection (string target, ArrayList attrs)
1175 public class Attributes {
1176 public ArrayList AttributeSections;
1178 public Attributes (AttributeSection a)
1180 AttributeSections = new ArrayList ();
1181 AttributeSections.Add (a);
1185 public void AddAttributeSection (AttributeSection a)
1187 if (a != null && !AttributeSections.Contains (a))
1188 AttributeSections.Add (a);
1191 public bool Contains (Type t)
1193 foreach (AttributeSection attr_section in AttributeSections){
1194 foreach (Attribute a in attr_section.Attributes){