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