Merge branch 'master' of github.com:mono/mono
[mono.git] / mcs / mcs / attribute.cs
1 //
2 // attribute.cs: Attribute Handler
3 //
4 // Author: Ravi Pratap (ravi@ximian.com)
5 //         Marek Safar (marek.safar@seznam.cz)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 //
12
13 using System;
14 using System.Collections.Generic;
15 using System.Runtime.InteropServices;
16 using System.Runtime.CompilerServices;
17 using System.Security; 
18 using System.Security.Permissions;
19 using System.Text;
20 using System.IO;
21
22 #if STATIC
23 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
24 using IKVM.Reflection;
25 using IKVM.Reflection.Emit;
26 #else
27 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
28 using System.Reflection;
29 using System.Reflection.Emit;
30 #endif
31
32 namespace Mono.CSharp {
33
34         /// <summary>
35         ///   Base class for objects that can have Attributes applied to them.
36         /// </summary>
37         public abstract class Attributable {
38                 //
39                 // Holds all attributes attached to this element
40                 //
41                 protected Attributes attributes;
42
43                 public void AddAttributes (Attributes attrs, IMemberContext context)
44                 {
45                         if (attrs == null)
46                                 return;
47
48                         if (attributes == null)
49                                 attributes = attrs;
50                         else
51                                 throw new NotImplementedException ();
52
53                         attributes.AttachTo (this, context);
54                 }
55
56                 public Attributes OptAttributes {
57                         get {
58                                 return attributes;
59                         }
60                         set {
61                                 attributes = value;
62                         }
63                 }
64
65                 /// <summary>
66                 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
67                 /// </summary>
68                 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
69
70                 /// <summary>
71                 /// Returns one AttributeTarget for this element.
72                 /// </summary>
73                 public abstract AttributeTargets AttributeTargets { get; }
74
75                 public abstract bool IsClsComplianceRequired ();
76
77                 /// <summary>
78                 /// Gets list of valid attribute targets for explicit target declaration.
79                 /// The first array item is default target. Don't break this rule.
80                 /// </summary>
81                 public abstract string[] ValidAttributeTargets { get; }
82         };
83
84         public class Attribute : Expression
85         {
86                 public readonly string ExplicitTarget;
87                 public AttributeTargets Target;
88                 readonly ATypeNameExpression expression;
89
90                 Arguments PosArguments;
91                 Arguments NamedArguments;
92
93                 bool resolve_error;
94                 bool arg_resolved;
95                 readonly bool nameEscaped;
96
97                 //
98                 // An attribute can be attached to multiple targets (e.g. multiple fields)
99                 //
100                 protected Attributable[] targets;
101
102                 //
103                 // A member context for the attribute, it's much easier to hold it here
104                 // than trying to pull it during resolve
105                 //
106                 IMemberContext context;
107
108                 public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
109                 static Assembly orig_sec_assembly;
110                 public static readonly object[] EmptyObject = new object [0];
111
112                 List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
113
114                 // Cache for parameter-less attributes
115                 static Dictionary<TypeSpec, MethodSpec> att_cache;
116
117                 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
118                 {
119                         this.expression = expr;
120                         if (args != null) {
121                                 PosArguments = args [0];
122                                 NamedArguments = args [1];                              
123                         }
124                         this.loc = loc;
125                         ExplicitTarget = target;
126                         this.nameEscaped = nameEscaped;
127                 }
128
129                 void AddModuleCharSet (ResolveContext rc)
130                 {
131                         const string dll_import_char_set = "CharSet";
132
133                         //
134                         // Only when not customized by user
135                         //
136                         if (HasField (dll_import_char_set))
137                                 return;
138
139                         if (!rc.Module.PredefinedTypes.CharSet.IsDefined) {
140                                 return;
141                         }
142
143                         if (NamedArguments == null)
144                                 NamedArguments = new Arguments (1);
145
146                         var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
147                         NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
148                 }
149
150                 public Attribute Clone ()
151                 {
152                         Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
153                         a.PosArguments = PosArguments;
154                         a.NamedArguments = NamedArguments;
155                         return a;
156                 }
157
158                 static Attribute ()
159                 {
160                         Reset ();
161                 }
162
163                 public static void Reset ()
164                 {
165                         att_cache = new Dictionary<TypeSpec, MethodSpec> ();
166                 }
167
168                 //
169                 // When the same attribute is attached to multiple fiels
170                 // we use @target field as a list of targets. The attribute
171                 // has to be resolved only once but emitted for each target.
172                 //
173                 public void AttachTo (Attributable target, IMemberContext context)
174                 {
175                         if (this.targets == null) {
176                                 this.targets = new Attributable[] { target };
177                                 this.context = context;
178                                 return;
179                         }
180
181                         // Resize target array
182                         Attributable[] new_array = new Attributable [this.targets.Length + 1];
183                         targets.CopyTo (new_array, 0);
184                         new_array [targets.Length] = target;
185                         this.targets = new_array;
186
187                         // No need to update context, different targets cannot have
188                         // different contexts, it's enough to remove same attributes
189                         // from secondary members.
190
191                         target.OptAttributes = null;
192                 }
193
194                 public ResolveContext CreateResolveContext ()
195                 {
196                         return new ResolveContext (context, ResolveContext.Options.ConstantScope);
197                 }
198
199                 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
200                 {
201                         rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
202                                       "must be fields which are not readonly, static, const or read-write properties which are " +
203                                       "public and not static",
204                               name.Name);
205                 }
206
207                 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
208                 {
209                         rc.Report.Error (655, name.Location,
210                                 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
211                                 name.Name);
212                 }
213
214                 public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
215                 {
216                         context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
217                 }
218                 
219                 public void Error_MissingGuidAttribute ()
220                 {
221                         Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
222                 }
223
224                 public void Error_MisusedExtensionAttribute ()
225                 {
226                         Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
227                 }
228
229                 public void Error_MisusedDynamicAttribute ()
230                 {
231                         Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
232                 }
233
234                 /// <summary>
235                 /// This is rather hack. We report many emit attribute error with same error to be compatible with
236                 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
237                 /// </summary>
238                 public void Error_AttributeEmitError (string inner)
239                 {
240                         Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
241                                       TypeManager.CSharpName (Type), inner);
242                 }
243
244                 public void Error_InvalidSecurityParent ()
245                 {
246                         Error_AttributeEmitError ("it is attached to invalid parent");
247                 }
248
249                 Attributable Owner {
250                         get {
251                                 return targets [0];
252                         }
253                 }
254
255                 protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
256                 {
257                         return expr.ResolveAsTypeTerminal (ec, false);
258                 }
259
260                 TypeSpec ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
261                 {
262                         TypeExpr te = ResolveAsTypeTerminal (expr, context);
263                         if (te == null)
264                                 return null;
265
266                         TypeSpec t = te.Type;
267                         if (t.IsAttribute) {
268                                 is_attr = true;
269                         } else {
270                                 Report.SymbolRelatedToPreviousError (t);
271                                 Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
272                         }
273                         return t;
274                 }
275
276                 /// <summary>
277                 ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
278                 /// </summary>
279                 void ResolveAttributeType ()
280                 {
281                         SessionReportPrinter resolve_printer = new SessionReportPrinter ();
282                         ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer);
283
284                         bool t1_is_attr = false;
285                         bool t2_is_attr = false;
286                         TypeSpec t1, t2;
287                         ATypeNameExpression expanded = null;
288
289                         try {
290                                 t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
291
292                                 if (nameEscaped) {
293                                         t2 = null;
294                                 } else {
295                                         expanded = (ATypeNameExpression) expression.Clone (null);
296                                         expanded.Name += "Attribute";
297
298                                         t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
299                                 }
300
301                                 resolve_printer.EndSession ();
302                         } finally {
303                                 context.Module.Compiler.Report.SetPrinter (prev_recorder);
304                         }
305
306                         if (t1_is_attr && t2_is_attr) {
307                                 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
308                                         GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
309                                 resolve_error = true;
310                                 return;
311                         }
312
313                         if (t1_is_attr) {
314                                 Type = t1;
315                                 return;
316                         }
317
318                         if (t2_is_attr) {
319                                 Type = t2;
320                                 return;
321                         }
322
323                         resolve_printer.Merge (prev_recorder);
324                         resolve_error = true;
325                 }
326
327                 public virtual TypeSpec ResolveType ()
328                 {
329                         if (Type == null && !resolve_error)
330                                 ResolveAttributeType ();
331                         return Type;
332                 }
333
334                 public override string GetSignatureForError ()
335                 {
336                         if (Type != null)
337                                 return TypeManager.CSharpName (Type);
338
339                         return expression.GetSignatureForError ();
340                 }
341
342                 public bool HasSecurityAttribute {
343                         get {
344                                 PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
345                                 return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false);
346                         }
347                 }
348
349                 public bool IsValidSecurityAttribute ()
350                 {
351                         return HasSecurityAttribute && IsSecurityActionValid (false);
352                 }
353
354                 static bool IsValidArgumentType (TypeSpec t)
355                 {
356                         if (t.IsArray) {
357                                 var ac = (ArrayContainer) t;
358                                 if (ac.Rank > 1)
359                                         return false;
360
361                                 t = ac.Element;
362                         }
363
364                         switch (t.BuildinType) {
365                         case BuildinTypeSpec.Type.Int:
366                         case BuildinTypeSpec.Type.UInt:
367                         case BuildinTypeSpec.Type.Long:
368                         case BuildinTypeSpec.Type.ULong:
369                         case BuildinTypeSpec.Type.Float:
370                         case BuildinTypeSpec.Type.Double:
371                         case BuildinTypeSpec.Type.Char:
372                         case BuildinTypeSpec.Type.Short:
373                         case BuildinTypeSpec.Type.Bool:
374                         case BuildinTypeSpec.Type.SByte:
375                         case BuildinTypeSpec.Type.Byte:
376                         case BuildinTypeSpec.Type.UShort:
377
378                         case BuildinTypeSpec.Type.String:
379                         case BuildinTypeSpec.Type.Object:
380                         case BuildinTypeSpec.Type.Dynamic:
381                         case BuildinTypeSpec.Type.Type:
382                                 return true;
383                         }
384
385                         return t.IsEnum;
386                 }
387
388                 // TODO: Don't use this ambiguous value
389                 public string Name {
390                         get { return expression.Name; }
391                 }
392
393                 public Report Report {
394                         get { return context.Module.Compiler.Report; }
395                 }
396
397                 public MethodSpec Resolve ()
398                 {
399                         if (resolve_error)
400                                 return null;
401
402                         resolve_error = true;
403                         arg_resolved = true;
404
405                         if (Type == null) {
406                                 ResolveAttributeType ();
407                                 if (Type == null)
408                                         return null;
409                         }
410
411                         if (Type.IsAbstract) {
412                                 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
413                                 return null;
414                         }
415
416                         ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
417                         if (obsolete_attr != null) {
418                                 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
419                         }
420
421                         MethodSpec ctor;
422                         // Try if the attribute is simple has been resolved before
423                         if (PosArguments == null && NamedArguments == null) {
424                                 if (att_cache.TryGetValue (Type, out ctor)) {
425                                         resolve_error = false;
426                                         return ctor;
427                                 }
428                         }
429
430                         ResolveContext rc = CreateResolveContext ();
431                         ctor = ResolveConstructor (rc);
432                         if (ctor == null) {
433                                 return null;
434                         }
435
436                         //
437                         // Add [module: DefaultCharSet] to all DllImport import attributes
438                         //
439                         var module = context.Module;
440                         if (Type == module.PredefinedAttributes.DllImport && module.HasDefaultCharSet) {
441                                 AddModuleCharSet (rc);
442                         }
443
444                         if (NamedArguments != null && !ResolveNamedArguments (rc)) {
445                                 return null;
446                         }
447
448                         resolve_error = false;
449                         return ctor;
450                 }
451
452                 protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
453                 {
454                         if (PosArguments != null) {
455                                 bool dynamic;
456                                 PosArguments.Resolve (ec, out dynamic);
457                                 if (dynamic) {
458                                         Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
459                                         return null;
460                                 }
461                         }
462
463                         return ConstructorLookup (ec, Type, ref PosArguments, loc);
464                 }
465
466                 protected virtual bool ResolveNamedArguments (ResolveContext ec)
467                 {
468                         int named_arg_count = NamedArguments.Count;
469                         var seen_names = new List<string> (named_arg_count);
470
471                         named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
472                         
473                         foreach (NamedArgument a in NamedArguments) {
474                                 string name = a.Name;
475                                 if (seen_names.Contains (name)) {
476                                         ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
477                                         continue;
478                                 }                       
479         
480                                 seen_names.Add (name);
481
482                                 a.Resolve (ec);
483
484                                 Expression member = Expression.MemberLookup (ec, ec.CurrentType, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
485
486                                 if (member == null) {
487                                         member = Expression.MemberLookup (null, ec.CurrentType, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
488
489                                         if (member != null) {
490                                                 // TODO: ec.Report.SymbolRelatedToPreviousError (member);
491                                                 Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
492                                                 return false;
493                                         }
494                                 }
495
496                                 if (member == null){
497                                         Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
498                                         return false;
499                                 }
500                                 
501                                 if (!(member is PropertyExpr || member is FieldExpr)) {
502                                         Error_InvalidNamedArgument (ec, a);
503                                         return false;
504                                 }
505
506                                 ObsoleteAttribute obsolete_attr;
507
508                                 if (member is PropertyExpr) {
509                                         var pi = ((PropertyExpr) member).PropertyInfo;
510
511                                         if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
512                                                 ec.Report.SymbolRelatedToPreviousError (pi);
513                                                 Error_InvalidNamedArgument (ec, a);
514                                                 return false;
515                                         }
516
517                                         if (!IsValidArgumentType (member.Type)) {
518                                                 ec.Report.SymbolRelatedToPreviousError (pi);
519                                                 Error_InvalidNamedArgumentType (ec, a);
520                                                 return false;
521                                         }
522
523                                         obsolete_attr = pi.GetAttributeObsolete ();
524                                         pi.MemberDefinition.SetIsAssigned ();
525                                 } else {
526                                         var fi = ((FieldExpr) member).Spec;
527
528                                         if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
529                                                 Error_InvalidNamedArgument (ec, a);
530                                                 return false;
531                                         }
532
533                                         if (!IsValidArgumentType (member.Type)) {
534                                                 ec.Report.SymbolRelatedToPreviousError (fi);
535                                                 Error_InvalidNamedArgumentType (ec, a);
536                                                 return false;
537                                         }
538
539                                         obsolete_attr = fi.GetAttributeObsolete ();
540                                         fi.MemberDefinition.SetIsAssigned ();
541                                 }
542
543                                 if (obsolete_attr != null && !context.IsObsolete)
544                                         AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
545
546                                 if (a.Type != member.Type) {
547                                         a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
548                                 }
549
550                                 if (a.Expr != null)
551                                         named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
552                         }
553
554                         return true;
555                 }
556
557                 /// <summary>
558                 ///   Get a string containing a list of valid targets for the attribute 'attr'
559                 /// </summary>
560                 public string GetValidTargets ()
561                 {
562                         StringBuilder sb = new StringBuilder ();
563                         AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
564
565                         if ((targets & AttributeTargets.Assembly) != 0)
566                                 sb.Append ("assembly, ");
567
568                         if ((targets & AttributeTargets.Module) != 0)
569                                 sb.Append ("module, ");
570
571                         if ((targets & AttributeTargets.Class) != 0)
572                                 sb.Append ("class, ");
573
574                         if ((targets & AttributeTargets.Struct) != 0)
575                                 sb.Append ("struct, ");
576
577                         if ((targets & AttributeTargets.Enum) != 0)
578                                 sb.Append ("enum, ");
579
580                         if ((targets & AttributeTargets.Constructor) != 0)
581                                 sb.Append ("constructor, ");
582
583                         if ((targets & AttributeTargets.Method) != 0)
584                                 sb.Append ("method, ");
585
586                         if ((targets & AttributeTargets.Property) != 0)
587                                 sb.Append ("property, indexer, ");
588
589                         if ((targets & AttributeTargets.Field) != 0)
590                                 sb.Append ("field, ");
591
592                         if ((targets & AttributeTargets.Event) != 0)
593                                 sb.Append ("event, ");
594
595                         if ((targets & AttributeTargets.Interface) != 0)
596                                 sb.Append ("interface, ");
597
598                         if ((targets & AttributeTargets.Parameter) != 0)
599                                 sb.Append ("parameter, ");
600
601                         if ((targets & AttributeTargets.Delegate) != 0)
602                                 sb.Append ("delegate, ");
603
604                         if ((targets & AttributeTargets.ReturnValue) != 0)
605                                 sb.Append ("return, ");
606
607                         if ((targets & AttributeTargets.GenericParameter) != 0)
608                                 sb.Append ("type parameter, ");
609
610                         return sb.Remove (sb.Length - 2, 2).ToString ();
611                 }
612
613                 public AttributeUsageAttribute GetAttributeUsageAttribute ()
614                 {
615                         if (!arg_resolved)
616                                 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
617                                 // But because a lot of attribute class code must be rewritten will be better to wait...
618                                 Resolve ();
619
620                         if (resolve_error)
621                                 return DefaultUsageAttribute;
622
623                         AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
624
625                         var field = GetNamedValue ("AllowMultiple") as BoolConstant;
626                         if (field != null)
627                                 usage_attribute.AllowMultiple = field.Value;
628
629                         field = GetNamedValue ("Inherited") as BoolConstant;
630                         if (field != null)
631                                 usage_attribute.Inherited = field.Value;
632
633                         return usage_attribute;
634                 }
635
636                 /// <summary>
637                 /// Returns custom name of indexer
638                 /// </summary>
639                 public string GetIndexerAttributeValue ()
640                 {
641                         if (!arg_resolved)
642                                 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
643                                 // But because a lot of attribute class code must be rewritten will be better to wait...
644                                 Resolve ();
645
646                         if (resolve_error)
647                                 return null;
648
649                         return ((Constant) PosArguments [0].Expr).GetValue () as string;
650                 }
651
652                 /// <summary>
653                 /// Returns condition of ConditionalAttribute
654                 /// </summary>
655                 public string GetConditionalAttributeValue ()
656                 {
657                         if (!arg_resolved)
658                                 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
659                                 // But because a lot of attribute class code must be rewritten will be better to wait...
660                                 Resolve ();
661
662                         if (resolve_error)
663                                 return null;
664
665                         return ((Constant) PosArguments[0].Expr).GetValue () as string;
666                 }
667
668                 /// <summary>
669                 /// Creates the instance of ObsoleteAttribute from this attribute instance
670                 /// </summary>
671                 public ObsoleteAttribute GetObsoleteAttribute ()
672                 {
673                         if (!arg_resolved) {
674                                 // corlib only case when obsolete is used before is resolved
675                                 var c = type.MemberDefinition as Class;
676                                 if (c != null && !c.HasMembersDefined)
677                                         c.Define ();
678                                 
679                                 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
680                                 // But because a lot of attribute class code must be rewritten will be better to wait...
681                                 Resolve ();
682                         }
683
684                         if (resolve_error)
685                                 return null;
686
687                         if (PosArguments == null)
688                                 return new ObsoleteAttribute ();
689
690                         string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
691                         if (PosArguments.Count == 1)
692                                 return new ObsoleteAttribute (msg);
693
694                         return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
695                 }
696
697                 /// <summary>
698                 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
699                 /// before ApplyAttribute. We need to resolve the arguments.
700                 /// This situation occurs when class deps is differs from Emit order.  
701                 /// </summary>
702                 public bool GetClsCompliantAttributeValue ()
703                 {
704                         if (!arg_resolved)
705                                 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
706                                 // But because a lot of attribute class code must be rewritten will be better to wait...
707                                 Resolve ();
708
709                         if (resolve_error)
710                                 return false;
711
712                         return ((BoolConstant) PosArguments[0].Expr).Value;
713                 }
714
715                 public TypeSpec GetCoClassAttributeValue ()
716                 {
717                         if (!arg_resolved)
718                                 Resolve ();
719
720                         if (resolve_error)
721                                 return null;
722
723                         return GetArgumentType ();
724                 }
725
726                 public bool CheckTarget ()
727                 {
728                         string[] valid_targets = Owner.ValidAttributeTargets;
729                         if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
730                                 Target = Owner.AttributeTargets;
731                                 return true;
732                         }
733
734                         // TODO: we can skip the first item
735                         if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
736                                 switch (ExplicitTarget) {
737                                 case "return": Target = AttributeTargets.ReturnValue; return true;
738                                 case "param": Target = AttributeTargets.Parameter; return true;
739                                 case "field": Target = AttributeTargets.Field; return true;
740                                 case "method": Target = AttributeTargets.Method; return true;
741                                 case "property": Target = AttributeTargets.Property; return true;
742                                 case "module": Target = AttributeTargets.Module; return true;
743                                 }
744                                 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
745                         }
746                                 
747                         StringBuilder sb = new StringBuilder ();
748                         foreach (string s in valid_targets) {
749                                 sb.Append (s);
750                                 sb.Append (", ");
751                         }
752                         sb.Remove (sb.Length - 2, 2);
753                         Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
754                                 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
755                         return false;
756                 }
757
758                 /// <summary>
759                 /// Tests permitted SecurityAction for assembly or other types
760                 /// </summary>
761                 protected virtual bool IsSecurityActionValid (bool for_assembly)
762                 {
763                         SecurityAction action = GetSecurityActionValue ();
764
765                         switch (action) {
766 #pragma warning disable 618
767                         case SecurityAction.Demand:
768                         case SecurityAction.Assert:
769                         case SecurityAction.Deny:
770                         case SecurityAction.PermitOnly:
771                         case SecurityAction.LinkDemand:
772                         case SecurityAction.InheritanceDemand:
773                                 if (!for_assembly)
774                                         return true;
775                                 break;
776
777                         case SecurityAction.RequestMinimum:
778                         case SecurityAction.RequestOptional:
779                         case SecurityAction.RequestRefuse:
780                                 if (for_assembly)
781                                         return true;
782                                 break;
783 #pragma warning restore 618
784
785                         default:
786                                 Error_AttributeEmitError ("SecurityAction is out of range");
787                                 return false;
788                         }
789
790                         Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
791                         return false;
792                 }
793
794                 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
795                 {
796                         return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
797                 }
798
799                 /// <summary>
800                 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
801                 /// </summary>
802                 /// <returns></returns>
803                 public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
804                 {
805 #if STATIC
806                         object[] values = new object [PosArguments.Count];
807                         for (int i = 0; i < values.Length; ++i)
808                                 values [i] = ((Constant) PosArguments [i].Expr).GetValue ();
809
810                         PropertyInfo[] prop;
811                         object[] prop_values;
812                         if (named_values == null) {
813                                 prop = null;
814                                 prop_values = null;
815                         } else {
816                                 prop = new PropertyInfo[named_values.Count];
817                                 prop_values = new object [named_values.Count];
818                                 for (int i = 0; i < prop.Length; ++i) {
819                                         prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
820                                         prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
821                                 }
822                         }
823
824                         if (permissions == null)
825                                 permissions = new SecurityType ();
826
827                         var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
828                         permissions.Add (cab);
829 #else
830                         throw new NotSupportedException ();
831 #endif
832                 }
833
834                 public Constant GetNamedValue (string name)
835                 {
836                         if (named_values == null)
837                                 return null;
838
839                         for (int i = 0; i < named_values.Count; ++i) {
840                                 if (named_values [i].Value.Name == name)
841                                         return named_values [i].Value.Expr as Constant;
842                         }
843
844                         return null;
845                 }
846
847                 public CharSet GetCharSetValue ()
848                 {
849                         return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
850                 }
851
852                 public bool HasField (string fieldName)
853                 {
854                         if (named_values == null)
855                                 return false;
856
857                         foreach (var na in named_values) {
858                                 if (na.Value.Name == fieldName)
859                                         return true;
860                         }
861
862                         return false;
863                 }
864
865                 //
866                 // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
867                 // 
868                 public bool IsInternalCall ()
869                 {
870                         MethodImplOptions options = 0;
871                         if (PosArguments.Count == 1) {
872                                 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
873                         } else if (HasField ("Value")) {
874                                 var named = GetNamedValue ("Value");
875                                 options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
876                         }
877
878                         return (options & MethodImplOptions.InternalCall) != 0;
879                 }
880
881                 //
882                 // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
883                 // 
884                 public bool IsExplicitLayoutKind ()
885                 {
886                         if (PosArguments == null || PosArguments.Count != 1)
887                                 return false;
888
889                         var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
890                         return value == LayoutKind.Explicit;
891                 }
892
893                 public Expression GetParameterDefaultValue ()
894                 {
895                         if (PosArguments == null)
896                                 return null;
897
898                         return PosArguments[0].Expr;
899                 }
900
901                 public override bool Equals (object obj)
902                 {
903                         Attribute a = obj as Attribute;
904                         if (a == null)
905                                 return false;
906
907                         return Type == a.Type && Target == a.Target;
908                 }
909
910                 public override int GetHashCode ()
911                 {
912                         return type.GetHashCode () ^ Target.GetHashCode ();
913                 }
914
915                 /// <summary>
916                 /// Emit attribute for Attributable symbol
917                 /// </summary>
918                 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
919                 {
920                         var ctor = Resolve ();
921                         if (ctor == null)
922                                 return;
923
924                         var predefined = context.Module.PredefinedAttributes;
925
926                         AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
927                         if ((usage_attr.ValidOn & Target) == 0) {
928                                 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
929                                               "It is valid on `{1}' declarations only",
930                                         GetSignatureForError (), GetValidTargets ());
931                                 return;
932                         }
933
934                         byte[] cdata;
935                         if (PosArguments == null && named_values == null) {
936                                 cdata = AttributeEncoder.Empty;
937                         } else {
938                                 AttributeEncoder encoder = new AttributeEncoder ();
939
940                                 if (PosArguments != null) {
941                                         var param_types = ctor.Parameters.Types;
942                                         for (int j = 0; j < PosArguments.Count; ++j) {
943                                                 var pt = param_types[j];
944                                                 var arg_expr = PosArguments[j].Expr;
945                                                 if (j == 0) {
946                                                         if (Type == predefined.IndexerName || Type == predefined.Conditional) {
947                                                                 string v = ((StringConstant) arg_expr).Value;
948                                                                 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
949                                                                         context.Module.Compiler.Report.Error (633, arg_expr.Location,
950                                                                                 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
951                                                                 }
952                                                         } else if (Type == predefined.Guid) {
953                                                                 try {
954                                                                         string v = ((StringConstant) arg_expr).Value;
955                                                                         new Guid (v);
956                                                                 } catch (Exception e) {
957                                                                         Error_AttributeEmitError (e.Message);
958                                                                         return;
959                                                                 }
960                                                         } else if (Type == predefined.AttributeUsage) {
961                                                                 int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
962                                                                 if (v == 0) {
963                                                                         context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
964                                                                                 "System.AttributeUsage");
965                                                                 }
966                                                         } else if (Type == predefined.MarshalAs) {
967                                                                 if (PosArguments.Count == 1) {
968                                                                         var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
969                                                                         if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
970                                                                                 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
971                                                                         }
972                                                                 }
973                                                         } else if (Type == predefined.DllImport) {
974                                                                 if (PosArguments.Count == 1) {
975                                                                         var value = ((Constant) PosArguments[0].Expr).GetValue () as string;
976                                                                         if (string.IsNullOrEmpty (value))
977                                                                                 Error_AttributeEmitError ("DllName cannot be empty");
978                                                                 }
979                                                         } else if (Type == predefined.MethodImpl && pt.BuildinType == BuildinTypeSpec.Type.Short &&
980                                                                 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
981                                                                 Error_AttributeEmitError ("Incorrect argument value.");
982                                                                 return;
983                                                         }
984                                                 }
985
986                                                 arg_expr.EncodeAttributeValue (context, encoder, pt);
987                                         }
988                                 }
989
990                                 if (named_values != null) {
991                                         encoder.Encode ((ushort) named_values.Count);
992                                         foreach (var na in named_values) {
993                                                 if (na.Key is FieldExpr)
994                                                         encoder.Encode ((byte) 0x53);
995                                                 else
996                                                         encoder.Encode ((byte) 0x54);
997
998                                                 encoder.Encode (na.Key.Type);
999                                                 encoder.Encode (na.Value.Name);
1000                                                 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1001                                         }
1002                                 } else {
1003                                         encoder.EncodeEmptyNamedArguments ();
1004                                 }
1005
1006                                 cdata = encoder.ToArray ();
1007                         }
1008
1009                         try {
1010                                 foreach (Attributable target in targets)
1011                                         target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1012                         } catch (Exception e) {
1013                                 Error_AttributeEmitError (e.Message);
1014                                 return;
1015                         }
1016
1017                         if (!usage_attr.AllowMultiple && allEmitted != null) {
1018                                 if (allEmitted.ContainsKey (this)) {
1019                                         var a = allEmitted [this];
1020                                         if (a == null) {
1021                                                 a = new List<Attribute> (2);
1022                                                 allEmitted [this] = a;
1023                                         }
1024                                         a.Add (this);
1025                                 } else {
1026                                         allEmitted.Add (this, null);
1027                                 }
1028                         }
1029
1030                         if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1031                                 return;
1032
1033                         // Here we are testing attribute arguments for array usage (error 3016)
1034                         if (Owner.IsClsComplianceRequired ()) {
1035                                 if (PosArguments != null)
1036                                         PosArguments.CheckArrayAsAttribute (context.Module.Compiler);
1037                         
1038                                 if (NamedArguments == null)
1039                                         return;
1040
1041                                 NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1042                         }
1043                 }
1044
1045                 private Expression GetValue () 
1046                 {
1047                         if (PosArguments == null || PosArguments.Count < 1)
1048                                 return null;
1049
1050                         return PosArguments [0].Expr;
1051                 }
1052
1053                 public string GetString () 
1054                 {
1055                         Expression e = GetValue ();
1056                         if (e is StringConstant)
1057                                 return ((StringConstant)e).Value;
1058                         return null;
1059                 }
1060
1061                 public bool GetBoolean () 
1062                 {
1063                         Expression e = GetValue ();
1064                         if (e is BoolConstant)
1065                                 return ((BoolConstant)e).Value;
1066                         return false;
1067                 }
1068
1069                 public TypeSpec GetArgumentType ()
1070                 {
1071                         TypeOf e = GetValue () as TypeOf;
1072                         if (e == null)
1073                                 return null;
1074                         return e.TypeArgument;
1075                 }
1076
1077                 public override Expression CreateExpressionTree (ResolveContext ec)
1078                 {
1079                         throw new NotSupportedException ("ET");
1080                 }
1081
1082                 protected override Expression DoResolve (ResolveContext ec)
1083                 {
1084                         throw new NotImplementedException ();
1085                 }
1086
1087                 public override void Emit (EmitContext ec)
1088                 {
1089                         throw new NotImplementedException ();
1090                 }
1091         }
1092         
1093
1094         /// <summary>
1095         /// For global attributes (assembly, module) we need special handling.
1096         /// Attributes can be located in the several files
1097         /// </summary>
1098         public class GlobalAttribute : Attribute
1099         {
1100                 public readonly NamespaceEntry ns;
1101
1102                 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1103                                         Arguments[] args, Location loc, bool nameEscaped):
1104                         base (target, expression, args, loc, nameEscaped)
1105                 {
1106                         this.ns = ns;
1107                 }
1108
1109                 void Enter ()
1110                 {
1111                         // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1112                         // each time a new file is parsed.  However, we need to use the NamespaceEntry
1113                         // in effect where the attribute was used.  Since code elsewhere cannot assume
1114                         // that the NamespaceEntry is right, just overwrite it.
1115                         //
1116                         // Precondition: RootContext.ToplevelTypes == null
1117
1118                         if (RootContext.ToplevelTypes.NamespaceEntry != null)
1119                                 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1120
1121                         RootContext.ToplevelTypes.NamespaceEntry = ns;
1122                 }
1123
1124                 protected override bool IsSecurityActionValid (bool for_assembly)
1125                 {
1126                         return base.IsSecurityActionValid (true);
1127                 }
1128
1129                 void Leave ()
1130                 {
1131                         RootContext.ToplevelTypes.NamespaceEntry = null;
1132                 }
1133
1134                 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1135                 {
1136                         try {
1137                                 Enter ();
1138                                 return base.ResolveAsTypeTerminal (expr, ec);
1139                         }
1140                         finally {
1141                                 Leave ();
1142                         }
1143                 }
1144
1145                 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1146                 {
1147                         try {
1148                                 Enter ();
1149                                 return base.ResolveConstructor (ec);
1150                         }
1151                         finally {
1152                                 Leave ();
1153                         }
1154                 }
1155
1156                 protected override bool ResolveNamedArguments (ResolveContext ec)
1157                 {
1158                         try {
1159                                 Enter ();
1160                                 return base.ResolveNamedArguments (ec);
1161                         }
1162                         finally {
1163                                 Leave ();
1164                         }
1165                 }
1166         }
1167
1168         public class Attributes {
1169                 public readonly List<Attribute> Attrs;
1170
1171                 public Attributes (Attribute a)
1172                 {
1173                         Attrs = new List<Attribute> ();
1174                         Attrs.Add (a);
1175                 }
1176
1177                 public Attributes (List<Attribute> attrs)
1178                 {
1179                         Attrs = attrs;
1180                 }
1181
1182                 public void AddAttributes (List<Attribute> attrs)
1183                 {
1184                         Attrs.AddRange (attrs);
1185                 }
1186
1187                 public void AttachTo (Attributable attributable, IMemberContext context)
1188                 {
1189                         foreach (Attribute a in Attrs)
1190                                 a.AttachTo (attributable, context);
1191                 }
1192
1193                 public Attributes Clone ()
1194                 {
1195                         var al = new List<Attribute> (Attrs.Count);
1196                         foreach (Attribute a in Attrs)
1197                                 al.Add (a.Clone ());
1198
1199                         return new Attributes (al);
1200                 }
1201
1202                 /// <summary>
1203                 /// Checks whether attribute target is valid for the current element
1204                 /// </summary>
1205                 public bool CheckTargets ()
1206                 {
1207                         foreach (Attribute a in Attrs) {
1208                                 if (!a.CheckTarget ())
1209                                         return false;
1210                         }
1211                         return true;
1212                 }
1213
1214                 public Attribute Search (PredefinedAttribute t)
1215                 {
1216                         return Search (null, t);
1217                 }
1218
1219                 public Attribute Search (string explicitTarget, PredefinedAttribute t)
1220                 {
1221                         foreach (Attribute a in Attrs) {
1222                                 if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1223                                         continue;
1224
1225                                 if (a.ResolveType () == t)
1226                                         return a;
1227                         }
1228                         return null;
1229                 }
1230
1231                 /// <summary>
1232                 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1233                 /// </summary>
1234                 public Attribute[] SearchMulti (PredefinedAttribute t)
1235                 {
1236                         List<Attribute> ar = null;
1237
1238                         foreach (Attribute a in Attrs) {
1239                                 if (a.ResolveType () == t) {
1240                                         if (ar == null)
1241                                                 ar = new List<Attribute> (Attrs.Count);
1242                                         ar.Add (a);
1243                                 }
1244                         }
1245
1246                         return ar == null ? null : ar.ToArray ();
1247                 }
1248
1249                 public void Emit ()
1250                 {
1251                         CheckTargets ();
1252
1253                         Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1254
1255                         foreach (Attribute a in Attrs)
1256                                 a.Emit (ld);
1257
1258                         if (ld == null || ld.Count == 0)
1259                                 return;
1260
1261                         foreach (var d in ld) {
1262                                 if (d.Value == null)
1263                                         continue;
1264
1265                                 Attribute a = d.Key;
1266
1267                                 foreach (Attribute collision in d.Value)
1268                                         a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1269
1270                                 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1271                                         a.GetSignatureForError ());
1272                         }
1273                 }
1274
1275                 public bool Contains (PredefinedAttribute t)
1276                 {
1277                         return Search (t) != null;
1278                 }
1279         }
1280
1281         public sealed class AttributeEncoder
1282         {
1283                 [Flags]
1284                 public enum EncodedTypeProperties
1285                 {
1286                         None = 0,
1287                         DynamicType = 1,
1288                         TypeParameter = 1 << 1
1289                 }
1290
1291                 public static readonly byte[] Empty;
1292
1293                 byte[] buffer;
1294                 int pos;
1295                 const ushort Version = 1;
1296
1297                 static AttributeEncoder ()
1298                 {
1299                         Empty = new byte[4];
1300                         Empty[0] = (byte) Version;
1301                 }
1302
1303                 public AttributeEncoder ()
1304                 {
1305                         buffer = new byte[32];
1306                         Encode (Version);
1307                 }
1308
1309                 public void Encode (bool value)
1310                 {
1311                         Encode (value ? (byte) 1 : (byte) 0);
1312                 }
1313
1314                 public void Encode (byte value)
1315                 {
1316                         if (pos == buffer.Length)
1317                                 Grow (1);
1318
1319                         buffer [pos++] = value;
1320                 }
1321
1322                 public void Encode (sbyte value)
1323                 {
1324                         Encode ((byte) value);
1325                 }
1326
1327                 public void Encode (short value)
1328                 {
1329                         if (pos + 2 > buffer.Length)
1330                                 Grow (2);
1331
1332                         buffer[pos++] = (byte) value;
1333                         buffer[pos++] = (byte) (value >> 8);
1334                 }
1335
1336                 public void Encode (ushort value)
1337                 {
1338                         Encode ((short) value);
1339                 }
1340
1341                 public void Encode (int value)
1342                 {
1343                         if (pos + 4 > buffer.Length)
1344                                 Grow (4);
1345
1346                         buffer[pos++] = (byte) value;
1347                         buffer[pos++] = (byte) (value >> 8);
1348                         buffer[pos++] = (byte) (value >> 16);
1349                         buffer[pos++] = (byte) (value >> 24);
1350                 }
1351
1352                 public void Encode (uint value)
1353                 {
1354                         Encode ((int) value);
1355                 }
1356
1357                 public void Encode (long value)
1358                 {
1359                         if (pos + 8 > buffer.Length)
1360                                 Grow (8);
1361
1362                         buffer[pos++] = (byte) value;
1363                         buffer[pos++] = (byte) (value >> 8);
1364                         buffer[pos++] = (byte) (value >> 16);
1365                         buffer[pos++] = (byte) (value >> 24);
1366                         buffer[pos++] = (byte) (value >> 32);
1367                         buffer[pos++] = (byte) (value >> 40);
1368                         buffer[pos++] = (byte) (value >> 48);
1369                         buffer[pos++] = (byte) (value >> 56);
1370                 }
1371
1372                 public void Encode (ulong value)
1373                 {
1374                         Encode ((long) value);
1375                 }
1376
1377                 public void Encode (float value)
1378                 {
1379                         Encode (SingleConverter.SingleToInt32Bits (value));
1380                 }
1381
1382                 public void Encode (double value)
1383                 {
1384                         Encode (BitConverter.DoubleToInt64Bits (value));
1385                 }
1386
1387                 public void Encode (string value)
1388                 {
1389                         if (value == null) {
1390                                 Encode ((byte) 0xFF);
1391                                 return;
1392                         }
1393
1394                         var buf = Encoding.UTF8.GetBytes(value);
1395                         WriteCompressedValue (buf.Length);
1396
1397                         if (pos + buf.Length > buffer.Length)
1398                                 Grow (buf.Length);
1399
1400                         Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1401                         pos += buf.Length;
1402                 }
1403
1404                 public EncodedTypeProperties Encode (TypeSpec type)
1405                 {
1406                         switch (type.BuildinType) {
1407                         case BuildinTypeSpec.Type.Bool:
1408                                 Encode ((byte) 0x02);
1409                                 break;
1410                         case BuildinTypeSpec.Type.Char:
1411                                 Encode ((byte) 0x03);
1412                                 break;
1413                         case BuildinTypeSpec.Type.SByte:
1414                                 Encode ((byte) 0x04);
1415                                 break;
1416                         case BuildinTypeSpec.Type.Byte:
1417                                 Encode ((byte) 0x05);
1418                                 break;
1419                         case BuildinTypeSpec.Type.Short:
1420                                 Encode ((byte) 0x06);
1421                                 break;
1422                         case BuildinTypeSpec.Type.UShort:
1423                                 Encode ((byte) 0x07);
1424                                 break;
1425                         case BuildinTypeSpec.Type.Int:
1426                                 Encode ((byte) 0x08);
1427                                 break;
1428                         case BuildinTypeSpec.Type.UInt:
1429                                 Encode ((byte) 0x09);
1430                                 break;
1431                         case BuildinTypeSpec.Type.Long:
1432                                 Encode ((byte) 0x0A);
1433                                 break;
1434                         case BuildinTypeSpec.Type.ULong:
1435                                 Encode ((byte) 0x0B);
1436                                 break;
1437                         case BuildinTypeSpec.Type.Float:
1438                                 Encode ((byte) 0x0C);
1439                                 break;
1440                         case BuildinTypeSpec.Type.Double:
1441                                 Encode ((byte) 0x0D);
1442                                 break;
1443                         case BuildinTypeSpec.Type.String:
1444                                 Encode ((byte) 0x0E);
1445                                 break;
1446                         case BuildinTypeSpec.Type.Type:
1447                                 Encode ((byte) 0x50);
1448                                 break;
1449                         case BuildinTypeSpec.Type.Object:
1450                                 Encode ((byte) 0x51);
1451                                 break;
1452                         case BuildinTypeSpec.Type.Dynamic:
1453                                 Encode ((byte) 0x51);
1454                                 return EncodedTypeProperties.DynamicType;
1455                         default:
1456                                 if (type.IsArray) {
1457                                         Encode ((byte) 0x1D);
1458                                         return Encode (TypeManager.GetElementType (type));
1459                                 }
1460
1461                                 if (type.Kind == MemberKind.Enum) {
1462                                         Encode ((byte) 0x55);
1463                                         EncodeTypeName (type);
1464                                 }
1465
1466                                 break;
1467                         }
1468
1469                         return EncodedTypeProperties.None;
1470                 }
1471
1472                 public void EncodeTypeName (TypeSpec type)
1473                 {
1474                         var old_type = type.GetMetaInfo ();
1475                         Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1476                 }
1477
1478                 //
1479                 // Encodes single property named argument per call
1480                 //
1481                 public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1482                 {
1483                         Encode ((ushort) 1);    // length
1484                         Encode ((byte) 0x54); // property
1485                         Encode (property.MemberType);
1486                         Encode (property.Name);
1487                         value.EncodeAttributeValue (null, this, property.MemberType);
1488                 }
1489
1490                 //
1491                 // Encodes single field named argument per call
1492                 //
1493                 public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1494                 {
1495                         Encode ((ushort) 1);    // length
1496                         Encode ((byte) 0x53); // field
1497                         Encode (field.MemberType);
1498                         Encode (field.Name);
1499                         value.EncodeAttributeValue (null, this, field.MemberType);
1500                 }
1501
1502                 public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1503                 {
1504                         Encode ((ushort) members.Length);
1505
1506                         for (int i = 0; i < members.Length; ++i)
1507                         {
1508                                 var member = members[i];
1509
1510                                 if (member.Kind == MemberKind.Field)
1511                                         Encode ((byte) 0x53);
1512                                 else if (member.Kind == MemberKind.Property)
1513                                         Encode ((byte) 0x54);
1514                                 else
1515                                         throw new NotImplementedException (member.Kind.ToString ());
1516
1517                                 Encode (member.MemberType);
1518                                 Encode (member.Name);
1519                                 values [i].EncodeAttributeValue (null, this, member.MemberType);
1520                         }
1521                 }
1522
1523                 public void EncodeEmptyNamedArguments ()
1524                 {
1525                         Encode ((ushort) 0);
1526                 }
1527
1528                 void Grow (int inc)
1529                 {
1530                         int size = System.Math.Max (pos * 4, pos + inc + 2);
1531                         Array.Resize (ref buffer, size);
1532                 }
1533
1534                 void WriteCompressedValue (int value)
1535                 {
1536                         if (value < 0x80) {
1537                                 Encode ((byte) value);
1538                                 return;
1539                         }
1540
1541                         if (value < 0x4000) {
1542                                 Encode ((byte) (0x80 | (value >> 8)));
1543                                 Encode ((byte) value);
1544                                 return;
1545                         }
1546
1547                         Encode (value);
1548                 }
1549
1550                 public byte[] ToArray ()
1551                 {
1552                         byte[] buf = new byte[pos];
1553                         Array.Copy (buffer, buf, pos);
1554                         return buf;
1555                 }
1556         }
1557
1558
1559         /// <summary>
1560         /// Helper class for attribute verification routine.
1561         /// </summary>
1562         static class AttributeTester
1563         {
1564                 public enum Result {
1565                         Ok,
1566                         RefOutArrayError,
1567                         ArrayArrayError
1568                 }
1569
1570                 /// <summary>
1571                 /// Returns true if parameters of two compared methods are CLS-Compliant.
1572                 /// It tests differing only in ref or out, or in array rank.
1573                 /// </summary>
1574                 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb) 
1575                 {
1576                         TypeSpec [] types_a = pa.Types;
1577                         TypeSpec [] types_b = pb.Types;
1578                         if (types_a == null || types_b == null)
1579                                 return Result.Ok;
1580
1581                         if (types_a.Length != types_b.Length)
1582                                 return Result.Ok;
1583
1584                         Result result = Result.Ok;
1585                         for (int i = 0; i < types_b.Length; ++i) {
1586                                 TypeSpec aType = types_a [i];
1587                                 TypeSpec bType = types_b [i];
1588
1589                                 var ac_a = aType as ArrayContainer;
1590                                 var ac_b = aType as ArrayContainer;
1591
1592                                 if (ac_a != null && ac_b != null) {
1593                                         if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1594                                                 result = Result.RefOutArrayError;
1595                                                 continue;
1596                                         }
1597
1598                                         if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1599                                                 result = Result.ArrayArrayError;
1600                                                 continue;
1601                                         }
1602                                 }
1603
1604                                 if (aType != bType)
1605                                         return Result.Ok;
1606
1607                                 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1608                                 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1609                                         result = Result.RefOutArrayError;
1610                         }
1611                         return result;
1612                 }
1613
1614                 /// <summary>
1615                 /// Common method for Obsolete error/warning reporting.
1616                 /// </summary>
1617                 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1618                 {
1619                         if (oa.IsError) {
1620                                 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1621                                 return;
1622                         }
1623
1624                         if (oa.Message == null || oa.Message.Length == 0) {
1625                                 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1626                                 return;
1627                         }
1628                         Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1629                 }
1630         }
1631
1632         //
1633         // Predefined attribute types
1634         //
1635         public class PredefinedAttributes
1636         {
1637                 // Build-in attributes
1638                 public readonly PredefinedAttribute ParamArray;
1639                 public readonly PredefinedAttribute Out;
1640
1641                 // Optional attributes
1642                 public readonly PredefinedAttribute Obsolete;
1643                 public readonly PredefinedAttribute DllImport;
1644                 public readonly PredefinedAttribute MethodImpl;
1645                 public readonly PredefinedAttribute MarshalAs;
1646                 public readonly PredefinedAttribute In;
1647                 public readonly PredefinedAttribute IndexerName;
1648                 public readonly PredefinedAttribute Conditional;
1649                 public readonly PredefinedAttribute CLSCompliant;
1650                 public readonly PredefinedAttribute Security;
1651                 public readonly PredefinedAttribute Required;
1652                 public readonly PredefinedAttribute Guid;
1653                 public readonly PredefinedAttribute AssemblyCulture;
1654                 public readonly PredefinedAttribute AssemblyVersion;
1655                 public readonly PredefinedAttribute AssemblyAlgorithmId;
1656                 public readonly PredefinedAttribute AssemblyFlags;
1657                 public readonly PredefinedAttribute AssemblyFileVersion;
1658                 public readonly PredefinedAttribute ComImport;
1659                 public readonly PredefinedAttribute CoClass;
1660                 public readonly PredefinedAttribute AttributeUsage;
1661                 public readonly PredefinedAttribute DefaultParameterValue;
1662                 public readonly PredefinedAttribute OptionalParameter;
1663                 public readonly PredefinedAttribute UnverifiableCode;
1664
1665                 // New in .NET 2.0
1666                 public readonly PredefinedAttribute DefaultCharset;
1667                 public readonly PredefinedAttribute TypeForwarder;
1668                 public readonly PredefinedAttribute FixedBuffer;
1669                 public readonly PredefinedAttribute CompilerGenerated;
1670                 public readonly PredefinedAttribute InternalsVisibleTo;
1671                 public readonly PredefinedAttribute RuntimeCompatibility;
1672                 public readonly PredefinedAttribute DebuggerHidden;
1673                 public readonly PredefinedAttribute UnsafeValueType;
1674
1675                 // New in .NET 3.5
1676                 public readonly PredefinedAttribute Extension;
1677
1678                 // New in .NET 4.0
1679                 public readonly PredefinedDynamicAttribute Dynamic;
1680
1681                 //
1682                 // Optional types which are used as types and for member lookup
1683                 //
1684                 public readonly PredefinedAttribute DefaultMember;
1685                 public readonly PredefinedDecimalAttribute DecimalConstant;
1686                 public readonly PredefinedAttribute StructLayout;
1687                 public readonly PredefinedAttribute FieldOffset;
1688
1689                 public PredefinedAttributes (ModuleContainer module)
1690                 {
1691                         ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1692                         Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1693                         ParamArray.Resolve (Location.Null);
1694                         Out.Resolve (Location.Null);
1695
1696                         Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1697                         DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1698                         MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1699                         MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1700                         In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1701                         IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1702                         Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1703                         CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1704                         Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1705                         Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1706                         Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1707                         AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1708                         AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1709                         AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1710                         AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1711                         AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1712                         ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1713                         CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1714                         AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1715                         DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1716                         OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1717                         UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1718
1719                         DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1720                         TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1721                         FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1722                         CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1723                         InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1724                         RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1725                         DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1726                         UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1727
1728                         Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1729
1730                         Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1731
1732                         DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1733                         DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1734                         StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1735                         FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1736
1737                         // TODO: Should define only attributes which are used for comparison
1738                         const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1739                                 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1740
1741                         foreach (var fi in GetType ().GetFields (all_fields)) {
1742                                 ((PredefinedAttribute) fi.GetValue (this)).Define ();
1743                         }
1744                 }
1745         }
1746
1747         public class PredefinedAttribute : PredefinedType
1748         {
1749                 protected MethodSpec ctor;
1750                 List<PropertySpec> properties;
1751
1752                 public PredefinedAttribute (ModuleContainer module, string ns, string name)
1753                         : base (module, MemberKind.Class, ns, name)
1754                 {
1755                 }
1756
1757                 #region Properties
1758
1759                 public MethodSpec Constructor {
1760                         get {
1761                                 return ctor;
1762                         }
1763                 }
1764
1765                 #endregion
1766
1767                 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1768                 {
1769                         return type == pa.type && pa.type != null;
1770                 }
1771
1772                 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1773                 {
1774                         return type != pa.type;
1775                 }
1776
1777                 public override int GetHashCode ()
1778                 {
1779                         return base.GetHashCode ();
1780                 }
1781
1782                 public override bool Equals (object obj)
1783                 {
1784                         throw new NotSupportedException ();
1785                 }
1786
1787                 public void EmitAttribute (ConstructorBuilder builder)
1788                 {
1789                         if (ResolveBuilder ())
1790                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1791                 }
1792
1793                 public void EmitAttribute (MethodBuilder builder)
1794                 {
1795                         if (ResolveBuilder ())
1796                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1797                 }
1798
1799                 public void EmitAttribute (PropertyBuilder builder)
1800                 {
1801                         if (ResolveBuilder ())
1802                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1803                 }
1804
1805                 public void EmitAttribute (FieldBuilder builder)
1806                 {
1807                         if (ResolveBuilder ())
1808                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1809                 }
1810
1811                 public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
1812                 {
1813                         builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1814                 }
1815
1816                 public void EmitAttribute (TypeBuilder builder)
1817                 {
1818                         if (ResolveBuilder ())
1819                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1820                 }
1821
1822                 public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
1823                 {
1824                         builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1825                 }
1826
1827                 public void EmitAttribute (AssemblyBuilder builder)
1828                 {
1829                         if (ResolveBuilder ())
1830                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1831                 }
1832
1833                 public void EmitAttribute (ModuleBuilder builder)
1834                 {
1835                         if (ResolveBuilder ())
1836                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1837                 }
1838
1839                 public void EmitAttribute (ParameterBuilder builder)
1840                 {
1841                         if (ResolveBuilder ())
1842                                 builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1843                 }
1844
1845                 public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
1846                 {
1847                         builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
1848                 }
1849
1850                 ConstructorInfo GetCtorMetaInfo ()
1851                 {
1852                         return (ConstructorInfo) ctor.GetMetaInfo ();
1853                 }
1854
1855                 public PropertySpec GetProperty (string name, TypeSpec memberType, Location loc)
1856                 {
1857                         PropertySpec spec;
1858
1859                         if (properties != null) {
1860                                 spec = properties.Find (l => l.Name == name);
1861                         } else {
1862                                 spec = null;
1863                         }
1864
1865                         if (spec == null) {
1866                                 spec = TypeManager.GetPredefinedProperty (type, name, loc, memberType);
1867
1868                                 if (spec != null) {
1869                                         if (properties == null) {
1870                                                 properties = new List<PropertySpec> ();
1871                                         }
1872
1873                                         properties.Add (spec);
1874                                 }
1875                         }
1876
1877                         return spec;
1878                 }
1879
1880                 public bool ResolveBuilder ()
1881                 {
1882                         if (ctor != null)
1883                                 return true;
1884
1885                         //
1886                         // Handle all parameter-less attributes as optional
1887                         //
1888                         if (!IsDefined)
1889                                 return false;
1890
1891                         ctor = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
1892                         return ctor != null;
1893                 }
1894
1895                 public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
1896                 {
1897                         if (ctor != null)
1898                                 throw new InternalErrorException ("Predefined ctor redefined");
1899
1900                         if (Resolve (loc) == null)
1901                                 return false;
1902
1903                         ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
1904                         return ctor != null;
1905                 }
1906         }
1907
1908         public class PredefinedDecimalAttribute : PredefinedAttribute
1909         {
1910                 public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1911                         : base (module, ns, name)
1912                 {
1913                 }
1914
1915                 public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1916                 {
1917                         if (Resolve (loc) == null)
1918                                 return;
1919
1920                         if (ctor == null && !ResolveConstructor (loc, module.Compiler.BuildinTypes.Byte, module.Compiler.BuildinTypes.Byte,
1921                                 module.Compiler.BuildinTypes.UInt, module.Compiler.BuildinTypes.UInt, module.Compiler.BuildinTypes.UInt))
1922                                 return;
1923
1924                         int[] bits = decimal.GetBits (value);
1925                         AttributeEncoder encoder = new AttributeEncoder ();
1926                         encoder.Encode ((byte) (bits[3] >> 16));
1927                         encoder.Encode ((byte) (bits[3] >> 31));
1928                         encoder.Encode ((uint) bits[2]);
1929                         encoder.Encode ((uint) bits[1]);
1930                         encoder.Encode ((uint) bits[0]);
1931                         encoder.EncodeEmptyNamedArguments ();
1932
1933                         EmitAttribute (builder, encoder);
1934                 }
1935
1936                 public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1937                 {
1938                         if (Resolve (loc) == null)
1939                                 return;
1940
1941                         if (ctor == null && !ResolveConstructor (loc, module.Compiler.BuildinTypes.Byte, module.Compiler.BuildinTypes.Byte,
1942                                 module.Compiler.BuildinTypes.UInt, module.Compiler.BuildinTypes.UInt, module.Compiler.BuildinTypes.UInt))
1943                                 return;
1944
1945                         int[] bits = decimal.GetBits (value);
1946                         AttributeEncoder encoder = new AttributeEncoder ();
1947                         encoder.Encode ((byte) (bits[3] >> 16));
1948                         encoder.Encode ((byte) (bits[3] >> 31));
1949                         encoder.Encode ((uint) bits[2]);
1950                         encoder.Encode ((uint) bits[1]);
1951                         encoder.Encode ((uint) bits[0]);
1952                         encoder.EncodeEmptyNamedArguments ();
1953
1954                         EmitAttribute (builder, encoder);
1955                 }
1956         }
1957
1958         public class PredefinedDynamicAttribute : PredefinedAttribute
1959         {
1960                 MethodSpec tctor;
1961
1962                 public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
1963                         : base (module, ns, name)
1964                 {
1965                 }
1966
1967                 public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
1968                 {
1969                         if (ResolveTransformationCtor (loc)) {
1970                                 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1971                                 builder.SetCustomAttribute (cab);
1972                         }
1973                 }
1974
1975                 public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
1976                 {
1977                         if (ResolveTransformationCtor (loc)) {
1978                                 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1979                                 builder.SetCustomAttribute (cab);
1980                         }
1981                 }
1982
1983                 public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
1984                 {
1985                         if (ResolveTransformationCtor (loc)) {
1986                                 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1987                                 builder.SetCustomAttribute (cab);
1988                         }
1989                 }
1990
1991                 public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
1992                 {
1993                         if (ResolveTransformationCtor (loc)) {
1994                                 var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1995                                 builder.SetCustomAttribute (cab);
1996                         }
1997                 }
1998
1999                 //
2000                 // When any element of the type is a dynamic type
2001                 //
2002                 // This method builds a transformation array for dynamic types
2003                 // used in places where DynamicAttribute cannot be applied to.
2004                 // It uses bool flag when type is of dynamic type and each
2005                 // section always starts with "false" for some reason.
2006                 //
2007                 // LAMESPEC: This should be part of C# specification
2008                 // 
2009                 // Example: Func<dynamic, int, dynamic[]>
2010                 // Transformation: { false, true, false, false, true }
2011                 //
2012                 static bool[] GetTransformationFlags (TypeSpec t)
2013                 {
2014                         bool[] element;
2015                         var ac = t as ArrayContainer;
2016                         if (ac != null) {
2017                                 element = GetTransformationFlags (ac.Element);
2018                                 if (element == null)
2019                                         return null;
2020
2021                                 bool[] res = new bool[element.Length + 1];
2022                                 res[0] = false;
2023                                 Array.Copy (element, 0, res, 1, element.Length);
2024                                 return res;
2025                         }
2026
2027                         if (t == null)
2028                                 return null;
2029
2030                         if (t.IsGeneric) {
2031                                 List<bool> transform = null;
2032                                 var targs = t.TypeArguments;
2033                                 for (int i = 0; i < targs.Length; ++i) {
2034                                         element = GetTransformationFlags (targs[i]);
2035                                         if (element != null) {
2036                                                 if (transform == null) {
2037                                                         transform = new List<bool> ();
2038                                                         for (int ii = 0; ii <= i; ++ii)
2039                                                                 transform.Add (false);
2040                                                 }
2041
2042                                                 transform.AddRange (element);
2043                                         } else if (transform != null) {
2044                                                 transform.Add (false);
2045                                         }
2046                                 }
2047
2048                                 if (transform != null)
2049                                         return transform.ToArray ();
2050                         }
2051
2052                         if (t.BuildinType == BuildinTypeSpec.Type.Dynamic)
2053                                 return new bool[] { true };
2054
2055                         return null;
2056                 }
2057
2058                 bool ResolveTransformationCtor (Location loc)
2059                 {
2060                         if (tctor != null)
2061                                 return true;
2062
2063                         if (Resolve (loc) == null)
2064                                 return false;
2065
2066                         tctor = TypeManager.GetPredefinedConstructor (type, Location.Null, ArrayContainer.MakeType (module, module.Compiler.BuildinTypes.Bool));
2067                         return tctor != null;
2068                 }
2069         }
2070 }