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