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