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