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