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