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