Small correction in the Test case file : 'ImpConversionDatetoStringA.vb'
[mono.git] / mcs / mbas / attribute.cs
1 //
2 // attribute.cs: Attribute Handler
3 //
4 // Author: Ravi Pratap (ravi@ximian.com)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11
12 using System;
13 using System.Diagnostics;
14 using System.Collections;
15 using System.Collections.Specialized;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.InteropServices;
19 using System.Runtime.CompilerServices;
20 using System.Text;
21
22 namespace Mono.MonoBASIC {
23
24         /// <summary>
25         ///   Base class for objects that can have Attributes applied to them.
26         /// </summary>
27         public abstract class Attributable {
28                 /// <summary>
29                 ///   Attributes for this type
30                 /// </summary>
31                 Attributes attributes;
32
33                 public Attributable(Attributes attrs)
34                 {
35                         attributes = attrs;
36                 }
37
38                 public Attributes OptAttributes 
39                 {
40                         get {
41                                 return attributes;
42                         }
43                         set {
44                                 attributes = value;
45                         }
46                 }
47
48                 /// <summary>
49                 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
50                 /// </summary>
51                 public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);
52                 /// <summary>
53                 /// Returns one AttributeTarget for this element.
54                 /// </summary>
55                 public abstract AttributeTargets AttributeTargets { get; }
56         };
57         public class Attribute {
58                 public readonly string ExplicitTarget;
59                 public readonly string    Name;
60                 public readonly ArrayList Arguments;
61
62                 public Location Location;
63
64                 public Type Type;
65
66                 // Is non-null if type is AttributeUsageAttribute
67                 AttributeUsageAttribute usage_attribute;
68
69                 public AttributeUsageAttribute UsageAttribute {
70                         get {
71                                 return usage_attribute;
72                         }
73                 }
74                 
75                 bool usage_attr = false;
76                 
77                 MethodImplOptions ImplOptions;
78                 public UnmanagedType     UnmanagedType;
79                 CustomAttributeBuilder cb;
80
81                 public Attribute (string name, ArrayList args, Location loc)
82                 {
83                         Name = name;
84                         Arguments = args;
85                         Location = loc;
86                 }
87                 
88                 public Attribute (string target, string name, ArrayList args, Location loc) 
89                 {
90                         ExplicitTarget = target;
91                 }
92
93                 void Error_InvalidNamedArgument (string name)
94                 {
95                         Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
96                                       "argument. Named attribute arguments must be fields which are not " +
97                                       "readonly, static or const, or properties with a set accessor which "+
98                                       "are not static.");
99                 }
100
101                 void Error_AttributeArgumentNotValid ()
102                 {
103                         Report.Error (182, Location,
104                                       "An attribute argument must be a constant expression, typeof " +
105                                       "expression or array creation expression");
106                 }
107
108                 static void Error_AttributeConstructorMismatch (Location loc)
109                 {
110                         Report.Error (
111                                         -6, loc,
112                                         "Could not find a constructor for this argument list.");
113                 }
114                 
115                 private Type CheckAttributeType (EmitContext ec) {
116                         Type t;
117                         bool isattributeclass = true;
118                         
119                         t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
120                         if (t != null) {
121                                 isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
122                                 if (isattributeclass)
123                                         return t;
124                         }
125                         t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
126                         if (t != null) {
127                                 if (t.IsSubclassOf (TypeManager.attribute_type))
128                                         return t;
129                         }
130                         if (!isattributeclass) {
131                                 Report.Error (616, Location, "'" + Name + "': is not an attribute class");
132                                 return null;
133                         }
134                         if (t != null) {
135                                 Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
136                                 return null;
137                         }
138                         Report.Error (
139                                 246, Location, "Could not find attribute '" + Name + "' (are you" +
140                                 " missing a using directive or an assembly reference ?)");
141                         return null;
142                 }
143                 
144
145                 public Type ResolveType (EmitContext ec)
146                 {
147                         Type = CheckAttributeType (ec);
148                         return Type;
149                 }
150
151                 
152                 public CustomAttributeBuilder Resolve (EmitContext ec)
153                 {
154                         if (Type == null)
155                                 Type = CheckAttributeType (ec);
156                         if (Type == null)
157                                 return null;
158
159                         bool MethodImplAttr = false;
160                         bool MarshalAsAttr = false;
161
162                         usage_attr = false;
163
164                         if (Type == TypeManager.attribute_usage_type)
165                                 usage_attr = true;
166                         if (Type == TypeManager.methodimpl_attr_type)
167                                 MethodImplAttr = true;
168                         if (Type == TypeManager.marshal_as_attr_type)
169                                 MarshalAsAttr = true;
170
171                         // Now we extract the positional and named arguments
172                         
173                         ArrayList pos_args = new ArrayList ();
174                         ArrayList named_args = new ArrayList ();
175                         int pos_arg_count = 0;
176                         
177                         if (Arguments != null) {
178                                 pos_args = (ArrayList) Arguments [0];
179                                 if (pos_args != null)
180                                         pos_arg_count = pos_args.Count;
181                                 if (Arguments.Count > 1)
182                                         named_args = (ArrayList) Arguments [1];
183                         }
184
185                         object [] pos_values = new object [pos_arg_count];
186
187                         //
188                         // First process positional arguments 
189                         //
190
191                         int i;
192                         for (i = 0; i < pos_arg_count; i++) {
193                                 Argument a = (Argument) pos_args [i];
194                                 Expression e;
195
196                                 if (!a.Resolve (ec, Location))
197                                         return null;
198
199                                 e = a.Expr;
200
201                                 if (e is Constant) {
202                                         pos_values [i] = ((Constant) e).GetValue ();
203                                 } else if (e is TypeOf) {
204                                         pos_values [i] = ((TypeOf) e).TypeArg;
205                                 } else {
206                                         Error_AttributeArgumentNotValid ();
207                                         return null;
208                                 }
209                                 
210                                 if (usage_attr)
211                                         usage_attribute = new AttributeUsageAttribute ((AttributeTargets) pos_values [0]);
212                                 
213                                 if (MethodImplAttr)
214                                         this.ImplOptions = (MethodImplOptions) pos_values [0];
215                                 
216                                 if (MarshalAsAttr)
217                                         this.UnmanagedType =
218                                         (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
219                         }
220
221                         //
222                         // Now process named arguments
223                         //
224
225                         ArrayList field_infos = new ArrayList ();
226                         ArrayList prop_infos  = new ArrayList ();
227                         ArrayList field_values = new ArrayList ();
228                         ArrayList prop_values = new ArrayList ();
229                         
230                         for (i = 0; i < named_args.Count; i++) {
231                                 DictionaryEntry de = (DictionaryEntry) named_args [i];
232                                 string member_name = (string) de.Key;
233                                 Argument a  = (Argument) de.Value;
234                                 Expression e;
235                                 
236                                 if (!a.Resolve (ec, Location))
237                                         return null;
238
239                                 Expression member = Expression.MemberLookup (
240                                         ec, Type, member_name,
241                                         MemberTypes.Field | MemberTypes.Property,
242                                         BindingFlags.Public | BindingFlags.Instance,
243                                         Location);
244
245                                 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
246                                         Error_InvalidNamedArgument (member_name);
247                                         return null;
248                                 }
249
250                                 e = a.Expr;
251                                 if (member is PropertyExpr) {
252                                         PropertyExpr pe = (PropertyExpr) member;
253                                         PropertyInfo pi = pe.PropertyInfo;
254
255                                         if (!pi.CanWrite) {
256                                                 Error_InvalidNamedArgument (member_name);
257                                                 return null;
258                                         }
259
260                                         if (e is Constant) {
261                                                 object o = ((Constant) e).GetValue ();
262                                                 prop_values.Add (o);
263                                                 
264                                                 if (usage_attr) {
265                                                         if (member_name == "AllowMultiple")
266                                                                 usage_attribute.AllowMultiple = (bool) o;
267                                                         if (member_name == "Inherited")
268                                                                 usage_attribute.Inherited = (bool) o;
269                                                 }
270                                                 
271                                         } else if (e is TypeOf) {
272                                                 prop_values.Add (((TypeOf) e).TypeArg);
273                                         } else {
274                                                 Error_AttributeArgumentNotValid ();
275                                                 return null;
276                                         }
277                                         
278                                         prop_infos.Add (pi);
279                                         
280                                 } else if (member is FieldExpr) {
281                                         FieldExpr fe = (FieldExpr) member;
282                                         FieldInfo fi = fe.FieldInfo;
283
284                                         if (fi.IsInitOnly) {
285                                                 Error_InvalidNamedArgument (member_name);
286                                                 return null;
287                                         }
288
289                                         //
290                                         // Handle charset here, and set the TypeAttributes
291                                         
292                                         if (e is Constant){
293                                                 object value = ((Constant) e).GetValue ();
294                                                 
295                                                 field_values.Add (value);
296                                         } else if (e is TypeOf) {
297                                                 field_values.Add (((TypeOf) e).TypeArg);
298                                         } else {
299                                                 Error_AttributeArgumentNotValid ();
300                                                 return null;
301                                         }
302                                         
303                                         field_infos.Add (fi);
304                                 }
305                         }
306
307                         Expression mg = Expression.MemberLookup (
308                                 ec, Type, ".ctor", MemberTypes.Constructor,
309                                 BindingFlags.Public | BindingFlags.Instance, Location);
310
311                         if (mg == null) {
312                                 Error_AttributeConstructorMismatch (Location);
313                                 return null;
314                         }
315
316                         MethodBase constructor = Invocation.OverloadResolve (
317                                 ec, (MethodGroupExpr) mg, pos_args, Location);
318
319                         if (constructor == null) {
320                                 Error_AttributeConstructorMismatch (Location);
321                                 return null;
322                         }
323
324                         //
325                         // Now we perform some checks on the positional args as they
326                         // cannot be null for a constructor which expects a parameter
327                         // of type object
328                         //
329
330                         ParameterData pd = Invocation.GetParameterData (constructor);
331
332                         for (int j = 0; j < pos_arg_count; ++j) {
333                                 Argument a = (Argument) pos_args [j];
334                                 
335                                 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
336                                         Error_AttributeArgumentNotValid ();
337                                         return null;
338                                 }
339                         }
340                         
341                         PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];
342                         FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];
343                         object [] field_values_arr = new object [field_values.Count];
344                         object [] prop_values_arr = new object [prop_values.Count];
345
346                         field_infos.CopyTo  (field_info_arr, 0);
347                         field_values.CopyTo (field_values_arr, 0);
348
349                         prop_values.CopyTo  (prop_values_arr, 0);
350                         prop_infos.CopyTo   (prop_info_arr, 0);
351
352                         try {
353                                 cb = new CustomAttributeBuilder (
354                                         (ConstructorInfo) constructor, pos_values,
355                                         prop_info_arr, prop_values_arr,
356                                         field_info_arr, field_values_arr); 
357
358                         } catch (NullReferenceException) {
359                                 // 
360                                 // Don't know what to do here
361                                 //
362                         } catch {
363                                 //
364                                 // Sample:
365                                 // using System.ComponentModel;
366                                 // [DefaultValue (CollectionChangeAction.Add)]
367                                 // class X { static void Main () {} }
368                                 //
369                                 Report.Warning (
370                                         -23, Location,
371                                         "The compiler can not encode this attribute in .NET due to\n" +
372                                         "\ta bug in the .NET runtime.  Try the Mono runtime");
373                         }
374                         
375                         return cb;
376                 }
377
378                 public string GetValidTargets ()
379                 {
380                         StringBuilder sb = new StringBuilder ();
381                         AttributeTargets targets = GetAttributeUsage ().ValidOn;
382                         
383                         if ((targets & AttributeTargets.Assembly) != 0)
384                                 sb.Append ("'assembly' ");
385
386                         if ((targets & AttributeTargets.Class) != 0)
387                                 sb.Append ("'class' ");
388
389                         if ((targets & AttributeTargets.Constructor) != 0)
390                                 sb.Append ("'constructor' ");
391
392                         if ((targets & AttributeTargets.Delegate) != 0)
393                                 sb.Append ("'delegate' ");
394
395                         if ((targets & AttributeTargets.Enum) != 0)
396                                 sb.Append ("'enum' ");
397
398                         if ((targets & AttributeTargets.Event) != 0)
399                                 sb.Append ("'event' ");
400
401                         if ((targets & AttributeTargets.Field) != 0)
402                                 sb.Append ("'field' ");
403
404                         if ((targets & AttributeTargets.Interface) != 0)
405                                 sb.Append ("'interface' ");
406
407                         if ((targets & AttributeTargets.Method) != 0)
408                                 sb.Append ("'method' ");
409
410                         if ((targets & AttributeTargets.Module) != 0)
411                                 sb.Append ("'module' ");
412
413                         if ((targets & AttributeTargets.Parameter) != 0)
414                                 sb.Append ("'parameter' ");
415
416                         if ((targets & AttributeTargets.Property) != 0)
417                                 sb.Append ("'property' ");
418
419                         if ((targets & AttributeTargets.ReturnValue) != 0)
420                                 sb.Append ("'return value' ");
421
422                         if ((targets & AttributeTargets.Struct) != 0)
423                                 sb.Append ("'struct' ");
424
425                         return sb.ToString ();
426
427                 }
428
429                 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
430                 {
431                         Report.Error (
432                                 30662, loc, "Attribute '" + a.Name +
433                                 "' is not valid on this declaration type. " +
434                                 "It is valid on " + a.GetValidTargets () + "declarations only.");
435                 }
436
437                 public static bool CheckAttribute (Attribute a, object element)
438                 {
439                         //TypeContainer attr = TypeManager.LookupClass (a.Type);
440                         AttributeTargets targets = a.GetAttributeUsage ().ValidOn;
441
442
443                         if (element is Class) {
444                                 if ((targets & AttributeTargets.Class) != 0)
445                                         return true;
446                                 else
447                                         return false;
448                                 
449                         } else if (element is Struct) {
450                                 if ((targets & AttributeTargets.Struct) != 0)
451                                         return true;
452                                 else
453                                         return false;
454                         } else if (element is Constructor) {
455                                 if ((targets & AttributeTargets.Constructor) != 0)
456                                         return true;
457                                 else
458                                         return false;
459                         } else if (element is Delegate) {
460                                 if ((targets & AttributeTargets.Delegate) != 0)
461                                         return true;
462                                 else
463                                         return false;
464                         } else if (element is Enum) {
465                                 if ((targets & AttributeTargets.Enum) != 0)
466                                         return true;
467                                 else
468                                         return false;
469                         } else if (element is Event /*|| element is InterfaceEvent*/) {
470                                 if ((targets & AttributeTargets.Event) != 0)
471                                         return true;
472                                 else
473                                         return false;
474                         } else if (element is Field || element is FieldBuilder) {
475                                 if ((targets & AttributeTargets.Field) != 0)
476                                         return true;
477                                 else
478                                         return false;
479                         } else if (element is Interface) {
480                                 if ((targets & AttributeTargets.Interface) != 0)
481                                         return true;
482                                 else
483                                         return false;
484                         } else if (element is Method || element is Accessor) {
485                                 if ((targets & AttributeTargets.Method) != 0)
486                                         return true;
487                                 else
488                                         return false;
489                         } else if (element is ParameterBuilder) {
490                                 if ((targets & AttributeTargets.Parameter) != 0)
491                                         return true;
492                                 else
493                                         return false;
494                         } else if (element is Property /* || element is Indexer ||
495                                    element is InterfaceProperty || element is InterfaceIndexer*/) {
496                                 if ((targets & AttributeTargets.Property) != 0)
497                                         return true;
498                                 else
499                                         return false;
500                         } else if (element is AssemblyBuilder){
501                                 if ((targets & AttributeTargets.Assembly) != 0)
502                                         return true;
503                                 else
504                                         return false;
505                         } else if (element is ModuleBuilder){
506                                         if ((targets & AttributeTargets.Module) != 0)
507                                                 return true;
508                                         else
509                                                 return false;
510                                 }  
511
512                         return false;
513                 }
514
515                 /// <summary>
516                 /// Returns AttributeUsage attribute for this type
517                 /// </summary>
518                 public AttributeUsageAttribute GetAttributeUsage ()
519                 {
520                         Class attr_class = (Class) TypeManager.LookupClass (Type);
521
522                         if (attr_class == null) {
523                                 object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true);
524                                 return (AttributeUsageAttribute)usage_attr [0];
525                         }
526                 
527                         return attr_class.AttributeUsage;
528                 }
529
530                 //
531                 // This method should be invoked to pull the DefaultPropName attribute from an
532                 // Indexer if it exists.
533                 //
534                 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
535                 {
536                         if (opt_attrs == null)
537                                 return null;
538
539                         foreach (Attribute a in opt_attrs.Attrs) {
540                                 if (a.ResolveType (ec) == null)
541                                         return null;
542                                         
543                                 if (a.Type != TypeManager.indexer_name_type)
544                                         continue;
545
546                                 //
547                                 // So we have found an DefaultPropName, pull the data out.
548                                 //
549                                 if (a.Arguments == null || a.Arguments [0] == null){
550                                         Error_AttributeConstructorMismatch (a.Location);
551                                         return null;
552                                 }
553                                 ArrayList pos_args = (ArrayList) a.Arguments [0];
554                                 if (pos_args.Count == 0){
555                                         Error_AttributeConstructorMismatch (a.Location);
556                                         return null;
557                                 }
558                                         
559                                 Argument arg = (Argument) pos_args [0];
560                                 if (!arg.Resolve (ec, a.Location))
561                                         return null;
562                                         
563                                 Expression e = arg.Expr;
564                                 if (!(e is StringConstant)){
565                                         Error_AttributeConstructorMismatch (a.Location);
566                                         return null;
567                                 }
568
569                                 //
570                                 // Remove the attribute from the list
571                                 //
572                                 opt_attrs.Attrs.Remove (a);
573
574                                 return (((StringConstant) e).Value);
575                         }
576                         return null;
577                 }
578
579                 //
580                 // This pulls the condition name out of a Conditional attribute
581                 //
582                 public string Conditional_GetConditionName ()
583                 {
584                         //
585                         // So we have a Conditional, pull the data out.
586                         //
587                         if (Arguments == null || Arguments [0] == null){
588                                 Error_AttributeConstructorMismatch (Location);
589                                 return null;
590                         }
591
592                         ArrayList pos_args = (ArrayList) Arguments [0];
593                         if (pos_args.Count != 1){
594                                 Error_AttributeConstructorMismatch (Location);
595                                 return null;
596                         }
597
598                         Argument arg = (Argument) pos_args [0]; 
599                         if (!(arg.Expr is StringConstant)){
600                                 Error_AttributeConstructorMismatch (Location);
601                                 return null;
602                         }
603
604                         return ((StringConstant) arg.Expr).Value;
605                 }
606
607                 //
608                 // This pulls the obsolete message and error flag out of an Obsolete attribute
609                 //
610                 public string Obsolete_GetObsoleteMessage (out bool is_error)
611                 {
612                         is_error = false;
613                         //
614                         // So we have an Obsolete, pull the data out.
615                         //
616                         if (Arguments == null || Arguments [0] == null)
617                                 return "";
618
619                         ArrayList pos_args = (ArrayList) Arguments [0];
620                         if (pos_args.Count == 0)
621                                 return "";
622                         else if (pos_args.Count > 2){
623                                 Error_AttributeConstructorMismatch (Location);
624                                 return null;
625                         }
626
627                         Argument arg = (Argument) pos_args [0]; 
628                         if (!(arg.Expr is StringConstant)){
629                                 Error_AttributeConstructorMismatch (Location);
630                                 return null;
631                         }
632
633                         if (pos_args.Count == 2){
634                                 Argument arg2 = (Argument) pos_args [1];
635                                 if (!(arg2.Expr is BoolConstant)){
636                                         Error_AttributeConstructorMismatch (Location);
637                                         return null;
638                                 }
639                                 is_error = ((BoolConstant) arg2.Expr).Value;
640                         }
641
642                         return ((StringConstant) arg.Expr).Value;
643                 }
644
645                 
646                 /// <summary>
647                 /// Emit attribute for Attributable symbol
648                 /// </summary>
649                 public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr)
650                 {
651                         CustomAttributeBuilder cb = Resolve (ec);
652                         if (cb == null)
653                                 return;
654                 
655                         AttributeUsageAttribute usage_attr = GetAttributeUsage ();
656                         if ((usage_attr.ValidOn & ias.AttributeTargets) == 0) {
657                                 Report.Error (30662, Location, "Attribute" + Name + "is not valid on this declaration type. It is valid on " + GetValidTargets () + " declarations only.");
658                                 return;
659                         }
660                 
661                         ias.ApplyAttributeBuilder (this, cb);
662                 }
663
664                 //
665                 // Applies the attributes to the `builder'.
666                 //                                                                      
667                 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
668                                                     Attributes opt_attrs, Location loc)
669                 {
670                         if (opt_attrs == null)
671                                 return;
672
673                         foreach (Attribute a in opt_attrs.Attrs) {
674                                 CustomAttributeBuilder cb = a.Resolve (ec);
675
676                                 if (cb == null)
677                                         continue;
678
679                                 if (!(kind is TypeContainer))
680                                         if (!CheckAttribute (a, kind)) {
681                                                         Error_AttributeNotValidForElement (a, loc);
682                                                         return;
683                                         }
684
685                                 if (kind is Method || kind is Accessor) {
686                                         if (a.Type == TypeManager.methodimpl_attr_type) {
687                                                 if (a.ImplOptions == MethodImplOptions.InternalCall)
688                                                                 ((MethodBuilder) builder).SetImplementationFlags (MethodImplAttributes.InternalCall |   MethodImplAttributes.Runtime);
689                                         } else if (a.Type != TypeManager.dllimport_type){
690                                                         ((MethodBuilder) builder).SetCustomAttribute (cb);
691                                         }
692                                 }  else
693                                         throw new Exception ("Unknown kind: " + kind);
694                         }
695                 }
696
697                 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
698                                                           MethodAttributes flags, Type ret_type, Type [] param_types)
699                 {
700                         //
701                         // We extract from the attribute the information we need 
702                         //
703
704                         if (Arguments == null) {
705                                 Console.WriteLine ("Internal error : this is not supposed to happen !");
706                                 return null;
707                         }
708
709                         Type = CheckAttributeType (ec);
710                         if (Type == null)
711                                 return null;
712                         
713                         ArrayList named_args = new ArrayList ();
714                         
715                         ArrayList pos_args = (ArrayList) Arguments [0];
716                         if (Arguments.Count > 1)
717                                 named_args = (ArrayList) Arguments [1];
718                         
719
720                         string dll_name = null;
721                         
722                         Argument tmp = (Argument) pos_args [0];
723
724                         if (!tmp.Resolve (ec, Location))
725                                 return null;
726                         
727                         if (tmp.Expr is Constant)
728                                 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
729                         else { 
730                                 Error_AttributeArgumentNotValid ();
731                                 return null;
732                         }
733
734                         // Now we process the named arguments
735                         CallingConvention cc = CallingConvention.Winapi;
736                         CharSet charset = CharSet.Ansi;
737                         bool preserve_sig = true;
738                         /*bool exact_spelling = false;
739                         bool set_last_err = false;*/
740                         string entry_point = null;
741
742                         for (int i = 0; i < named_args.Count; i++) {
743
744                                 DictionaryEntry de = (DictionaryEntry) named_args [i];
745
746                                 string member_name = (string) de.Key;
747                                 Argument a  = (Argument) de.Value;
748
749                                 if (!a.Resolve (ec, Location))
750                                         return null;
751
752                                 Expression member = Expression.MemberLookup (
753                                         ec, Type, member_name, 
754                                         MemberTypes.Field | MemberTypes.Property,
755                                         BindingFlags.Public | BindingFlags.Instance,
756                                         Location);
757
758                                 if (member == null || !(member is FieldExpr)) {
759                                         Error_InvalidNamedArgument (member_name);
760                                         return null;
761                                 }
762
763                                 if (member is FieldExpr) {
764                                         FieldExpr fe = (FieldExpr) member;
765                                         FieldInfo fi = fe.FieldInfo;
766
767                                         if (fi.IsInitOnly) {
768                                                 Error_InvalidNamedArgument (member_name);
769                                                 return null;
770                                         }
771
772                                         if (a.Expr is Constant) {
773                                                 Constant c = (Constant) a.Expr;
774                                                 
775                                                 if (member_name == "CallingConvention")
776                                                         cc = (CallingConvention) c.GetValue ();
777                                                 else if (member_name == "CharSet")
778                                                         charset = (CharSet) c.GetValue ();
779                                                 else if (member_name == "EntryPoint")
780                                                         entry_point = (string) c.GetValue ();
781                                                 /*else if (member_name == "SetLastError")
782                                                         set_last_err = (bool) c.GetValue ();
783                                                 else if (member_name == "ExactSpelling")
784                                                         exact_spelling = (bool) c.GetValue ();*/
785                                                 else if (member_name == "PreserveSig")
786                                                         preserve_sig = (bool) c.GetValue ();
787                                         } else { 
788                                                 Error_AttributeArgumentNotValid ();
789                                                 return null;
790                                         }
791                                         
792                                 }
793                         }
794
795                         if (entry_point == null)
796                                 entry_point = name;
797                         
798                         MethodBuilder mb = builder.DefinePInvokeMethod (
799                                 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
800                                 CallingConventions.Standard,
801                                 ret_type,
802                                 param_types,
803                                 cc,
804                                 charset);
805
806                         if (preserve_sig)
807                                 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
808                         
809                         return mb;
810                 }
811
812                 public bool IsAssemblyAttribute {
813                         get {
814                                 return ExplicitTarget == "assembly";
815                         }
816                 }
817
818                 public bool IsModuleAttribute {
819                         get {
820                                 return ExplicitTarget == "module";
821                         }
822                 }
823         }
824         
825         public class Attributes {
826                 public ArrayList Attrs;
827                 public Location Location;
828                 
829                 public Attributes (Attribute a)
830                 {
831                         Attrs = new ArrayList ();
832                         Attrs.Add (a);
833                 }
834
835                 public Attributes (ArrayList attrs)
836                 {
837                         Attrs = attrs;
838                 }
839
840                 public void Add (Attribute attr)
841                 {
842                         Attrs.Add (attr);
843                 }
844
845                 public void Add (ArrayList attrs)
846                 {
847                         Attrs.AddRange (attrs);
848                 }
849
850                 public void Emit (EmitContext ec, Attributable ias)
851                 {
852                         ListDictionary ld = new ListDictionary ();
853         
854                         foreach (Attribute a in Attrs)
855                                 a.Emit (ec, ias, ld);
856                 }
857         }
858 }