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
150 Error_AttributeArgumentNotValid (loc);
\r
154 public CustomAttributeBuilder Resolve (EmitContext ec)
\r
157 Type = CheckAttributeType (ec);
\r
161 bool MethodImplAttr = false;
\r
162 bool MarshalAsAttr = false;
\r
163 bool GuidAttr = false;
\r
166 bool DoCompares = true;
\r
169 // If we are a certain special attribute, we
\r
170 // set the information accordingly
\r
173 if (Type == TypeManager.attribute_usage_type)
\r
175 else if (Type == TypeManager.methodimpl_attr_type)
\r
176 MethodImplAttr = true;
\r
177 else if (Type == TypeManager.marshal_as_attr_type)
\r
178 MarshalAsAttr = true;
\r
179 else if (Type == TypeManager.guid_attr_type)
\r
182 DoCompares = false;
\r
184 // Now we extract the positional and named arguments
\r
186 ArrayList pos_args = new ArrayList ();
\r
187 ArrayList named_args = new ArrayList ();
\r
188 int pos_arg_count = 0;
\r
190 if (Arguments != null) {
\r
191 pos_args = (ArrayList) Arguments [0];
\r
192 if (pos_args != null)
\r
193 pos_arg_count = pos_args.Count;
\r
194 if (Arguments.Count > 1)
\r
195 named_args = (ArrayList) Arguments [1];
\r
198 object [] pos_values = new object [pos_arg_count];
\r
201 // First process positional arguments
\r
205 for (i = 0; i < pos_arg_count; i++) {
\r
206 Argument a = (Argument) pos_args [i];
\r
209 if (!a.Resolve (ec, Location))
\r
215 if (!GetAttributeArgumentExpression (e, Location, out val))
\r
218 pos_values [i] = val;
\r
221 this.Targets = (AttributeTargets) pos_values [0];
\r
222 else if (MethodImplAttr)
\r
223 this.ImplOptions = (MethodImplOptions) pos_values [0];
\r
224 else if (GuidAttr){
\r
226 // we will later check the validity of the type
\r
228 if (pos_values [0] is string){
\r
229 if (!ValidateGuid ((string) pos_values [0]))
\r
233 } else if (MarshalAsAttr)
\r
234 this.UnmanagedType =
\r
235 (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
\r
240 // Now process named arguments
\r
243 ArrayList field_infos = null;
\r
244 ArrayList prop_infos = null;
\r
245 ArrayList field_values = null;
\r
246 ArrayList prop_values = null;
\r
248 if (named_args.Count > 0) {
\r
249 field_infos = new ArrayList ();
\r
250 prop_infos = new ArrayList ();
\r
251 field_values = new ArrayList ();
\r
252 prop_values = new ArrayList ();
\r
255 for (i = 0; i < named_args.Count; i++) {
\r
256 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
257 string member_name = (string) de.Key;
\r
258 Argument a = (Argument) de.Value;
\r
261 if (!a.Resolve (ec, Location))
\r
264 Expression member = Expression.MemberLookup (
\r
265 ec, Type, member_name,
\r
266 MemberTypes.Field | MemberTypes.Property,
\r
267 BindingFlags.Public | BindingFlags.Instance,
\r
270 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
\r
271 Error_InvalidNamedArgument (member_name);
\r
276 if (member is PropertyExpr) {
\r
277 PropertyExpr pe = (PropertyExpr) member;
\r
278 PropertyInfo pi = pe.PropertyInfo;
\r
280 if (!pi.CanWrite) {
\r
281 Error_InvalidNamedArgument (member_name);
\r
285 if (e is Constant) {
\r
286 object o = ((Constant) e).GetValue ();
\r
287 prop_values.Add (o);
\r
290 if (member_name == "AllowMultiple")
\r
291 this.AllowMultiple = (bool) o;
\r
292 if (member_name == "Inherited")
\r
293 this.Inherited = (bool) o;
\r
296 } else if (e is TypeOf) {
\r
297 prop_values.Add (((TypeOf) e).TypeArg);
\r
299 Error_AttributeArgumentNotValid (Location);
\r
303 prop_infos.Add (pi);
\r
305 } else if (member is FieldExpr) {
\r
306 FieldExpr fe = (FieldExpr) member;
\r
307 FieldInfo fi = fe.FieldInfo;
\r
309 if (fi.IsInitOnly) {
\r
310 Error_InvalidNamedArgument (member_name);
\r
315 // Handle charset here, and set the TypeAttributes
\r
317 if (e is Constant){
\r
318 object value = ((Constant) e).GetValue ();
\r
320 field_values.Add (value);
\r
321 } else if (e is TypeOf) {
\r
322 field_values.Add (((TypeOf) e).TypeArg);
\r
324 Error_AttributeArgumentNotValid (Location);
\r
328 field_infos.Add (fi);
\r
332 Expression mg = Expression.MemberLookup (
\r
333 ec, Type, ".ctor", MemberTypes.Constructor,
\r
334 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
\r
338 Error_AttributeConstructorMismatch (Location);
\r
342 MethodBase constructor = Invocation.OverloadResolve (
\r
343 ec, (MethodGroupExpr) mg, pos_args, Location);
\r
345 if (constructor == null) {
\r
346 Error_AttributeConstructorMismatch (Location);
\r
351 // Now we perform some checks on the positional args as they
\r
352 // cannot be null for a constructor which expects a parameter
\r
356 ParameterData pd = Invocation.GetParameterData (constructor);
\r
358 int group_in_params_array = Int32.MaxValue;
\r
360 if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)
\r
361 group_in_params_array = pc-1;
\r
363 for (int j = 0; j < pos_arg_count; ++j) {
\r
364 Argument a = (Argument) pos_args [j];
\r
366 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
\r
367 Error_AttributeArgumentNotValid (Location);
\r
371 if (j < group_in_params_array)
\r
374 if (j == group_in_params_array){
\r
375 object v = pos_values [j];
\r
376 int count = pos_arg_count - j;
\r
378 object [] array = new object [count];
\r
379 pos_values [j] = array;
\r
382 object [] array = (object []) pos_values [group_in_params_array];
\r
384 array [j - group_in_params_array] = pos_values [j];
\r
389 // Adjust the size of the pos_values if it had params
\r
391 if (group_in_params_array != Int32.MaxValue){
\r
392 int argc = group_in_params_array+1;
\r
393 object [] new_pos_values = new object [argc];
\r
395 for (int p = 0; p < argc; p++)
\r
396 new_pos_values [p] = pos_values [p];
\r
397 pos_values = new_pos_values;
\r
401 if (named_args.Count > 0) {
\r
402 prop_info_arr = new PropertyInfo [prop_infos.Count];
\r
403 field_info_arr = new FieldInfo [field_infos.Count];
\r
404 field_values_arr = new object [field_values.Count];
\r
405 prop_values_arr = new object [prop_values.Count];
\r
407 field_infos.CopyTo (field_info_arr, 0);
\r
408 field_values.CopyTo (field_values_arr, 0);
\r
410 prop_values.CopyTo (prop_values_arr, 0);
\r
411 prop_infos.CopyTo (prop_info_arr, 0);
\r
413 cb = new CustomAttributeBuilder (
\r
414 (ConstructorInfo) constructor, pos_values,
\r
415 prop_info_arr, prop_values_arr,
\r
416 field_info_arr, field_values_arr);
\r
419 cb = new CustomAttributeBuilder (
\r
420 (ConstructorInfo) constructor, pos_values);
\r
421 } catch (NullReferenceException) {
\r
423 // Don't know what to do here
\r
426 -101, Location, "NullReferenceException while trying to create attribute." +
\r
427 "Something's wrong!");
\r
428 } catch (Exception e) {
\r
431 // using System.ComponentModel;
\r
432 // [DefaultValue (CollectionChangeAction.Add)]
\r
433 // class X { static void Main () {} }
\r
437 "The compiler can not encode this attribute in .NET due to\n" +
\r
438 "\ta bug in the .NET runtime. Try the Mono runtime.\nThe error was: " + e.Message);
\r
445 /// Get a string containing a list of valid targets for the attribute 'attr'
\r
447 static string GetValidTargets (Attribute attr)
\r
449 StringBuilder sb = new StringBuilder ();
\r
450 AttributeTargets targets = 0;
\r
452 TypeContainer a = TypeManager.LookupAttr (attr.Type);
\r
456 System.Attribute [] attrs = null;
\r
459 attrs = System.Attribute.GetCustomAttributes (attr.Type);
\r
462 Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
\r
463 " (maybe you forgot to set the usage using the" +
\r
464 " AttributeUsage attribute ?).");
\r
468 foreach (System.Attribute tmp in attrs)
\r
469 if (tmp is AttributeUsageAttribute) {
\r
470 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
474 targets = a.Targets;
\r
477 if ((targets & AttributeTargets.Assembly) != 0)
\r
478 sb.Append ("'assembly' ");
\r
480 if ((targets & AttributeTargets.Class) != 0)
\r
481 sb.Append ("'class' ");
\r
483 if ((targets & AttributeTargets.Constructor) != 0)
\r
484 sb.Append ("'constructor' ");
\r
486 if ((targets & AttributeTargets.Delegate) != 0)
\r
487 sb.Append ("'delegate' ");
\r
489 if ((targets & AttributeTargets.Enum) != 0)
\r
490 sb.Append ("'enum' ");
\r
492 if ((targets & AttributeTargets.Event) != 0)
\r
493 sb.Append ("'event' ");
\r
495 if ((targets & AttributeTargets.Field) != 0)
\r
496 sb.Append ("'field' ");
\r
498 if ((targets & AttributeTargets.Interface) != 0)
\r
499 sb.Append ("'interface' ");
\r
501 if ((targets & AttributeTargets.Method) != 0)
\r
502 sb.Append ("'method' ");
\r
504 if ((targets & AttributeTargets.Module) != 0)
\r
505 sb.Append ("'module' ");
\r
507 if ((targets & AttributeTargets.Parameter) != 0)
\r
508 sb.Append ("'parameter' ");
\r
510 if ((targets & AttributeTargets.Property) != 0)
\r
511 sb.Append ("'property' ");
\r
513 if ((targets & AttributeTargets.ReturnValue) != 0)
\r
514 sb.Append ("'return value' ");
\r
516 if ((targets & AttributeTargets.Struct) != 0)
\r
517 sb.Append ("'struct' ");
\r
519 return sb.ToString ();
\r
523 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
\r
526 592, loc, "Attribute '" + a.Name +
\r
527 "' is not valid on this declaration type. " +
\r
528 "It is valid on " + GetValidTargets (a) + "declarations only.");
\r
532 /// Ensure that Attribute 'a' is being applied to the right language element (target)
\r
534 public static bool CheckAttributeTarget (Attribute a, object element)
\r
536 TypeContainer attr = TypeManager.LookupAttr (a.Type);
\r
537 AttributeTargets targets = 0;
\r
539 if (attr == null) {
\r
540 System.Attribute [] attrs = null;
\r
543 attrs = System.Attribute.GetCustomAttributes (a.Type);
\r
546 Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
\r
547 " (maybe you forgot to set the usage using the" +
\r
548 " AttributeUsage attribute ?).");
\r
552 foreach (System.Attribute tmp in attrs)
\r
553 if (tmp is AttributeUsageAttribute) {
\r
554 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
558 targets = attr.Targets;
\r
561 if (element is Class) {
\r
562 if ((targets & AttributeTargets.Class) != 0)
\r
567 } else if (element is Struct) {
\r
568 if ((targets & AttributeTargets.Struct) != 0)
\r
572 } else if (element is Constructor) {
\r
573 if ((targets & AttributeTargets.Constructor) != 0)
\r
577 } else if (element is Delegate) {
\r
578 if ((targets & AttributeTargets.Delegate) != 0)
\r
582 } else if (element is Enum) {
\r
583 if ((targets & AttributeTargets.Enum) != 0)
\r
587 } else if (element is Event || element is InterfaceEvent) {
\r
588 if ((targets & AttributeTargets.Event) != 0)
\r
592 } else if (element is Field || element is FieldBuilder) {
\r
593 if ((targets & AttributeTargets.Field) != 0)
\r
597 } else if (element is Interface) {
\r
598 if ((targets & AttributeTargets.Interface) != 0)
\r
602 } else if (element is Method || element is Operator ||
\r
603 element is InterfaceMethod || element is Accessor) {
\r
604 if ((targets & AttributeTargets.Method) != 0)
\r
608 } else if (element is ParameterBuilder) {
\r
609 if ((targets & AttributeTargets.Parameter) != 0 ||
\r
610 (targets & AttributeTargets.ReturnValue) != 0)
\r
614 } else if (element is Property || element is Indexer ||
\r
615 element is InterfaceProperty || element is InterfaceIndexer) {
\r
616 if ((targets & AttributeTargets.Property) != 0)
\r
620 } else if (element is AssemblyBuilder){
\r
621 if ((targets & AttributeTargets.Assembly) != 0)
\r
631 // This method should be invoked to pull the IndexerName attribute from an
\r
632 // Indexer if it exists.
\r
634 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
\r
636 if (opt_attrs == null)
\r
638 if (opt_attrs.AttributeSections == null)
\r
641 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
642 if (asec.Attributes == null)
\r
645 foreach (Attribute a in asec.Attributes){
\r
646 if (a.ResolveType (ec) == null)
\r
649 if (a.Type != TypeManager.indexer_name_type)
\r
653 // So we have found an IndexerName, pull the data out.
\r
655 if (a.Arguments == null || a.Arguments [0] == null){
\r
656 Error_AttributeConstructorMismatch (a.Location);
\r
659 ArrayList pos_args = (ArrayList) a.Arguments [0];
\r
660 if (pos_args.Count == 0){
\r
661 Error_AttributeConstructorMismatch (a.Location);
\r
665 Argument arg = (Argument) pos_args [0];
\r
666 if (!arg.Resolve (ec, a.Location))
\r
669 Expression e = arg.Expr;
\r
670 if (!(e is StringConstant)){
\r
671 Error_AttributeConstructorMismatch (a.Location);
\r
676 // Remove the attribute from the list
\r
678 asec.Attributes.Remove (a);
\r
680 return (((StringConstant) e).Value);
\r
687 // This pulls the condition name out of a Conditional attribute
\r
689 public string Conditional_GetConditionName ()
\r
692 // So we have a Conditional, pull the data out.
\r
694 if (Arguments == null || Arguments [0] == null){
\r
695 Error_AttributeConstructorMismatch (Location);
\r
699 ArrayList pos_args = (ArrayList) Arguments [0];
\r
700 if (pos_args.Count != 1){
\r
701 Error_AttributeConstructorMismatch (Location);
\r
705 Argument arg = (Argument) pos_args [0];
\r
706 if (!(arg.Expr is StringConstant)){
\r
707 Error_AttributeConstructorMismatch (Location);
\r
711 return ((StringConstant) arg.Expr).Value;
\r
715 // This pulls the obsolete message and error flag out of an Obsolete attribute
\r
717 public string Obsolete_GetObsoleteMessage (out bool is_error)
\r
721 // So we have an Obsolete, pull the data out.
\r
723 if (Arguments == null || Arguments [0] == null)
\r
726 ArrayList pos_args = (ArrayList) Arguments [0];
\r
727 if (pos_args.Count == 0)
\r
729 else if (pos_args.Count > 2){
\r
730 Error_AttributeConstructorMismatch (Location);
\r
734 Argument arg = (Argument) pos_args [0];
\r
735 if (!(arg.Expr is StringConstant)){
\r
736 Error_AttributeConstructorMismatch (Location);
\r
740 if (pos_args.Count == 2){
\r
741 Argument arg2 = (Argument) pos_args [1];
\r
742 if (!(arg2.Expr is BoolConstant)){
\r
743 Error_AttributeConstructorMismatch (Location);
\r
746 is_error = ((BoolConstant) arg2.Expr).Value;
\r
749 return ((StringConstant) arg.Expr).Value;
\r
752 static object GetFieldValue (Attribute a, string name)
\r
755 if (a.field_info_arr == null)
\r
758 foreach (FieldInfo fi in a.field_info_arr) {
\r
759 if (fi.Name == name)
\r
760 return a.field_values_arr [i];
\r
766 static UnmanagedMarshal GetMarshal (Attribute a)
\r
768 UnmanagedMarshal marshal;
\r
770 if (a.UnmanagedType == UnmanagedType.CustomMarshaler) {
\r
771 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
\r
772 BindingFlags.Static | BindingFlags.Public);
\r
773 if (define_custom == null) {
\r
776 object[] args = new object [4];
\r
777 args [0] = GetFieldValue (a, "MarshalTypeRef");
\r
778 args [1] = GetFieldValue (a, "MarshalCookie");
\r
779 args [2] = GetFieldValue (a, "MarshalType");
\r
780 args [3] = Guid.Empty;
\r
781 marshal = (UnmanagedMarshal) define_custom.Invoke (null, args);
\r
783 * need to special case other special marshal types
\r
786 marshal = UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
\r
792 /// Applies the attributes specified on target 'kind' to the `builder'.
\r
794 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
\r
795 Attributes opt_attrs)
\r
797 Type attr_type = null;
\r
799 if (opt_attrs == null)
\r
801 if (opt_attrs.AttributeSections == null)
\r
804 ArrayList emitted_attrs = new ArrayList ();
\r
805 ArrayList emitted_targets = new ArrayList ();
\r
807 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
808 string attr_target = asec.Target;
\r
810 if (asec.Attributes == null)
\r
813 if (attr_target == "assembly" && !(builder is AssemblyBuilder))
\r
816 if (attr_target == "return" && !(builder is ParameterBuilder))
\r
819 foreach (Attribute a in asec.Attributes) {
\r
820 Location loc = a.Location;
\r
821 CustomAttributeBuilder cb = a.Resolve (ec);
\r
822 attr_type = a.Type;
\r
827 if (!(kind is TypeContainer))
\r
828 if (!CheckAttributeTarget (a, kind)) {
\r
829 Error_AttributeNotValidForElement (a, loc);
\r
834 // Perform the check for duplicate attributes
\r
836 if (emitted_attrs.Contains (attr_type) &&
\r
837 emitted_targets.Contains (attr_target) &&
\r
838 !TypeManager.AreMultipleAllowed (attr_type)) {
\r
839 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
\r
843 if (kind is Method || kind is Operator || kind is InterfaceMethod ||
\r
844 kind is Accessor) {
\r
845 if (attr_type == TypeManager.methodimpl_attr_type) {
\r
846 if (a.ImplOptions == MethodImplOptions.InternalCall)
\r
847 ((MethodBuilder) builder).
\r
848 SetImplementationFlags (
\r
849 MethodImplAttributes.InternalCall |
\r
850 MethodImplAttributes.Runtime);
\r
852 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
853 } else if (attr_type != TypeManager.dllimport_type){
\r
854 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
856 } else if (kind is Constructor) {
\r
857 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
\r
858 } else if (kind is Field) {
\r
859 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
860 } else if (kind is Property || kind is Indexer ||
\r
861 kind is InterfaceProperty || kind is InterfaceIndexer) {
\r
862 ((PropertyBuilder) builder).SetCustomAttribute (cb);
\r
863 } else if (kind is Event || kind is InterfaceEvent) {
\r
864 ((MyEventBuilder) builder).SetCustomAttribute (cb);
\r
865 } else if (kind is ParameterBuilder) {
\r
867 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
868 UnmanagedMarshal marshal = GetMarshal (a);
\r
869 if (marshal == null) {
\r
870 Report.Warning (-24, loc,
\r
871 "The Microsoft Runtime cannot set this marshal info. " +
\r
872 "Please use the Mono runtime instead.");
\r
874 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
879 ((ParameterBuilder) builder).SetCustomAttribute (cb);
\r
880 } catch (System.ArgumentException) {
\r
881 Report.Warning (-24, loc,
\r
882 "The Microsoft Runtime cannot set attributes \n" +
\r
883 "on the return type of a method. Please use the \n" +
\r
884 "Mono runtime instead.");
\r
888 } else if (kind is Enum) {
\r
889 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
891 } else if (kind is TypeContainer) {
\r
892 TypeContainer tc = (TypeContainer) kind;
\r
895 tc.Targets = a.Targets;
\r
896 tc.AllowMultiple = a.AllowMultiple;
\r
897 tc.Inherited = a.Inherited;
\r
899 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
\r
902 } else if (attr_type == TypeManager.default_member_type) {
\r
903 if (tc.Indexers != null) {
\r
904 Report.Error (646, loc,
\r
905 "Cannot specify the DefaultMember attribute on" +
\r
906 " a type containing an indexer");
\r
911 if (!CheckAttributeTarget (a, kind)) {
\r
912 Error_AttributeNotValidForElement (a, loc);
\r
918 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
919 } catch (System.ArgumentException e) {
\r
922 "The CharSet named property on StructLayout\n"+
\r
923 "\tdoes not work correctly on Microsoft.NET\n"+
\r
924 "\tYou might want to remove the CharSet declaration\n"+
\r
925 "\tor compile using the Mono runtime instead of the\n"+
\r
926 "\tMicrosoft .NET runtime");
\r
928 } else if (kind is Delegate){
\r
929 if (!CheckAttributeTarget (a, kind)) {
\r
930 Error_AttributeNotValidForElement (a, loc);
\r
934 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
935 } catch (System.ArgumentException e) {
\r
938 "The CharSet named property on StructLayout\n"+
\r
939 "\tdoes not work correctly on Microsoft.NET\n"+
\r
940 "\tYou might want to remove the CharSet declaration\n"+
\r
941 "\tor compile using the Mono runtime instead of the\n"+
\r
942 "\tMicrosoft .NET runtime");
\r
944 } else if (kind is Interface) {
\r
945 Interface iface = (Interface) kind;
\r
947 if ((attr_type == TypeManager.default_member_type) &&
\r
948 (iface.InterfaceIndexers != null)) {
\r
951 "Cannot specify the DefaultMember attribute on" +
\r
952 " a type containing an indexer");
\r
956 if (!CheckAttributeTarget (a, kind)) {
\r
957 Error_AttributeNotValidForElement (a, loc);
\r
961 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
962 } else if (kind is AssemblyBuilder){
\r
963 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
\r
964 } else if (kind is ModuleBuilder) {
\r
965 ((ModuleBuilder) builder).SetCustomAttribute (cb);
\r
966 } else if (kind is FieldBuilder) {
\r
967 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
968 UnmanagedMarshal marshal = GetMarshal (a);
\r
969 if (marshal == null) {
\r
970 Report.Warning (-24, loc,
\r
971 "The Microsoft Runtime cannot set this marshal info. " +
\r
972 "Please use the Mono runtime instead.");
\r
974 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
977 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
980 throw new Exception ("Unknown kind: " + kind);
\r
983 // Once an attribute type has been emitted once we
\r
984 // keep track of the info to prevent multiple occurences
\r
985 // for attributes which do not explicitly allow it
\r
987 if (!emitted_attrs.Contains (attr_type))
\r
988 emitted_attrs.Add (attr_type);
\r
991 // We keep of this target-wise and so emitted targets
\r
994 if (!emitted_targets.Contains (attr_target))
\r
995 emitted_targets.Add (attr_target);
\r
1002 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
\r
1003 MethodAttributes flags, Type ret_type, Type [] param_types)
\r
1006 // We extract from the attribute the information we need
\r
1009 if (Arguments == null) {
\r
1010 Console.WriteLine ("Internal error : this is not supposed to happen !");
\r
1014 Type = CheckAttributeType (ec);
\r
1018 ArrayList named_args = new ArrayList ();
\r
1020 ArrayList pos_args = (ArrayList) Arguments [0];
\r
1021 if (Arguments.Count > 1)
\r
1022 named_args = (ArrayList) Arguments [1];
\r
1025 string dll_name = null;
\r
1027 Argument tmp = (Argument) pos_args [0];
\r
1029 if (!tmp.Resolve (ec, Location))
\r
1032 if (tmp.Expr is Constant)
\r
1033 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
\r
1035 Error_AttributeArgumentNotValid (Location);
\r
1039 // Now we process the named arguments
\r
1040 CallingConvention cc = CallingConvention.Winapi;
\r
1041 CharSet charset = CharSet.Ansi;
\r
1042 bool preserve_sig = true;
\r
1043 bool exact_spelling = false;
\r
1044 bool set_last_err = false;
\r
1045 string entry_point = null;
\r
1047 for (int i = 0; i < named_args.Count; i++) {
\r
1049 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
1051 string member_name = (string) de.Key;
\r
1052 Argument a = (Argument) de.Value;
\r
1054 if (!a.Resolve (ec, Location))
\r
1057 Expression member = Expression.MemberLookup (
\r
1058 ec, Type, member_name,
\r
1059 MemberTypes.Field | MemberTypes.Property,
\r
1060 BindingFlags.Public | BindingFlags.Instance,
\r
1063 if (member == null || !(member is FieldExpr)) {
\r
1064 Error_InvalidNamedArgument (member_name);
\r
1068 if (member is FieldExpr) {
\r
1069 FieldExpr fe = (FieldExpr) member;
\r
1070 FieldInfo fi = fe.FieldInfo;
\r
1072 if (fi.IsInitOnly) {
\r
1073 Error_InvalidNamedArgument (member_name);
\r
1077 if (a.Expr is Constant) {
\r
1078 Constant c = (Constant) a.Expr;
\r
1080 if (member_name == "CallingConvention")
\r
1081 cc = (CallingConvention) c.GetValue ();
\r
1082 else if (member_name == "CharSet")
\r
1083 charset = (CharSet) c.GetValue ();
\r
1084 else if (member_name == "EntryPoint")
\r
1085 entry_point = (string) c.GetValue ();
\r
1086 else if (member_name == "SetLastError")
\r
1087 set_last_err = (bool) c.GetValue ();
\r
1088 else if (member_name == "ExactSpelling")
\r
1089 exact_spelling = (bool) c.GetValue ();
\r
1090 else if (member_name == "PreserveSig")
\r
1091 preserve_sig = (bool) c.GetValue ();
\r
1093 Error_AttributeArgumentNotValid (Location);
\r
1100 if (entry_point == null)
\r
1101 entry_point = name;
\r
1103 charset = (CharSet)((int)charset | 0x40);
\r
1105 MethodBuilder mb = builder.DefinePInvokeMethod (
\r
1106 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
\r
1107 CallingConventions.Standard,
\r
1114 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
\r
1121 public class AttributeSection {
\r
1122 public readonly string Target;
\r
1123 public readonly ArrayList Attributes;
\r
1125 public AttributeSection (string target, ArrayList attrs)
\r
1128 Attributes = attrs;
\r
1133 public class Attributes {
\r
1134 public ArrayList AttributeSections;
\r
1136 public Attributes (AttributeSection a)
\r
1138 AttributeSections = new ArrayList ();
\r
1139 AttributeSections.Add (a);
\r
1143 public void AddAttributeSection (AttributeSection a)
\r
1145 if (a != null && !AttributeSections.Contains (a))
\r
1146 AttributeSections.Add (a);
\r
1149 public bool Contains (Type t)
\r
1151 foreach (AttributeSection attr_section in AttributeSections){
\r
1152 foreach (Attribute a in attr_section.Attributes){
\r