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