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