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