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