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