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 one of the builtin ones
\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
79 static void Error_TypeParameterInAttribute (Location loc)
\r
82 -202, loc, "Can not use a type parameter in an attribute");
\r
85 private Type CheckAttributeType (EmitContext ec) {
\r
87 bool isattributeclass = true;
\r
89 t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
\r
91 isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
\r
92 if (isattributeclass)
\r
95 t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
\r
97 if (t.IsSubclassOf (TypeManager.attribute_type))
\r
100 if (!isattributeclass) {
\r
101 Report.Error (616, Location, "'" + Name + "': is not an attribute class");
\r
105 Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
\r
109 246, Location, "Could not find attribute '" + Name + "' (are you" +
\r
110 " missing a using directive or an assembly reference ?)");
\r
114 public Type ResolveType (EmitContext ec)
\r
116 Type = CheckAttributeType (ec);
\r
121 /// Validates the guid string
\r
123 bool ValidateGuid (string guid)
\r
129 Report.Error (647, Location, "Format of GUID is invalid: " + guid);
\r
135 // Given an expression, if the expression is a valid attribute-argument-expression
\r
136 // returns an object that can be used to encode it, or null on failure.
\r
138 public static bool GetAttributeArgumentExpression (Expression e, Location loc, out object result)
\r
140 if (e is Constant) {
\r
141 result = ((Constant) e).GetValue ();
\r
143 } else if (e is TypeOf) {
\r
144 result = ((TypeOf) e).TypeArg;
\r
146 } else if (e is ArrayCreation){
\r
147 result = ((ArrayCreation) e).EncodeAsAttribute ();
\r
148 if (result != null)
\r
153 Error_AttributeArgumentNotValid (loc);
\r
157 public CustomAttributeBuilder Resolve (EmitContext ec)
\r
160 Type = CheckAttributeType (ec);
\r
164 bool MethodImplAttr = false;
\r
165 bool MarshalAsAttr = false;
\r
166 bool GuidAttr = false;
\r
169 bool DoCompares = true;
\r
170 if (Type == TypeManager.attribute_usage_type)
\r
172 else if (Type == TypeManager.methodimpl_attr_type)
\r
173 MethodImplAttr = true;
\r
174 else if (Type == TypeManager.marshal_as_attr_type)
\r
175 MarshalAsAttr = true;
\r
176 else if (Type == TypeManager.guid_attr_type)
\r
179 DoCompares = false;
\r
181 // Now we extract the positional and named arguments
\r
183 ArrayList pos_args = new ArrayList ();
\r
184 ArrayList named_args = new ArrayList ();
\r
185 int pos_arg_count = 0;
\r
187 if (Arguments != null) {
\r
188 pos_args = (ArrayList) Arguments [0];
\r
189 if (pos_args != null)
\r
190 pos_arg_count = pos_args.Count;
\r
191 if (Arguments.Count > 1)
\r
192 named_args = (ArrayList) Arguments [1];
\r
195 object [] pos_values = new object [pos_arg_count];
\r
198 // First process positional arguments
\r
202 for (i = 0; i < pos_arg_count; i++) {
\r
203 Argument a = (Argument) pos_args [i];
\r
206 if (!a.Resolve (ec, Location))
\r
212 if (!GetAttributeArgumentExpression (e, Location, out val))
\r
215 pos_values [i] = val;
\r
218 this.Targets = (AttributeTargets) pos_values [0];
\r
219 else if (MethodImplAttr)
\r
220 this.ImplOptions = (MethodImplOptions) pos_values [0];
\r
221 else if (GuidAttr){
\r
223 // we will later check the validity of the type
\r
225 if (pos_values [0] is string){
\r
226 if (!ValidateGuid ((string) pos_values [0]))
\r
230 } else if (MarshalAsAttr)
\r
231 this.UnmanagedType =
\r
232 (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
\r
237 // Now process named arguments
\r
240 ArrayList field_infos = null;
\r
241 ArrayList prop_infos = null;
\r
242 ArrayList field_values = null;
\r
243 ArrayList prop_values = null;
\r
245 if (named_args.Count > 0) {
\r
246 field_infos = new ArrayList ();
\r
247 prop_infos = new ArrayList ();
\r
248 field_values = new ArrayList ();
\r
249 prop_values = new ArrayList ();
\r
252 for (i = 0; i < named_args.Count; i++) {
\r
253 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
254 string member_name = (string) de.Key;
\r
255 Argument a = (Argument) de.Value;
\r
258 if (!a.Resolve (ec, Location))
\r
261 Expression member = Expression.MemberLookup (
\r
262 ec, Type, member_name,
\r
263 MemberTypes.Field | MemberTypes.Property,
\r
264 BindingFlags.Public | BindingFlags.Instance,
\r
267 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
\r
268 Error_InvalidNamedArgument (member_name);
\r
273 if (e is TypeParameterExpr){
\r
274 Error_TypeParameterInAttribute (Location);
\r
278 if (member is PropertyExpr) {
\r
279 PropertyExpr pe = (PropertyExpr) member;
\r
280 PropertyInfo pi = pe.PropertyInfo;
\r
282 if (!pi.CanWrite) {
\r
283 Error_InvalidNamedArgument (member_name);
\r
287 if (e is Constant) {
\r
288 object o = ((Constant) e).GetValue ();
\r
289 prop_values.Add (o);
\r
292 if (member_name == "AllowMultiple")
\r
293 this.AllowMultiple = (bool) o;
\r
294 if (member_name == "Inherited")
\r
295 this.Inherited = (bool) o;
\r
298 } else if (e is TypeOf) {
\r
299 prop_values.Add (((TypeOf) e).TypeArg);
\r
301 Error_AttributeArgumentNotValid (Location);
\r
305 prop_infos.Add (pi);
\r
307 } else if (member is FieldExpr) {
\r
308 FieldExpr fe = (FieldExpr) member;
\r
309 FieldInfo fi = fe.FieldInfo;
\r
311 if (fi.IsInitOnly) {
\r
312 Error_InvalidNamedArgument (member_name);
\r
317 // Handle charset here, and set the TypeAttributes
\r
319 if (e is Constant){
\r
320 object value = ((Constant) e).GetValue ();
\r
322 field_values.Add (value);
\r
323 } else if (e is TypeOf) {
\r
324 field_values.Add (((TypeOf) e).TypeArg);
\r
326 Error_AttributeArgumentNotValid (Location);
\r
330 field_infos.Add (fi);
\r
334 Expression mg = Expression.MemberLookup (
\r
335 ec, Type, ".ctor", MemberTypes.Constructor,
\r
336 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
\r
340 Error_AttributeConstructorMismatch (Location);
\r
344 MethodBase constructor = Invocation.OverloadResolve (
\r
345 ec, (MethodGroupExpr) mg, pos_args, Location);
\r
347 if (constructor == null) {
\r
348 Error_AttributeConstructorMismatch (Location);
\r
353 // Now we perform some checks on the positional args as they
\r
354 // cannot be null for a constructor which expects a parameter
\r
358 ParameterData pd = Invocation.GetParameterData (constructor);
\r
360 int group_in_params_array = Int32.MaxValue;
\r
362 if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
\r
363 group_in_params_array = pc-1;
\r
365 for (int j = 0; j < pos_arg_count; ++j) {
\r
366 Argument a = (Argument) pos_args [j];
\r
368 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
\r
369 Error_AttributeArgumentNotValid (Location);
\r
373 if (j < group_in_params_array)
\r
376 if (j == group_in_params_array){
\r
377 object v = pos_values [j];
\r
378 int count = pos_arg_count - j;
\r
380 object [] array = new object [count];
\r
381 pos_values [j] = array;
\r
384 object [] array = (object []) pos_values [group_in_params_array];
\r
386 array [j - group_in_params_array] = pos_values [j];
\r
391 // Adjust the size of the pos_values if it had params
\r
393 if (group_in_params_array != Int32.MaxValue){
\r
394 int argc = group_in_params_array+1;
\r
395 object [] new_pos_values = new object [argc];
\r
397 for (int p = 0; p < argc; p++)
\r
398 new_pos_values [p] = pos_values [p];
\r
399 pos_values = new_pos_values;
\r
403 if (named_args.Count > 0) {
\r
404 prop_info_arr = new PropertyInfo [prop_infos.Count];
\r
405 field_info_arr = new FieldInfo [field_infos.Count];
\r
406 field_values_arr = new object [field_values.Count];
\r
407 prop_values_arr = new object [prop_values.Count];
\r
409 field_infos.CopyTo (field_info_arr, 0);
\r
410 field_values.CopyTo (field_values_arr, 0);
\r
412 prop_values.CopyTo (prop_values_arr, 0);
\r
413 prop_infos.CopyTo (prop_info_arr, 0);
\r
415 cb = new CustomAttributeBuilder (
\r
416 (ConstructorInfo) constructor, pos_values,
\r
417 prop_info_arr, prop_values_arr,
\r
418 field_info_arr, field_values_arr);
\r
421 cb = new CustomAttributeBuilder (
\r
422 (ConstructorInfo) constructor, pos_values);
\r
423 } catch (NullReferenceException) {
\r
425 // Don't know what to do here
\r
428 -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!");
\r
429 } catch (Exception e) {
\r
432 // using System.ComponentModel;
\r
433 // [DefaultValue (CollectionChangeAction.Add)]
\r
434 // class X { static void Main () {} }
\r
438 "The compiler can not encode this attribute in .NET due to\n" +
\r
439 "\ta bug in the .NET runtime. Try the Mono runtime.\nThe error was: " + e.Message);
\r
445 static string GetValidPlaces (Attribute attr)
\r
447 StringBuilder sb = new StringBuilder ();
\r
448 AttributeTargets targets = 0;
\r
450 TypeContainer a = TypeManager.LookupAttr (attr.Type);
\r
454 System.Attribute [] attrs = null;
\r
457 attrs = System.Attribute.GetCustomAttributes (attr.Type);
\r
460 Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
\r
461 " (maybe you forgot to set the usage using the" +
\r
462 " AttributeUsage attribute ?).");
\r
466 foreach (System.Attribute tmp in attrs)
\r
467 if (tmp is AttributeUsageAttribute) {
\r
468 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
472 targets = a.Targets;
\r
475 if ((targets & AttributeTargets.Assembly) != 0)
\r
476 sb.Append ("'assembly' ");
\r
478 if ((targets & AttributeTargets.Class) != 0)
\r
479 sb.Append ("'class' ");
\r
481 if ((targets & AttributeTargets.Constructor) != 0)
\r
482 sb.Append ("'constructor' ");
\r
484 if ((targets & AttributeTargets.Delegate) != 0)
\r
485 sb.Append ("'delegate' ");
\r
487 if ((targets & AttributeTargets.Enum) != 0)
\r
488 sb.Append ("'enum' ");
\r
490 if ((targets & AttributeTargets.Event) != 0)
\r
491 sb.Append ("'event' ");
\r
493 if ((targets & AttributeTargets.Field) != 0)
\r
494 sb.Append ("'field' ");
\r
496 if ((targets & AttributeTargets.Interface) != 0)
\r
497 sb.Append ("'interface' ");
\r
499 if ((targets & AttributeTargets.Method) != 0)
\r
500 sb.Append ("'method' ");
\r
502 if ((targets & AttributeTargets.Module) != 0)
\r
503 sb.Append ("'module' ");
\r
505 if ((targets & AttributeTargets.Parameter) != 0)
\r
506 sb.Append ("'parameter' ");
\r
508 if ((targets & AttributeTargets.Property) != 0)
\r
509 sb.Append ("'property' ");
\r
511 if ((targets & AttributeTargets.ReturnValue) != 0)
\r
512 sb.Append ("'return value' ");
\r
514 if ((targets & AttributeTargets.Struct) != 0)
\r
515 sb.Append ("'struct' ");
\r
517 return sb.ToString ();
\r
521 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
\r
524 592, loc, "Attribute '" + a.Name +
\r
525 "' is not valid on this declaration type. " +
\r
526 "It is valid on " + GetValidPlaces (a) + "declarations only.");
\r
529 public static bool CheckAttribute (Attribute a, object element)
\r
531 TypeContainer attr = TypeManager.LookupAttr (a.Type);
\r
532 AttributeTargets targets = 0;
\r
535 if (attr == null) {
\r
536 System.Attribute [] attrs = null;
\r
539 attrs = System.Attribute.GetCustomAttributes (a.Type);
\r
542 Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
\r
543 " (maybe you forgot to set the usage using the" +
\r
544 " AttributeUsage attribute ?).");
\r
548 foreach (System.Attribute tmp in attrs)
\r
549 if (tmp is AttributeUsageAttribute)
\r
550 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
552 targets = attr.Targets;
\r
554 if (element is Class) {
\r
555 if ((targets & AttributeTargets.Class) != 0)
\r
560 } else if (element is Struct) {
\r
561 if ((targets & AttributeTargets.Struct) != 0)
\r
565 } else if (element is Constructor) {
\r
566 if ((targets & AttributeTargets.Constructor) != 0)
\r
570 } else if (element is Delegate) {
\r
571 if ((targets & AttributeTargets.Delegate) != 0)
\r
575 } else if (element is Enum) {
\r
576 if ((targets & AttributeTargets.Enum) != 0)
\r
580 } else if (element is Event || element is InterfaceEvent) {
\r
581 if ((targets & AttributeTargets.Event) != 0)
\r
585 } else if (element is Field || element is FieldBuilder) {
\r
586 if ((targets & AttributeTargets.Field) != 0)
\r
590 } else if (element is Interface) {
\r
591 if ((targets & AttributeTargets.Interface) != 0)
\r
595 } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {
\r
596 if ((targets & AttributeTargets.Method) != 0)
\r
600 } else if (element is ParameterBuilder) {
\r
601 if ((targets & AttributeTargets.Parameter) != 0)
\r
605 } else if (element is Property || element is Indexer ||
\r
606 element is InterfaceProperty || element is InterfaceIndexer) {
\r
607 if ((targets & AttributeTargets.Property) != 0)
\r
611 } else if (element is AssemblyBuilder){
\r
612 if ((targets & AttributeTargets.Assembly) != 0)
\r
622 // This method should be invoked to pull the IndexerName attribute from an
\r
623 // Indexer if it exists.
\r
625 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
\r
627 if (opt_attrs == null)
\r
629 if (opt_attrs.AttributeSections == null)
\r
632 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
633 if (asec.Attributes == null)
\r
636 foreach (Attribute a in asec.Attributes){
\r
637 if (a.ResolveType (ec) == null)
\r
640 if (a.Type != TypeManager.indexer_name_type)
\r
644 // So we have found an IndexerName, pull the data out.
\r
646 if (a.Arguments == null || a.Arguments [0] == null){
\r
647 Error_AttributeConstructorMismatch (a.Location);
\r
650 ArrayList pos_args = (ArrayList) a.Arguments [0];
\r
651 if (pos_args.Count == 0){
\r
652 Error_AttributeConstructorMismatch (a.Location);
\r
656 Argument arg = (Argument) pos_args [0];
\r
657 if (!arg.Resolve (ec, a.Location))
\r
660 Expression e = arg.Expr;
\r
661 if (!(e is StringConstant)){
\r
662 Error_AttributeConstructorMismatch (a.Location);
\r
667 // Remove the attribute from the list
\r
669 asec.Attributes.Remove (a);
\r
671 return (((StringConstant) e).Value);
\r
678 // This pulls the condition name out of a Conditional attribute
\r
680 public string Conditional_GetConditionName ()
\r
683 // So we have a Conditional, pull the data out.
\r
685 if (Arguments == null || Arguments [0] == null){
\r
686 Error_AttributeConstructorMismatch (Location);
\r
690 ArrayList pos_args = (ArrayList) Arguments [0];
\r
691 if (pos_args.Count != 1){
\r
692 Error_AttributeConstructorMismatch (Location);
\r
696 Argument arg = (Argument) pos_args [0];
\r
697 if (!(arg.Expr is StringConstant)){
\r
698 Error_AttributeConstructorMismatch (Location);
\r
702 return ((StringConstant) arg.Expr).Value;
\r
706 // This pulls the obsolete message and error flag out of an Obsolete attribute
\r
708 public string Obsolete_GetObsoleteMessage (out bool is_error)
\r
712 // So we have an Obsolete, pull the data out.
\r
714 if (Arguments == null || Arguments [0] == null)
\r
717 ArrayList pos_args = (ArrayList) Arguments [0];
\r
718 if (pos_args.Count == 0)
\r
720 else if (pos_args.Count > 2){
\r
721 Error_AttributeConstructorMismatch (Location);
\r
725 Argument arg = (Argument) pos_args [0];
\r
726 if (!(arg.Expr is StringConstant)){
\r
727 Error_AttributeConstructorMismatch (Location);
\r
731 if (pos_args.Count == 2){
\r
732 Argument arg2 = (Argument) pos_args [1];
\r
733 if (!(arg2.Expr is BoolConstant)){
\r
734 Error_AttributeConstructorMismatch (Location);
\r
737 is_error = ((BoolConstant) arg2.Expr).Value;
\r
740 return ((StringConstant) arg.Expr).Value;
\r
743 static object GetFieldValue (Attribute a, string name) {
\r
745 if (a.field_info_arr == null)
\r
748 foreach (FieldInfo fi in a.field_info_arr) {
\r
749 if (fi.Name == name)
\r
750 return a.field_values_arr [i];
\r
756 static UnmanagedMarshal GetMarshal (Attribute a) {
\r
757 UnmanagedMarshal marshal;
\r
759 if (a.UnmanagedType == UnmanagedType.CustomMarshaler) {
\r
760 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom", BindingFlags.Static | BindingFlags.Public);
\r
761 if (define_custom == null) {
\r
764 object[] args = new object [4];
\r
765 args [0] = GetFieldValue (a, "MarshalTypeRef");
\r
766 args [1] = GetFieldValue (a, "MarshalCookie");
\r
767 args [2] = GetFieldValue (a, "MarshalType");
\r
768 args [3] = Guid.Empty;
\r
769 marshal = (UnmanagedMarshal) define_custom.Invoke (null, args);
\r
771 * need to special case other special marshal types
\r
774 marshal = UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
\r
780 // Applies the attributes to the `builder'.
\r
782 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
\r
783 Attributes opt_attrs)
\r
785 Type attr_type = null;
\r
787 if (opt_attrs == null)
\r
789 if (opt_attrs.AttributeSections == null)
\r
792 ArrayList emitted_attrs = new ArrayList ();
\r
793 ArrayList emitted_targets = new ArrayList ();
\r
795 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
796 string attr_target = asec.Target;
\r
798 if (asec.Attributes == null)
\r
801 if (attr_target == "assembly" && !(builder is AssemblyBuilder))
\r
804 if (attr_target == "return" && !(builder is ParameterBuilder))
\r
807 foreach (Attribute a in asec.Attributes) {
\r
808 Location loc = a.Location;
\r
809 CustomAttributeBuilder cb = a.Resolve (ec);
\r
810 attr_type = a.Type;
\r
815 if (!(kind is TypeContainer))
\r
816 if (!CheckAttribute (a, kind)) {
\r
817 Error_AttributeNotValidForElement (a, loc);
\r
822 // Perform the check for duplicate attributes
\r
824 if (emitted_attrs.Contains (attr_type) &&
\r
825 emitted_targets.Contains (attr_target) &&
\r
826 !TypeManager.AreMultipleAllowed (attr_type)) {
\r
827 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
\r
831 if (kind is Method || kind is Operator || kind is InterfaceMethod ||
\r
832 kind is Accessor) {
\r
833 if (attr_type == TypeManager.methodimpl_attr_type) {
\r
834 if (a.ImplOptions == MethodImplOptions.InternalCall)
\r
835 ((MethodBuilder) builder).
\r
836 SetImplementationFlags (
\r
837 MethodImplAttributes.InternalCall |
\r
838 MethodImplAttributes.Runtime);
\r
840 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
841 } else if (attr_type != TypeManager.dllimport_type){
\r
842 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
844 } else if (kind is Constructor) {
\r
845 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
\r
846 } else if (kind is Field) {
\r
847 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
848 } else if (kind is Property || kind is Indexer ||
\r
849 kind is InterfaceProperty || kind is InterfaceIndexer) {
\r
850 ((PropertyBuilder) builder).SetCustomAttribute (cb);
\r
851 } else if (kind is Event || kind is InterfaceEvent) {
\r
852 ((MyEventBuilder) builder).SetCustomAttribute (cb);
\r
853 } else if (kind is ParameterBuilder) {
\r
855 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
856 UnmanagedMarshal marshal = GetMarshal (a);
\r
857 if (marshal == null) {
\r
858 Report.Warning (-24, loc,
\r
859 "The Microsoft Runtime cannot set this marshal info. " +
\r
860 "Please use the Mono runtime instead.");
\r
862 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
867 ((ParameterBuilder) builder).SetCustomAttribute (cb);
\r
868 } catch (System.ArgumentException) {
\r
869 Report.Warning (-24, loc,
\r
870 "The Microsoft Runtime cannot set attributes \n" +
\r
871 "on the return type of a method. Please use the \n" +
\r
872 "Mono runtime instead.");
\r
876 } else if (kind is Enum) {
\r
877 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
879 } else if (kind is TypeContainer) {
\r
880 TypeContainer tc = (TypeContainer) kind;
\r
883 tc.Targets = a.Targets;
\r
884 tc.AllowMultiple = a.AllowMultiple;
\r
885 tc.Inherited = a.Inherited;
\r
887 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
\r
890 } else if (attr_type == TypeManager.default_member_type) {
\r
891 if (tc.Indexers != null) {
\r
892 Report.Error (646, loc,
\r
893 "Cannot specify the DefaultMember attribute on" +
\r
894 " a type containing an indexer");
\r
899 if (!CheckAttribute (a, kind)) {
\r
900 Error_AttributeNotValidForElement (a, loc);
\r
906 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
907 } catch (System.ArgumentException) {
\r
910 "The CharSet named property on StructLayout\n"+
\r
911 "\tdoes not work correctly on Microsoft.NET\n"+
\r
912 "\tYou might want to remove the CharSet declaration\n"+
\r
913 "\tor compile using the Mono runtime instead of the\n"+
\r
914 "\tMicrosoft .NET runtime");
\r
917 } else if (kind is Interface) {
\r
918 Interface iface = (Interface) kind;
\r
920 if ((attr_type == TypeManager.default_member_type) &&
\r
921 (iface.InterfaceIndexers != null)) {
\r
924 "Cannot specify the DefaultMember attribute on" +
\r
925 " a type containing an indexer");
\r
929 if (!CheckAttribute (a, kind)) {
\r
930 Error_AttributeNotValidForElement (a, loc);
\r
934 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
935 } else if (kind is AssemblyBuilder){
\r
936 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
\r
937 } else if (kind is ModuleBuilder) {
\r
938 ((ModuleBuilder) builder).SetCustomAttribute (cb);
\r
939 } else if (kind is FieldBuilder) {
\r
940 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
941 UnmanagedMarshal marshal = GetMarshal (a);
\r
942 if (marshal == null) {
\r
943 Report.Warning (-24, loc,
\r
944 "The Microsoft Runtime cannot set this marshal info. " +
\r
945 "Please use the Mono runtime instead.");
\r
947 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
950 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
953 throw new Exception ("Unknown kind: " + kind);
\r
956 // Once an attribute type has been emitted once we
\r
957 // keep track of the info to prevent multiple occurences
\r
958 // for attributes which do not explicitly allow it
\r
960 if (!emitted_attrs.Contains (attr_type))
\r
961 emitted_attrs.Add (attr_type);
\r
964 // We keep of this target-wise and so emitted targets
\r
967 if (!emitted_targets.Contains (attr_target))
\r
968 emitted_targets.Add (attr_target);
\r
975 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
\r
976 MethodAttributes flags, Type ret_type, Type [] param_types)
\r
979 // We extract from the attribute the information we need
\r
982 if (Arguments == null) {
\r
983 Console.WriteLine ("Internal error : this is not supposed to happen !");
\r
987 Type = CheckAttributeType (ec);
\r
991 ArrayList named_args = new ArrayList ();
\r
993 ArrayList pos_args = (ArrayList) Arguments [0];
\r
994 if (Arguments.Count > 1)
\r
995 named_args = (ArrayList) Arguments [1];
\r
998 string dll_name = null;
\r
1000 Argument tmp = (Argument) pos_args [0];
\r
1002 if (!tmp.Resolve (ec, Location))
\r
1005 if (tmp.Expr is Constant)
\r
1006 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
\r
1008 Error_AttributeArgumentNotValid (Location);
\r
1012 // Now we process the named arguments
\r
1013 CallingConvention cc = CallingConvention.Winapi;
\r
1014 CharSet charset = CharSet.Ansi;
\r
1015 bool preserve_sig = true;
\r
1016 bool exact_spelling = false;
\r
1017 bool set_last_err = false;
\r
1018 string entry_point = null;
\r
1020 for (int i = 0; i < named_args.Count; i++) {
\r
1022 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
1024 string member_name = (string) de.Key;
\r
1025 Argument a = (Argument) de.Value;
\r
1027 if (!a.Resolve (ec, Location))
\r
1030 Expression member = Expression.MemberLookup (
\r
1031 ec, Type, member_name,
\r
1032 MemberTypes.Field | MemberTypes.Property,
\r
1033 BindingFlags.Public | BindingFlags.Instance,
\r
1036 if (member == null || !(member is FieldExpr)) {
\r
1037 Error_InvalidNamedArgument (member_name);
\r
1041 if (member is FieldExpr) {
\r
1042 FieldExpr fe = (FieldExpr) member;
\r
1043 FieldInfo fi = fe.FieldInfo;
\r
1045 if (fi.IsInitOnly) {
\r
1046 Error_InvalidNamedArgument (member_name);
\r
1050 if (a.Expr is Constant) {
\r
1051 Constant c = (Constant) a.Expr;
\r
1053 if (member_name == "CallingConvention")
\r
1054 cc = (CallingConvention) c.GetValue ();
\r
1055 else if (member_name == "CharSet")
\r
1056 charset = (CharSet) c.GetValue ();
\r
1057 else if (member_name == "EntryPoint")
\r
1058 entry_point = (string) c.GetValue ();
\r
1059 else if (member_name == "SetLastError")
\r
1060 set_last_err = (bool) c.GetValue ();
\r
1061 else if (member_name == "ExactSpelling")
\r
1062 exact_spelling = (bool) c.GetValue ();
\r
1063 else if (member_name == "PreserveSig")
\r
1064 preserve_sig = (bool) c.GetValue ();
\r
1066 Error_AttributeArgumentNotValid (Location);
\r
1073 if (entry_point == null)
\r
1074 entry_point = name;
\r
1076 MethodBuilder mb = builder.DefinePInvokeMethod (
\r
1077 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
\r
1078 CallingConventions.Standard,
\r
1085 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
\r
1092 public class AttributeSection {
\r
1093 public readonly string Target;
\r
1094 public readonly ArrayList Attributes;
\r
1096 public AttributeSection (string target, ArrayList attrs)
\r
1099 Attributes = attrs;
\r
1104 public class Attributes {
\r
1105 public ArrayList AttributeSections;
\r
1107 public Attributes (AttributeSection a)
\r
1109 AttributeSections = new ArrayList ();
\r
1110 AttributeSections.Add (a);
\r
1114 public void AddAttributeSection (AttributeSection a)
\r
1116 if (a != null && !AttributeSections.Contains (a))
\r
1117 AttributeSections.Add (a);
\r
1120 public bool Contains (Type t)
\r
1122 foreach (AttributeSection attr_section in AttributeSections){
\r
1123 foreach (Attribute a in attr_section.Attributes){
\r