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