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