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