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