2 // attribute.cs: Attribute Handler
\r
4 // Author: Ravi Pratap (ravi@ximian.com)
\r
6 // Licensed under the terms of the GNU GPL
\r
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
\r
13 using System.Diagnostics;
\r
14 using System.Collections;
\r
15 using System.Reflection;
\r
16 using System.Reflection.Emit;
\r
17 using System.Runtime.InteropServices;
\r
18 using System.Runtime.CompilerServices;
\r
21 namespace Mono.CSharp {
\r
23 public class Attribute {
\r
24 public readonly string Name;
\r
25 public readonly ArrayList Arguments;
\r
32 // The following are only meaningful when the attribute
\r
33 // being emitted is an AttributeUsage attribute
\r
35 AttributeTargets Targets;
\r
39 bool UsageAttr = false;
\r
41 MethodImplOptions ImplOptions;
\r
42 UnmanagedType UnmanagedType;
\r
43 CustomAttributeBuilder cb;
\r
45 // non-null if named args present after Resolve () is called
\r
46 PropertyInfo [] prop_info_arr;
\r
47 FieldInfo [] field_info_arr;
\r
48 object [] field_values_arr;
\r
49 object [] prop_values_arr;
\r
51 public Attribute (string name, ArrayList args, Location loc)
\r
58 void Error_InvalidNamedArgument (string name)
\r
60 Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
\r
61 "argument. Named attribute arguments must be fields which are not " +
\r
62 "readonly, static or const, or properties with a set accessor which "+
\r
66 static void Error_AttributeArgumentNotValid (Location loc)
\r
68 Report.Error (182, loc,
\r
69 "An attribute argument must be a constant expression, typeof " +
\r
70 "expression or array creation expression");
\r
73 static void Error_AttributeConstructorMismatch (Location loc)
\r
75 Report.Error (-6, loc,
\r
76 "Could not find a constructor for this argument list.");
\r
80 /// Tries to resolve the type of the attribute. Flags an error if it can't.
\r
82 private Type CheckAttributeType (EmitContext ec) {
\r
84 bool isattributeclass = true;
\r
86 t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
\r
88 isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
\r
89 if (isattributeclass)
\r
92 t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
\r
94 if (t.IsSubclassOf (TypeManager.attribute_type))
\r
97 if (!isattributeclass) {
\r
98 Report.Error (616, Location, "'" + Name + "': is not an attribute class");
\r
102 Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
\r
106 246, Location, "Could not find attribute '" + Name + "' (are you" +
\r
107 " missing a using directive or an assembly reference ?)");
\r
111 public Type ResolveType (EmitContext ec)
\r
113 Type = CheckAttributeType (ec);
\r
118 /// Validates the guid string
\r
120 bool ValidateGuid (string guid)
\r
126 Report.Error (647, Location, "Format of GUID is invalid: " + guid);
\r
132 // Given an expression, if the expression is a valid attribute-argument-expression
\r
133 // returns an object that can be used to encode it, or null on failure.
\r
135 public static bool GetAttributeArgumentExpression (Expression e, Location loc, out object result)
\r
137 if (e is Constant) {
\r
138 result = ((Constant) e).GetValue ();
\r
140 } else if (e is TypeOf) {
\r
141 result = ((TypeOf) e).TypeArg;
\r
143 } else if (e is ArrayCreation){
\r
144 result = ((ArrayCreation) e).EncodeAsAttribute ();
\r
145 if (result != null)
\r
147 } else if (e is EmptyCast) {
149 if (((EmptyCast) e).Child is Constant) {
150 result = ((Constant) ((EmptyCast)e).Child).GetValue();
156 Error_AttributeArgumentNotValid (loc);
\r
160 public CustomAttributeBuilder Resolve (EmitContext ec)
\r
163 Type = CheckAttributeType (ec);
\r
167 bool MethodImplAttr = false;
\r
168 bool MarshalAsAttr = false;
\r
169 bool GuidAttr = false;
\r
172 bool DoCompares = true;
\r
175 // If we are a certain special attribute, we
\r
176 // set the information accordingly
\r
179 if (Type == TypeManager.attribute_usage_type)
\r
181 else if (Type == TypeManager.methodimpl_attr_type)
\r
182 MethodImplAttr = true;
\r
183 else if (Type == TypeManager.marshal_as_attr_type)
\r
184 MarshalAsAttr = true;
\r
185 else if (Type == TypeManager.guid_attr_type)
\r
188 DoCompares = false;
\r
190 // Now we extract the positional and named arguments
\r
192 ArrayList pos_args = new ArrayList ();
\r
193 ArrayList named_args = new ArrayList ();
\r
194 int pos_arg_count = 0;
\r
196 if (Arguments != null) {
\r
197 pos_args = (ArrayList) Arguments [0];
\r
198 if (pos_args != null)
\r
199 pos_arg_count = pos_args.Count;
\r
200 if (Arguments.Count > 1)
\r
201 named_args = (ArrayList) Arguments [1];
\r
204 object [] pos_values = new object [pos_arg_count];
\r
207 // First process positional arguments
\r
211 for (i = 0; i < pos_arg_count; i++) {
\r
212 Argument a = (Argument) pos_args [i];
\r
215 if (!a.Resolve (ec, Location))
\r
221 if (!GetAttributeArgumentExpression (e, Location, out val))
\r
224 pos_values [i] = val;
\r
227 this.Targets = (AttributeTargets) pos_values [0];
\r
228 else if (MethodImplAttr)
\r
229 this.ImplOptions = (MethodImplOptions) pos_values [0];
\r
230 else if (GuidAttr){
\r
232 // we will later check the validity of the type
\r
234 if (pos_values [0] is string){
\r
235 if (!ValidateGuid ((string) pos_values [0]))
\r
239 } else if (MarshalAsAttr)
\r
240 this.UnmanagedType =
\r
241 (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
\r
246 // Now process named arguments
\r
249 ArrayList field_infos = null;
\r
250 ArrayList prop_infos = null;
\r
251 ArrayList field_values = null;
\r
252 ArrayList prop_values = null;
\r
254 if (named_args.Count > 0) {
\r
255 field_infos = new ArrayList ();
\r
256 prop_infos = new ArrayList ();
\r
257 field_values = new ArrayList ();
\r
258 prop_values = new ArrayList ();
\r
261 for (i = 0; i < named_args.Count; i++) {
\r
262 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
263 string member_name = (string) de.Key;
\r
264 Argument a = (Argument) de.Value;
\r
267 if (!a.Resolve (ec, Location))
\r
270 Expression member = Expression.MemberLookup (
\r
271 ec, Type, member_name,
\r
272 MemberTypes.Field | MemberTypes.Property,
\r
273 BindingFlags.Public | BindingFlags.Instance,
\r
276 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
\r
277 Error_InvalidNamedArgument (member_name);
\r
282 if (member is PropertyExpr) {
\r
283 PropertyExpr pe = (PropertyExpr) member;
\r
284 PropertyInfo pi = pe.PropertyInfo;
\r
286 if (!pi.CanWrite) {
\r
287 Error_InvalidNamedArgument (member_name);
\r
291 if (e is Constant) {
\r
292 object o = ((Constant) e).GetValue ();
\r
293 prop_values.Add (o);
\r
296 if (member_name == "AllowMultiple")
\r
297 this.AllowMultiple = (bool) o;
\r
298 if (member_name == "Inherited")
\r
299 this.Inherited = (bool) o;
\r
302 } else if (e is TypeOf) {
\r
303 prop_values.Add (((TypeOf) e).TypeArg);
\r
304 } else if (e is ArrayCreation) {
\r
305 prop_values.Add (((ArrayCreation) e).EncodeAsAttribute());
\r
307 Error_AttributeArgumentNotValid (Location);
\r
311 prop_infos.Add (pi);
\r
313 } else if (member is FieldExpr) {
\r
314 FieldExpr fe = (FieldExpr) member;
\r
315 FieldInfo fi = fe.FieldInfo;
\r
317 if (fi.IsInitOnly) {
\r
318 Error_InvalidNamedArgument (member_name);
\r
323 // Handle charset here, and set the TypeAttributes
\r
325 if (e is Constant){
\r
326 object value = ((Constant) e).GetValue ();
\r
328 field_values.Add (value);
\r
329 } else if (e is TypeOf) {
\r
330 field_values.Add (((TypeOf) e).TypeArg);
\r
332 Error_AttributeArgumentNotValid (Location);
\r
336 field_infos.Add (fi);
\r
340 Expression mg = Expression.MemberLookup (
\r
341 ec, Type, ".ctor", MemberTypes.Constructor,
\r
342 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
\r
346 Error_AttributeConstructorMismatch (Location);
\r
350 MethodBase constructor = Invocation.OverloadResolve (
\r
351 ec, (MethodGroupExpr) mg, pos_args, Location);
\r
353 if (constructor == null) {
\r
354 Error_AttributeConstructorMismatch (Location);
\r
359 // Now we perform some checks on the positional args as they
\r
360 // cannot be null for a constructor which expects a parameter
\r
364 ParameterData pd = Invocation.GetParameterData (constructor);
\r
366 int group_in_params_array = Int32.MaxValue;
\r
368 if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
\r
369 group_in_params_array = pc-1;
\r
371 for (int j = 0; j < pos_arg_count; ++j) {
\r
372 Argument a = (Argument) pos_args [j];
\r
374 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
\r
375 Error_AttributeArgumentNotValid (Location);
\r
379 if (j < group_in_params_array)
\r
382 if (j == group_in_params_array){
\r
383 object v = pos_values [j];
\r
384 int count = pos_arg_count - j;
\r
386 object [] array = new object [count];
\r
387 pos_values [j] = array;
\r
390 object [] array = (object []) pos_values [group_in_params_array];
\r
392 array [j - group_in_params_array] = pos_values [j];
\r
397 // Adjust the size of the pos_values if it had params
\r
399 if (group_in_params_array != Int32.MaxValue){
\r
400 int argc = group_in_params_array+1;
\r
401 object [] new_pos_values = new object [argc];
\r
403 for (int p = 0; p < argc; p++)
\r
404 new_pos_values [p] = pos_values [p];
\r
405 pos_values = new_pos_values;
\r
409 if (named_args.Count > 0) {
\r
410 prop_info_arr = new PropertyInfo [prop_infos.Count];
\r
411 field_info_arr = new FieldInfo [field_infos.Count];
\r
412 field_values_arr = new object [field_values.Count];
\r
413 prop_values_arr = new object [prop_values.Count];
\r
415 field_infos.CopyTo (field_info_arr, 0);
\r
416 field_values.CopyTo (field_values_arr, 0);
\r
418 prop_values.CopyTo (prop_values_arr, 0);
\r
419 prop_infos.CopyTo (prop_info_arr, 0);
\r
421 cb = new CustomAttributeBuilder (
\r
422 (ConstructorInfo) constructor, pos_values,
\r
423 prop_info_arr, prop_values_arr,
\r
424 field_info_arr, field_values_arr);
\r
427 cb = new CustomAttributeBuilder (
\r
428 (ConstructorInfo) constructor, pos_values);
\r
429 } catch (NullReferenceException) {
\r
431 // Don't know what to do here
\r
434 -101, Location, "NullReferenceException while trying to create attribute." +
\r
435 "Something's wrong!");
\r
436 } catch (Exception e) {
\r
439 // using System.ComponentModel;
\r
440 // [DefaultValue (CollectionChangeAction.Add)]
\r
441 // class X { static void Main () {} }
\r
445 "The compiler can not encode this attribute in .NET due to\n" +
\r
446 "\ta bug in the .NET runtime. Try the Mono runtime.\nThe error was: " + e.Message);
\r
453 /// Get a string containing a list of valid targets for the attribute 'attr'
\r
455 static string GetValidTargets (Attribute attr)
\r
457 StringBuilder sb = new StringBuilder ();
\r
458 AttributeTargets targets = 0;
\r
460 TypeContainer a = TypeManager.LookupAttr (attr.Type);
\r
464 System.Attribute [] attrs = null;
\r
467 attrs = System.Attribute.GetCustomAttributes (attr.Type);
\r
470 Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
\r
471 " (maybe you forgot to set the usage using the" +
\r
472 " AttributeUsage attribute ?).");
\r
476 foreach (System.Attribute tmp in attrs)
\r
477 if (tmp is AttributeUsageAttribute) {
\r
478 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
482 targets = a.Targets;
\r
485 if ((targets & AttributeTargets.Assembly) != 0)
\r
486 sb.Append ("'assembly' ");
\r
488 if ((targets & AttributeTargets.Class) != 0)
\r
489 sb.Append ("'class' ");
\r
491 if ((targets & AttributeTargets.Constructor) != 0)
\r
492 sb.Append ("'constructor' ");
\r
494 if ((targets & AttributeTargets.Delegate) != 0)
\r
495 sb.Append ("'delegate' ");
\r
497 if ((targets & AttributeTargets.Enum) != 0)
\r
498 sb.Append ("'enum' ");
\r
500 if ((targets & AttributeTargets.Event) != 0)
\r
501 sb.Append ("'event' ");
\r
503 if ((targets & AttributeTargets.Field) != 0)
\r
504 sb.Append ("'field' ");
\r
506 if ((targets & AttributeTargets.Interface) != 0)
\r
507 sb.Append ("'interface' ");
\r
509 if ((targets & AttributeTargets.Method) != 0)
\r
510 sb.Append ("'method' ");
\r
512 if ((targets & AttributeTargets.Module) != 0)
\r
513 sb.Append ("'module' ");
\r
515 if ((targets & AttributeTargets.Parameter) != 0)
\r
516 sb.Append ("'parameter' ");
\r
518 if ((targets & AttributeTargets.Property) != 0)
\r
519 sb.Append ("'property' ");
\r
521 if ((targets & AttributeTargets.ReturnValue) != 0)
\r
522 sb.Append ("'return value' ");
\r
524 if ((targets & AttributeTargets.Struct) != 0)
\r
525 sb.Append ("'struct' ");
\r
527 return sb.ToString ();
\r
531 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
\r
534 592, loc, "Attribute '" + a.Name +
\r
535 "' is not valid on this declaration type. " +
\r
536 "It is valid on " + GetValidTargets (a) + "declarations only.");
\r
540 /// Ensure that Attribute 'a' is being applied to the right language element (target)
\r
542 public static bool CheckAttributeTarget (Attribute a, object element)
\r
544 TypeContainer attr = TypeManager.LookupAttr (a.Type);
\r
545 AttributeTargets targets = 0;
\r
547 if (attr == null) {
\r
548 System.Attribute [] attrs = null;
\r
551 attrs = System.Attribute.GetCustomAttributes (a.Type);
\r
554 Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
\r
555 " (maybe you forgot to set the usage using the" +
\r
556 " AttributeUsage attribute ?).");
\r
560 foreach (System.Attribute tmp in attrs)
\r
561 if (tmp is AttributeUsageAttribute) {
\r
562 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
566 targets = attr.Targets;
\r
569 if (element is Class) {
\r
570 if ((targets & AttributeTargets.Class) != 0)
\r
575 } else if (element is Struct) {
\r
576 if ((targets & AttributeTargets.Struct) != 0)
\r
580 } else if (element is Constructor) {
\r
581 if ((targets & AttributeTargets.Constructor) != 0)
\r
585 } else if (element is Delegate) {
\r
586 if ((targets & AttributeTargets.Delegate) != 0)
\r
590 } else if (element is Enum) {
\r
591 if ((targets & AttributeTargets.Enum) != 0)
\r
595 } else if (element is Event || element is InterfaceEvent) {
\r
596 if ((targets & AttributeTargets.Event) != 0)
\r
600 } else if (element is Field || element is FieldBuilder) {
\r
601 if ((targets & AttributeTargets.Field) != 0)
\r
605 } else if (element is Interface) {
\r
606 if ((targets & AttributeTargets.Interface) != 0)
\r
610 } else if (element is Method || element is Operator ||
\r
611 element is InterfaceMethod || element is Accessor) {
\r
612 if ((targets & AttributeTargets.Method) != 0)
\r
616 } else if (element is ParameterBuilder) {
\r
617 if ((targets & AttributeTargets.Parameter) != 0 ||
\r
618 (targets & AttributeTargets.ReturnValue) != 0)
\r
622 } else if (element is Property || element is Indexer ||
\r
623 element is InterfaceProperty || element is InterfaceIndexer) {
\r
624 if ((targets & AttributeTargets.Property) != 0)
\r
628 } else if (element is AssemblyBuilder){
\r
629 if ((targets & AttributeTargets.Assembly) != 0)
\r
639 // This method should be invoked to pull the IndexerName attribute from an
\r
640 // Indexer if it exists.
\r
642 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
\r
644 if (opt_attrs == null)
\r
646 if (opt_attrs.AttributeSections == null)
\r
649 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
650 if (asec.Attributes == null)
\r
653 foreach (Attribute a in asec.Attributes){
\r
654 if (a.ResolveType (ec) == null)
\r
657 if (a.Type != TypeManager.indexer_name_type)
\r
661 // So we have found an IndexerName, pull the data out.
\r
663 if (a.Arguments == null || a.Arguments [0] == null){
\r
664 Error_AttributeConstructorMismatch (a.Location);
\r
667 ArrayList pos_args = (ArrayList) a.Arguments [0];
\r
668 if (pos_args.Count == 0){
\r
669 Error_AttributeConstructorMismatch (a.Location);
\r
673 Argument arg = (Argument) pos_args [0];
\r
674 if (!arg.Resolve (ec, a.Location))
\r
677 Expression e = arg.Expr;
\r
678 if (!(e is StringConstant)){
\r
679 Error_AttributeConstructorMismatch (a.Location);
\r
684 // Remove the attribute from the list
\r
686 asec.Attributes.Remove (a);
\r
688 return (((StringConstant) e).Value);
\r
695 // This pulls the condition name out of a Conditional attribute
\r
697 public string Conditional_GetConditionName ()
\r
700 // So we have a Conditional, pull the data out.
\r
702 if (Arguments == null || Arguments [0] == null){
\r
703 Error_AttributeConstructorMismatch (Location);
\r
707 ArrayList pos_args = (ArrayList) Arguments [0];
\r
708 if (pos_args.Count != 1){
\r
709 Error_AttributeConstructorMismatch (Location);
\r
713 Argument arg = (Argument) pos_args [0];
\r
714 if (!(arg.Expr is StringConstant)){
\r
715 Error_AttributeConstructorMismatch (Location);
\r
719 return ((StringConstant) arg.Expr).Value;
\r
723 // This pulls the obsolete message and error flag out of an Obsolete attribute
\r
725 public string Obsolete_GetObsoleteMessage (out bool is_error)
\r
729 // So we have an Obsolete, pull the data out.
\r
731 if (Arguments == null || Arguments [0] == null)
\r
734 ArrayList pos_args = (ArrayList) Arguments [0];
\r
735 if (pos_args.Count == 0)
\r
737 else if (pos_args.Count > 2){
\r
738 Error_AttributeConstructorMismatch (Location);
\r
742 Argument arg = (Argument) pos_args [0];
\r
743 if (!(arg.Expr is StringConstant)){
\r
744 Error_AttributeConstructorMismatch (Location);
\r
748 if (pos_args.Count == 2){
\r
749 Argument arg2 = (Argument) pos_args [1];
\r
750 if (!(arg2.Expr is BoolConstant)){
\r
751 Error_AttributeConstructorMismatch (Location);
\r
754 is_error = ((BoolConstant) arg2.Expr).Value;
\r
757 return ((StringConstant) arg.Expr).Value;
\r
760 static object GetFieldValue (Attribute a, string name)
\r
763 if (a.field_info_arr == null)
\r
766 foreach (FieldInfo fi in a.field_info_arr) {
\r
767 if (fi.Name == name)
\r
768 return a.field_values_arr [i];
\r
774 static UnmanagedMarshal GetMarshal (Attribute a)
\r
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'.
\r
813 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
\r
814 Attributes opt_attrs)
\r
816 Type attr_type = null;
\r
818 if (opt_attrs == null)
\r
820 if (opt_attrs.AttributeSections == null)
\r
823 ArrayList emitted_attrs = new ArrayList ();
\r
824 ArrayList emitted_targets = new ArrayList ();
\r
826 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
827 string attr_target = asec.Target;
\r
829 if (asec.Attributes == null)
\r
832 if (attr_target == "assembly" && !(builder is AssemblyBuilder))
\r
835 if (attr_target == "return" && !(builder is ParameterBuilder))
\r
838 foreach (Attribute a in asec.Attributes) {
\r
839 Location loc = a.Location;
\r
840 CustomAttributeBuilder cb = a.Resolve (ec);
\r
841 attr_type = a.Type;
\r
846 if (!(kind is TypeContainer))
\r
847 if (!CheckAttributeTarget (a, kind)) {
\r
848 Error_AttributeNotValidForElement (a, loc);
\r
853 // Perform the check for duplicate attributes
\r
855 if (emitted_attrs.Contains (attr_type) &&
\r
856 emitted_targets.Contains (attr_target) &&
\r
857 !TypeManager.AreMultipleAllowed (attr_type)) {
\r
858 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
\r
862 if (kind is Method || kind is Operator || kind is InterfaceMethod ||
\r
863 kind is Accessor) {
\r
864 if (attr_type == TypeManager.methodimpl_attr_type) {
\r
865 if (a.ImplOptions == MethodImplOptions.InternalCall)
\r
866 ((MethodBuilder) builder).
\r
867 SetImplementationFlags (
\r
868 MethodImplAttributes.InternalCall |
\r
869 MethodImplAttributes.Runtime);
\r
871 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
872 } else if (attr_type != TypeManager.dllimport_type){
\r
873 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
875 } else if (kind is Constructor) {
\r
876 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
\r
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 ||
\r
891 kind is InterfaceProperty || kind is InterfaceIndexer) {
\r
892 ((PropertyBuilder) builder).SetCustomAttribute (cb);
\r
893 } else if (kind is Event || kind is InterfaceEvent) {
\r
894 ((MyEventBuilder) builder).SetCustomAttribute (cb);
\r
895 } else if (kind is ParameterBuilder) {
\r
897 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
898 UnmanagedMarshal marshal = GetMarshal (a);
\r
899 if (marshal == null) {
\r
900 Report.Warning (-24, loc,
\r
901 "The Microsoft Runtime cannot set this marshal info. " +
\r
902 "Please use the Mono runtime instead.");
\r
904 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
909 ((ParameterBuilder) builder).SetCustomAttribute (cb);
\r
910 } catch (System.ArgumentException) {
\r
911 Report.Warning (-24, loc,
\r
912 "The Microsoft Runtime cannot set attributes \n" +
\r
913 "on the return type of a method. Please use the \n" +
\r
914 "Mono runtime instead.");
\r
918 } else if (kind is Enum) {
\r
919 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
921 } else if (kind is TypeContainer) {
\r
922 TypeContainer tc = (TypeContainer) kind;
\r
925 tc.Targets = a.Targets;
\r
926 tc.AllowMultiple = a.AllowMultiple;
\r
927 tc.Inherited = a.Inherited;
\r
929 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
\r
932 } else if (attr_type == TypeManager.default_member_type) {
\r
933 if (tc.Indexers != null) {
\r
934 Report.Error (646, loc,
\r
935 "Cannot specify the DefaultMember attribute on" +
\r
936 " a type containing an indexer");
\r
941 if (!CheckAttributeTarget (a, kind)) {
\r
942 Error_AttributeNotValidForElement (a, loc);
\r
948 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
949 } catch (System.ArgumentException) {
\r
952 "The CharSet named property on StructLayout\n"+
\r
953 "\tdoes not work correctly on Microsoft.NET\n"+
\r
954 "\tYou might want to remove the CharSet declaration\n"+
\r
955 "\tor compile using the Mono runtime instead of the\n"+
\r
956 "\tMicrosoft .NET runtime");
\r
958 } else if (kind is Delegate){
\r
959 if (!CheckAttributeTarget (a, kind)) {
\r
960 Error_AttributeNotValidForElement (a, loc);
\r
964 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
965 } catch (System.ArgumentException) {
\r
968 "The CharSet named property on StructLayout\n"+
\r
969 "\tdoes not work correctly on Microsoft.NET\n"+
\r
970 "\tYou might want to remove the CharSet declaration\n"+
\r
971 "\tor compile using the Mono runtime instead of the\n"+
\r
972 "\tMicrosoft .NET runtime");
\r
974 } else if (kind is Interface) {
\r
975 Interface iface = (Interface) kind;
\r
977 if ((attr_type == TypeManager.default_member_type) &&
\r
978 (iface.InterfaceIndexers != null)) {
\r
981 "Cannot specify the DefaultMember attribute on" +
\r
982 " a type containing an indexer");
\r
986 if (!CheckAttributeTarget (a, kind)) {
\r
987 Error_AttributeNotValidForElement (a, loc);
\r
991 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
992 } else if (kind is AssemblyBuilder){
\r
993 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
\r
994 } else if (kind is ModuleBuilder) {
\r
995 ((ModuleBuilder) builder).SetCustomAttribute (cb);
\r
996 } else if (kind is FieldBuilder) {
\r
997 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
998 UnmanagedMarshal marshal = GetMarshal (a);
\r
999 if (marshal == null) {
\r
1000 Report.Warning (-24, loc,
\r
1001 "The Microsoft Runtime cannot set this marshal info. " +
\r
1002 "Please use the Mono runtime instead.");
\r
1004 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
1007 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
1010 throw new Exception ("Unknown kind: " + kind);
\r
1013 // Once an attribute type has been emitted once we
\r
1014 // keep track of the info to prevent multiple occurences
\r
1015 // for attributes which do not explicitly allow it
\r
1017 if (!emitted_attrs.Contains (attr_type))
\r
1018 emitted_attrs.Add (attr_type);
\r
1021 // We keep of this target-wise and so emitted targets
\r
1022 // are tracked too
\r
1024 if (!emitted_targets.Contains (attr_target))
\r
1025 emitted_targets.Add (attr_target);
\r
1032 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
\r
1033 MethodAttributes flags, Type ret_type, Type [] param_types)
\r
1036 // We extract from the attribute the information we need
\r
1039 if (Arguments == null) {
\r
1040 Console.WriteLine ("Internal error : this is not supposed to happen !");
\r
1044 Type = CheckAttributeType (ec);
\r
1048 ArrayList named_args = new ArrayList ();
\r
1050 ArrayList pos_args = (ArrayList) Arguments [0];
\r
1051 if (Arguments.Count > 1)
\r
1052 named_args = (ArrayList) Arguments [1];
\r
1055 string dll_name = null;
\r
1057 Argument tmp = (Argument) pos_args [0];
\r
1059 if (!tmp.Resolve (ec, Location))
\r
1062 if (tmp.Expr is Constant)
\r
1063 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
\r
1065 Error_AttributeArgumentNotValid (Location);
\r
1069 // Now we process the named arguments
\r
1070 CallingConvention cc = CallingConvention.Winapi;
\r
1071 CharSet charset = CharSet.Ansi;
\r
1072 bool preserve_sig = true;
\r
1074 bool exact_spelling = false;
\r
1076 bool set_last_err = false;
\r
1077 string entry_point = null;
\r
1079 for (int i = 0; i < named_args.Count; i++) {
\r
1081 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
1083 string member_name = (string) de.Key;
\r
1084 Argument a = (Argument) de.Value;
\r
1086 if (!a.Resolve (ec, Location))
\r
1089 Expression member = Expression.MemberLookup (
\r
1090 ec, Type, member_name,
\r
1091 MemberTypes.Field | MemberTypes.Property,
\r
1092 BindingFlags.Public | BindingFlags.Instance,
\r
1095 if (member == null || !(member is FieldExpr)) {
\r
1096 Error_InvalidNamedArgument (member_name);
\r
1100 if (member is FieldExpr) {
\r
1101 FieldExpr fe = (FieldExpr) member;
\r
1102 FieldInfo fi = fe.FieldInfo;
\r
1104 if (fi.IsInitOnly) {
\r
1105 Error_InvalidNamedArgument (member_name);
\r
1109 if (a.Expr is Constant) {
\r
1110 Constant c = (Constant) a.Expr;
\r
1112 if (member_name == "CallingConvention")
\r
1113 cc = (CallingConvention) c.GetValue ();
\r
1114 else if (member_name == "CharSet")
\r
1115 charset = (CharSet) c.GetValue ();
\r
1116 else if (member_name == "EntryPoint")
\r
1117 entry_point = (string) c.GetValue ();
\r
1118 else if (member_name == "SetLastError")
\r
1119 set_last_err = (bool) c.GetValue ();
\r
1121 else if (member_name == "ExactSpelling")
\r
1122 exact_spelling = (bool) c.GetValue ();
\r
1124 else if (member_name == "PreserveSig")
\r
1125 preserve_sig = (bool) c.GetValue ();
\r
1127 Error_AttributeArgumentNotValid (Location);
\r
1134 if (entry_point == null)
\r
1135 entry_point = name;
\r
1137 charset = (CharSet)((int)charset | 0x40);
\r
1139 MethodBuilder mb = builder.DefinePInvokeMethod (
\r
1140 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
\r
1141 CallingConventions.Standard,
\r
1148 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
\r
1155 public class AttributeSection {
\r
1156 public readonly string Target;
\r
1157 public readonly ArrayList Attributes;
\r
1159 public AttributeSection (string target, ArrayList attrs)
\r
1162 Attributes = attrs;
\r
1167 public class Attributes {
\r
1168 public ArrayList AttributeSections;
\r
1170 public Attributes (AttributeSection a)
\r
1172 AttributeSections = new ArrayList ();
\r
1173 AttributeSections.Add (a);
\r
1177 public void AddAttributeSection (AttributeSection a)
\r
1179 if (a != null && !AttributeSections.Contains (a))
\r
1180 AttributeSections.Add (a);
\r
1183 public bool Contains (Type t)
\r
1185 foreach (AttributeSection attr_section in AttributeSections){
\r
1186 foreach (Attribute a in attr_section.Attributes){
\r