1204e11b79037982270ba6820a823a08b3734348
[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 arg_expr = PosArguments[j].Expr;
1135                                         if (j == 0) {
1136                                                 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
1137                                                         string v = ((StringConstant) arg_expr).Value;
1138                                                         if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
1139                                                                 context.Compiler.Report.Error (633, arg_expr.Location,
1140                                                                         "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1141                                                         }
1142                                                 } else if (Type == predefined.Guid) {
1143                                                         try {
1144                                                                 string v = ((StringConstant) arg_expr).Value;
1145                                                                 new Guid (v);
1146                                                         } catch (Exception e) {
1147                                                                 Error_AttributeEmitError (e.Message);
1148                                                         }
1149                                                 } else if (Type == predefined.AttributeUsage) {
1150                                                         int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
1151                                                         if (v == 0) {
1152                                                                 context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1153                                                                         "System.AttributeUsage");
1154                                                         }
1155                                                 }
1156                                         } else if (j == 1) {
1157                                                 if (Type == predefined.MethodImpl && param_types[j] == TypeManager.short_type &&
1158                                                         !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetTypedValue ())) {
1159                                                         Error_AttributeEmitError ("Incorrect argument value.");
1160                                                 }
1161                                         }
1162
1163                                         arg_expr.EncodeAttributeValue (context, encoder, param_types[j]);
1164                                 }
1165                         }
1166
1167                         if (named_values != null) {
1168                                 encoder.Stream.Write ((ushort) named_values.Count);
1169                                 foreach (var na in named_values) {
1170                                         if (na.Key is FieldExpr)
1171                                                 encoder.Stream.Write ((byte) 0x53);
1172                                         else
1173                                                 encoder.Stream.Write ((byte) 0x54);
1174
1175                                         encoder.Encode (na.Key.Type);
1176                                         encoder.Encode (na.Value.Name);
1177                                         na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1178                                 }
1179                         } else {
1180                                 encoder.Stream.Write ((ushort) 0);
1181                         }
1182
1183                         byte[] cdata = encoder.ToArray ();
1184
1185                         try {
1186                                 foreach (Attributable target in targets)
1187                                         target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1188                         } catch (Exception e) {
1189                                 Error_AttributeEmitError (e.Message);
1190                                 return;
1191                         }
1192
1193                         if (!usage_attr.AllowMultiple && allEmitted != null) {
1194                                 if (allEmitted.ContainsKey (this)) {
1195                                         var a = allEmitted [this];
1196                                         if (a == null) {
1197                                                 a = new List<Attribute> (2);
1198                                                 allEmitted [this] = a;
1199                                         }
1200                                         a.Add (this);
1201                                 } else {
1202                                         allEmitted.Add (this, null);
1203                                 }
1204                         }
1205
1206                         if (!RootContext.VerifyClsCompliance)
1207                                 return;
1208
1209                         // Here we are testing attribute arguments for array usage (error 3016)
1210                         if (Owner.IsClsComplianceRequired ()) {
1211                                 if (PosArguments != null)
1212                                         PosArguments.CheckArrayAsAttribute (context.Compiler);
1213                         
1214                                 if (NamedArguments == null)
1215                                         return;
1216
1217                                 NamedArguments.CheckArrayAsAttribute (context.Compiler);
1218                         }
1219                 }
1220
1221                 private Expression GetValue () 
1222                 {
1223                         if (PosArguments == null || PosArguments.Count < 1)
1224                                 return null;
1225
1226                         return PosArguments [0].Expr;
1227                 }
1228
1229                 public string GetString () 
1230                 {
1231                         Expression e = GetValue ();
1232                         if (e is StringConstant)
1233                                 return ((StringConstant)e).Value;
1234                         return null;
1235                 }
1236
1237                 public bool GetBoolean () 
1238                 {
1239                         Expression e = GetValue ();
1240                         if (e is BoolConstant)
1241                                 return ((BoolConstant)e).Value;
1242                         return false;
1243                 }
1244
1245                 public Type GetArgumentType ()
1246                 {
1247                         TypeOf e = GetValue () as TypeOf;
1248                         if (e == null)
1249                                 return null;
1250                         return e.TypeArgument;
1251                 }
1252
1253                 public override Expression CreateExpressionTree (ResolveContext ec)
1254                 {
1255                         throw new NotSupportedException ("ET");
1256                 }
1257
1258                 protected override Expression DoResolve (ResolveContext ec)
1259                 {
1260                         throw new NotImplementedException ();
1261                 }
1262
1263                 public override void Emit (EmitContext ec)
1264                 {
1265                         throw new NotImplementedException ();
1266                 }
1267         }
1268         
1269
1270         /// <summary>
1271         /// For global attributes (assembly, module) we need special handling.
1272         /// Attributes can be located in the several files
1273         /// </summary>
1274         public class GlobalAttribute : Attribute
1275         {
1276                 public readonly NamespaceEntry ns;
1277
1278                 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1279                                         Arguments[] args, Location loc, bool nameEscaped):
1280                         base (target, expression, args, loc, nameEscaped)
1281                 {
1282                         this.ns = ns;
1283                 }
1284                 
1285                 public override void AttachTo (Attributable target, IMemberContext context)
1286                 {
1287                         if (ExplicitTarget == "assembly") {
1288                                 base.AttachTo (CodeGen.Assembly, context);
1289                                 return;
1290                         }
1291
1292                         if (ExplicitTarget == "module") {
1293                                 base.AttachTo (RootContext.ToplevelTypes, context);
1294                                 return;
1295                         }
1296
1297                         throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
1298                 }
1299
1300                 void Enter ()
1301                 {
1302                         // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1303                         // each time a new file is parsed.  However, we need to use the NamespaceEntry
1304                         // in effect where the attribute was used.  Since code elsewhere cannot assume
1305                         // that the NamespaceEntry is right, just overwrite it.
1306                         //
1307                         // Precondition: RootContext.ToplevelTypes == null
1308
1309                         if (RootContext.ToplevelTypes.NamespaceEntry != null)
1310                                 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1311
1312                         RootContext.ToplevelTypes.NamespaceEntry = ns;
1313                 }
1314
1315                 protected override bool IsSecurityActionValid (bool for_assembly)
1316                 {
1317                         return base.IsSecurityActionValid (true);
1318                 }
1319
1320                 void Leave ()
1321                 {
1322                         RootContext.ToplevelTypes.NamespaceEntry = null;
1323                 }
1324
1325                 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1326                 {
1327                         try {
1328                                 Enter ();
1329                                 return base.ResolveAsTypeTerminal (expr, ec);
1330                         }
1331                         finally {
1332                                 Leave ();
1333                         }
1334                 }
1335
1336                 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1337                 {
1338                         try {
1339                                 Enter ();
1340                                 return base.ResolveConstructor (ec);
1341                         }
1342                         finally {
1343                                 Leave ();
1344                         }
1345                 }
1346
1347                 protected override bool ResolveNamedArguments (ResolveContext ec)
1348                 {
1349                         try {
1350                                 Enter ();
1351                                 return base.ResolveNamedArguments (ec);
1352                         }
1353                         finally {
1354                                 Leave ();
1355                         }
1356                 }
1357         }
1358
1359         public class Attributes {
1360                 public readonly List<Attribute> Attrs;
1361
1362                 public Attributes (Attribute a)
1363                 {
1364                         Attrs = new List<Attribute> ();
1365                         Attrs.Add (a);
1366                 }
1367
1368                 public Attributes (List<Attribute> attrs)
1369                 {
1370                         Attrs = attrs;
1371                 }
1372
1373                 public void AddAttributes (List<Attribute> attrs)
1374                 {
1375                         Attrs.AddRange (attrs);
1376                 }
1377
1378                 public void AttachTo (Attributable attributable, IMemberContext context)
1379                 {
1380                         foreach (Attribute a in Attrs)
1381                                 a.AttachTo (attributable, context);
1382                 }
1383
1384                 public Attributes Clone ()
1385                 {
1386                         var al = new List<Attribute> (Attrs.Count);
1387                         foreach (Attribute a in Attrs)
1388                                 al.Add (a.Clone ());
1389
1390                         return new Attributes (al);
1391                 }
1392
1393                 /// <summary>
1394                 /// Checks whether attribute target is valid for the current element
1395                 /// </summary>
1396                 public bool CheckTargets ()
1397                 {
1398                         foreach (Attribute a in Attrs) {
1399                                 if (!a.CheckTarget ())
1400                                         return false;
1401                         }
1402                         return true;
1403                 }
1404
1405                 public Attribute Search (PredefinedAttribute t)
1406                 {
1407                         foreach (Attribute a in Attrs) {
1408                                 if (a.ResolveType () == t)
1409                                         return a;
1410                         }
1411                         return null;
1412                 }
1413
1414                 /// <summary>
1415                 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1416                 /// </summary>
1417                 public Attribute[] SearchMulti (PredefinedAttribute t)
1418                 {
1419                         List<Attribute> ar = null;
1420
1421                         foreach (Attribute a in Attrs) {
1422                                 if (a.ResolveType () == t) {
1423                                         if (ar == null)
1424                                                 ar = new List<Attribute> (Attrs.Count);
1425                                         ar.Add (a);
1426                                 }
1427                         }
1428
1429                         return ar == null ? null : ar.ToArray ();
1430                 }
1431
1432                 public void Emit ()
1433                 {
1434                         CheckTargets ();
1435
1436                         Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1437
1438                         foreach (Attribute a in Attrs)
1439                                 a.Emit (ld);
1440
1441                         if (ld == null || ld.Count == 0)
1442                                 return;
1443
1444                         foreach (var d in ld) {
1445                                 if (d.Value == null)
1446                                         continue;
1447
1448                                 Attribute a = d.Key;
1449
1450                                 foreach (Attribute collision in d.Value)
1451                                         a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1452
1453                                 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1454                                         a.GetSignatureForError ());
1455                         }
1456                 }
1457
1458                 public bool Contains (PredefinedAttribute t)
1459                 {
1460                         return Search (t) != null;
1461                 }
1462         }
1463
1464         public struct AttributeEncoder
1465         {
1466                 public readonly BinaryWriter Stream;
1467
1468                 public AttributeEncoder (bool empty)
1469                 {
1470                         if (empty) {
1471                                 Stream = null;
1472                                 return;
1473                         }
1474
1475                         Stream = new BinaryWriter (new MemoryStream ());
1476                         const ushort version = 1;
1477                         Stream.Write (version);
1478                 }
1479
1480                 public void Encode (string value)
1481                 {
1482                         if (value == null)
1483                                 throw new ArgumentNullException ();
1484
1485                         var buf = Encoding.UTF8.GetBytes(value);
1486                         WriteCompressedValue (buf.Length);
1487                         Stream.Write (buf);
1488                 }
1489
1490                 public void Encode (Type type)
1491                 {
1492                         if (type == TypeManager.bool_type) {
1493                                 Stream.Write ((byte) 0x02);
1494                         } else if (type == TypeManager.char_type) {
1495                                 Stream.Write ((byte) 0x03);
1496                         } else if (type == TypeManager.sbyte_type) {
1497                                 Stream.Write ((byte) 0x04);
1498                         } else if (type == TypeManager.byte_type) {
1499                                 Stream.Write ((byte) 0x05);
1500                         } else if (type == TypeManager.short_type) {
1501                                 Stream.Write ((byte) 0x06);
1502                         } else if (type == TypeManager.ushort_type) {
1503                                 Stream.Write ((byte) 0x07);
1504                         } else if (type == TypeManager.int32_type) {
1505                                 Stream.Write ((byte) 0x08);
1506                         } else if (type == TypeManager.uint32_type) {
1507                                 Stream.Write ((byte) 0x09);
1508                         } else if (type == TypeManager.int64_type) {
1509                                 Stream.Write ((byte) 0x0A);
1510                         } else if (type == TypeManager.uint64_type) {
1511                                 Stream.Write ((byte) 0x0B);
1512                         } else if (type == TypeManager.float_type) {
1513                                 Stream.Write ((byte) 0x0C);
1514                         } else if (type == TypeManager.double_type) {
1515                                 Stream.Write ((byte) 0x0D);
1516                         } else if (type == TypeManager.string_type) {
1517                                 Stream.Write ((byte) 0x0E);
1518                         } else if (type == TypeManager.type_type) {
1519                                 Stream.Write ((byte) 0x50);
1520                         } else if (type == TypeManager.object_type) {
1521                                 Stream.Write ((byte) 0x51);
1522                         } else if (TypeManager.IsEnumType (type)) {
1523                                 Stream.Write ((byte) 0x55);
1524                                 EncodeTypeName (type);
1525                         } else if (type.IsArray) {
1526                                 Stream.Write ((byte) 0x1D);
1527                                 Encode (TypeManager.GetElementType (type));
1528                         } else {
1529                                 throw new NotImplementedException (type.ToString ());
1530                         }
1531                 }
1532
1533                 public bool EncodeTypeName (Type type)
1534                 {
1535                         if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
1536                                 return false;
1537
1538                         Encode (CodeGen.Assembly.Builder == type.Assembly ? type.FullName : type.AssemblyQualifiedName);
1539                         return true;
1540                 }
1541
1542                 void WriteCompressedValue (int value)
1543                 {
1544                         if (value < 0x80) {
1545                                 Stream.Write ((byte) value);
1546                                 return;
1547                         }
1548
1549                         if (value < 0x4000) {
1550                                 Stream.Write ((byte) (0x80 | (value >> 8)));
1551                                 Stream.Write ((byte) value);
1552                                 return;
1553                         }
1554
1555                         Stream.Write (value);
1556                 }
1557
1558                 public byte[] ToArray ()
1559                 {
1560                         return ((MemoryStream) Stream.BaseStream).ToArray ();
1561                 }
1562         }
1563
1564
1565         /// <summary>
1566         /// Helper class for attribute verification routine.
1567         /// </summary>
1568         sealed class AttributeTester
1569         {
1570                 static Dictionary<Type, bool> analyzed_types;
1571                 static Dictionary<Type, ObsoleteAttribute> analyzed_types_obsolete;
1572                 static Dictionary<MemberInfo, ObsoleteAttribute> analyzed_member_obsolete;
1573                 static Dictionary<MethodBase, bool> analyzed_method_excluded;
1574 //              static Dictionary<FieldInfo, IFixedBuffer> fixed_buffer_cache;
1575
1576                 static AttributeTester ()
1577                 {
1578                         Reset ();
1579                 }
1580
1581                 private AttributeTester ()
1582                 {
1583                 }
1584
1585                 public static void Reset ()
1586                 {
1587                         analyzed_types = new Dictionary<Type, bool> (ReferenceEquality<Type>.Default);
1588                         analyzed_types_obsolete = new Dictionary<Type, ObsoleteAttribute> (ReferenceEquality<Type>.Default);
1589                         analyzed_member_obsolete = new Dictionary<MemberInfo, ObsoleteAttribute> (ReferenceEquality<MemberInfo>.Default);
1590                         analyzed_method_excluded = new Dictionary<MethodBase, bool> (ReferenceEquality<MethodBase>.Default);
1591 //                      fixed_buffer_cache = new Dictionary<FieldInfo, IFixedBuffer> (ReferenceEquality<FieldInfo>.Default);
1592                 }
1593
1594                 public enum Result {
1595                         Ok,
1596                         RefOutArrayError,
1597                         ArrayArrayError
1598                 }
1599
1600                 /// <summary>
1601                 /// Returns true if parameters of two compared methods are CLS-Compliant.
1602                 /// It tests differing only in ref or out, or in array rank.
1603                 /// </summary>
1604                 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb) 
1605                 {
1606                         Type [] types_a = pa.Types;
1607                         Type [] types_b = pb.Types;
1608                         if (types_a == null || types_b == null)
1609                                 return Result.Ok;
1610
1611                         if (types_a.Length != types_b.Length)
1612                                 return Result.Ok;
1613
1614                         Result result = Result.Ok;
1615                         for (int i = 0; i < types_b.Length; ++i) {
1616                                 Type aType = types_a [i];
1617                                 Type bType = types_b [i];
1618
1619                                 if (aType.IsArray && bType.IsArray) {
1620                                         Type a_el_type = TypeManager.GetElementType (aType);
1621                                         Type b_el_type = TypeManager.GetElementType (bType);
1622                                         if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) {
1623                                                 result = Result.RefOutArrayError;
1624                                                 continue;
1625                                         }
1626
1627                                         if (a_el_type.IsArray || b_el_type.IsArray) {
1628                                                 result = Result.ArrayArrayError;
1629                                                 continue;
1630                                         }
1631                                 }
1632
1633                                 if (aType != bType)
1634                                         return Result.Ok;
1635
1636                                 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1637                                 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1638                                         result = Result.RefOutArrayError;
1639                         }
1640                         return result;
1641                 }
1642
1643                 /// <summary>
1644                 /// This method tests the CLS compliance of external types. It doesn't test type visibility.
1645                 /// </summary>
1646                 public static bool IsClsCompliant (Type type) 
1647                 {
1648                         if (type == null)
1649                                 return true;
1650
1651                         bool result;
1652                         if (analyzed_types.TryGetValue (type, out result))
1653                                 return result;
1654
1655                         if (type.IsPointer) {
1656                                 analyzed_types.Add (type, false);
1657                                 return false;
1658                         }
1659
1660                         if (type.IsArray) {
1661                                 result = IsClsCompliant (TypeManager.GetElementType (type));
1662                         } else if (TypeManager.IsNullableType (type)) {
1663                                 result = IsClsCompliant (TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (type) [0]));
1664                         } else {
1665                                 result = AnalyzeTypeCompliance (type);
1666                         }
1667                         analyzed_types.Add (type, result);
1668                         return result;
1669                 }        
1670
1671                 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1672                 {
1673                         Module[] modules = GlobalRootNamespace.Instance.Modules;
1674                         if (modules == null)
1675                                 return;
1676
1677                         // The first module is generated assembly
1678                         for (int i = 1; i < modules.Length; ++i) {
1679                                 Module module = modules [i];
1680                                 if (!GetClsCompliantAttributeValue (module, null)) {
1681                                         ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1682                                                       "to match the assembly", module.Name);
1683                                         return;
1684                                 }
1685                         }
1686                 }
1687
1688                 public static Type GetImportedIgnoreCaseClsType (string name)
1689                 {
1690                         foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
1691                                 Type t = a.GetType (name, false, true);
1692                                 if (t == null)
1693                                         continue;
1694
1695                                 if (IsClsCompliant (t))
1696                                         return t;
1697                         }
1698                         return null;
1699                 }
1700
1701                 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a) 
1702                 {
1703                         PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
1704                         if (!pa.IsDefined)
1705                                 return false;
1706
1707                         object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
1708                         if (cls_attr.Length == 0) {
1709                                 if (a == null)
1710                                         return false;
1711
1712                                 return GetClsCompliantAttributeValue (a, null);
1713                         }
1714                         
1715                         return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1716                 }
1717
1718                 static bool AnalyzeTypeCompliance (Type type)
1719                 {
1720                         type = TypeManager.DropGenericTypeArguments (type);
1721                         DeclSpace ds = TypeManager.LookupDeclSpace (type);
1722                         if (ds != null) {
1723                                 return ds.IsClsComplianceRequired ();
1724                         }
1725
1726                         if (TypeManager.IsGenericParameter (type))
1727                                 return true;
1728
1729                         return GetClsCompliantAttributeValue (type, type.Assembly);
1730                 }
1731
1732                 /// <summary>
1733                 /// Returns instance of ObsoleteAttribute when type is obsolete
1734                 /// </summary>
1735                 public static ObsoleteAttribute GetObsoleteAttribute (Type type)
1736                 {
1737                         ObsoleteAttribute result;
1738                         if (analyzed_types_obsolete.TryGetValue (type, out result))
1739                                 return result;
1740
1741                         if (TypeManager.HasElementType (type)) {
1742                                 result = GetObsoleteAttribute (TypeManager.GetElementType (type));
1743                         } else if (TypeManager.IsGenericParameter (type))
1744                                 result = null;  // TODO: throw new NotSupportedException ()
1745                         else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
1746                                 return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
1747                         } else {
1748                                 DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
1749
1750                                 // Type is external, we can get attribute directly
1751                                 if (type_ds == null) {
1752                                         PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1753                                         if (pa.IsDefined) {
1754                                                 object[] attribute = type.GetCustomAttributes (pa.Type, false);
1755                                                 if (attribute.Length == 1)
1756                                                         result = (ObsoleteAttribute) attribute[0];
1757                                         }
1758                                 } else {
1759                                         result = type_ds.GetObsoleteAttribute ();
1760                                 }
1761                         }
1762
1763                         // Cannot use .Add because of corlib bootstrap
1764                         analyzed_types_obsolete [type] = result;
1765                         return result;
1766                 }
1767
1768                 /// <summary>
1769                 /// Returns instance of ObsoleteAttribute when method is obsolete
1770                 /// </summary>
1771                 public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
1772                 {
1773                         IMethodData mc = TypeManager.GetMethod (mb);
1774                         if (mc != null) 
1775                                 return mc.GetObsoleteAttribute ();
1776
1777                         // compiler generated methods are not registered by AddMethod
1778                         if (mb.DeclaringType is TypeBuilder)
1779                                 return null;
1780
1781                         MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
1782                         if (mi != null)
1783                                 return GetMemberObsoleteAttribute (mi);
1784
1785                         mi = TypeManager.GetEventFromAccessor (mb);
1786                         if (mi != null)
1787                                 return GetMemberObsoleteAttribute (mi);
1788
1789                         return GetMemberObsoleteAttribute (mb);
1790                 }
1791
1792                 /// <summary>
1793                 /// Returns instance of ObsoleteAttribute when member is obsolete
1794                 /// </summary>
1795                 public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
1796                 {
1797                         ObsoleteAttribute oa;
1798                         if (analyzed_member_obsolete.TryGetValue (mi, out oa))
1799                                 return oa;
1800
1801                         if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
1802                                 return null;
1803
1804                         PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1805                         if (!pa.IsDefined)
1806                                 return null;
1807
1808                         oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false) as ObsoleteAttribute;
1809                         analyzed_member_obsolete.Add (mi, oa);
1810                         return oa;
1811                 }
1812
1813                 /// <summary>
1814                 /// Common method for Obsolete error/warning reporting.
1815                 /// </summary>
1816                 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1817                 {
1818                         if (oa.IsError) {
1819                                 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1820                                 return;
1821                         }
1822
1823                         if (oa.Message == null || oa.Message.Length == 0) {
1824                                 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1825                                 return;
1826                         }
1827                         Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1828                 }
1829
1830                 public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
1831                 {
1832                         bool excluded;
1833                         if (analyzed_method_excluded.TryGetValue (mb, out excluded))
1834                                 return excluded;
1835
1836                         PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1837                         if (!pa.IsDefined)
1838                                 return false;
1839
1840                         ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
1841                                 as ConditionalAttribute[];
1842                         if (attrs.Length == 0) {
1843                                 analyzed_method_excluded.Add (mb, false);
1844                                 return false;
1845                         }
1846
1847                         foreach (ConditionalAttribute a in attrs) {
1848                                 if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
1849                                         analyzed_method_excluded.Add (mb, false);
1850                                         return false;
1851                                 }
1852                         }
1853
1854                         analyzed_method_excluded.Add (mb, true);
1855                         return true;
1856                 }
1857
1858                 /// <summary>
1859                 /// Analyzes class whether it has attribute which has ConditionalAttribute
1860                 /// and its condition is not defined.
1861                 /// </summary>
1862                 public static bool IsAttributeExcluded (Type type, Location loc)
1863                 {
1864                         if (!type.IsClass)
1865                                 return false;
1866
1867                         Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
1868
1869                         // TODO: add caching
1870                         // TODO: merge all Type bases attribute caching to one cache to save memory
1871                         PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1872                         if (class_decl == null && pa.IsDefined) {
1873                                 object[] attributes = type.GetCustomAttributes (pa.Type, false);
1874                                 foreach (ConditionalAttribute ca in attributes) {
1875                                         if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
1876                                                 return false;
1877                                 }
1878                                 return attributes.Length > 0;
1879                         }
1880
1881                         return class_decl.IsExcluded ();
1882                 }
1883
1884                 public static Type GetCoClassAttribute (Type type)
1885                 {
1886                         TypeContainer tc = TypeManager.LookupInterface (type);
1887                         PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
1888                         if (tc == null) {
1889                                 if (!pa.IsDefined)
1890                                         return null;
1891
1892                                 object[] o = type.GetCustomAttributes (pa.Type, false);
1893                                 if (o.Length < 1)
1894                                         return null;
1895                                 return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
1896                         }
1897
1898                         if (tc.OptAttributes == null)
1899                                 return null;
1900
1901                         Attribute a = tc.OptAttributes.Search (pa);
1902                         if (a == null)
1903                                 return null;
1904
1905                         return a.GetCoClassAttributeValue ();
1906                 }
1907         }
1908
1909         public class PredefinedAttributes
1910         {
1911                 // Core types
1912                 public readonly PredefinedAttribute ParamArray;
1913                 public readonly PredefinedAttribute Out;
1914
1915                 // Optional types
1916                 public readonly PredefinedAttribute Obsolete;
1917                 public readonly PredefinedAttribute DllImport;
1918                 public readonly PredefinedAttribute MethodImpl;
1919                 public readonly PredefinedAttribute MarshalAs;
1920                 public readonly PredefinedAttribute In;
1921                 public readonly PredefinedAttribute IndexerName;
1922                 public readonly PredefinedAttribute Conditional;
1923                 public readonly PredefinedAttribute CLSCompliant;
1924                 public readonly PredefinedAttribute Security;
1925                 public readonly PredefinedAttribute Required;
1926                 public readonly PredefinedAttribute Guid;
1927                 public readonly PredefinedAttribute AssemblyCulture;
1928                 public readonly PredefinedAttribute AssemblyVersion;
1929                 public readonly PredefinedAttribute ComImport;
1930                 public readonly PredefinedAttribute CoClass;
1931                 public readonly PredefinedAttribute AttributeUsage;
1932                 public readonly PredefinedAttribute DefaultParameterValue;
1933                 public readonly PredefinedAttribute OptionalParameter;
1934
1935                 // New in .NET 2.0
1936                 public readonly PredefinedAttribute DefaultCharset;
1937                 public readonly PredefinedAttribute TypeForwarder;
1938                 public readonly PredefinedAttribute FixedBuffer;
1939                 public readonly PredefinedAttribute CompilerGenerated;
1940                 public readonly PredefinedAttribute InternalsVisibleTo;
1941                 public readonly PredefinedAttribute RuntimeCompatibility;
1942                 public readonly PredefinedAttribute DebuggerHidden;
1943                 public readonly PredefinedAttribute UnsafeValueType;
1944
1945                 // New in .NET 3.5
1946                 public readonly PredefinedAttribute Extension;
1947
1948                 // New in .NET 4.0
1949                 public readonly PredefinedAttribute Dynamic;
1950                 public readonly PredefinedAttribute DynamicTransform;   // DynamicAttribute with transform arguments
1951
1952                 //
1953                 // Optional types which are used as types and for member lookup
1954                 //
1955                 public readonly PredefinedAttribute DefaultMember;
1956                 public readonly PredefinedAttribute DecimalConstant;
1957                 public readonly PredefinedAttribute StructLayout;
1958                 public readonly PredefinedAttribute FieldOffset;
1959
1960                 public static PredefinedAttributes Get = new PredefinedAttributes ();
1961
1962                 private PredefinedAttributes ()
1963                 {
1964                         ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1965                         Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1966
1967                         Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1968                         DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1969                         MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1970                         MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1971                         In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1972                         IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1973                         Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1974                         CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1975                         Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1976                         Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1977                         Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1978                         AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1979                         AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1980                         ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1981                         CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1982                         AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1983                         DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1984                         OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1985
1986                         DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1987                         TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1988                         FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1989                         CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1990                         InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1991                         RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1992                         DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1993                         UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1994
1995                         Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1996
1997                         Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1998                         DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1999
2000                         DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
2001                         DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
2002                         StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
2003                         FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
2004                 }
2005
2006                 public void Initialize (CompilerContext ctx)
2007                 {
2008                         foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
2009                                 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
2010                         }
2011                 }
2012
2013                 public static void Reset ()
2014                 {
2015                         Get = new PredefinedAttributes ();
2016                 }
2017         }
2018
2019         public class PredefinedAttribute
2020         {
2021                 Type type;
2022                 CustomAttributeBuilder cab;
2023                 ConstructorInfo ctor;
2024                 readonly string ns, name;
2025                 CompilerContext compiler;
2026
2027                 static readonly Type NotFound = typeof (PredefinedAttribute);
2028
2029                 public PredefinedAttribute (string ns, string name)
2030                 {
2031                         this.ns = ns;
2032                         this.name = name;
2033                 }
2034
2035                 public static bool operator == (Type type, PredefinedAttribute pa)
2036                 {
2037                         return type == pa.type;
2038                 }
2039
2040                 public static bool operator != (Type type, PredefinedAttribute pa)
2041                 {
2042                         return type != pa.type;
2043                 }
2044
2045                 public ConstructorInfo Constructor {
2046                         get { return ctor; }
2047                 }
2048
2049                 public override int GetHashCode ()
2050                 {
2051                         return base.GetHashCode ();
2052                 }
2053
2054                 public string GetSignatureForError ()
2055                 {
2056                         return ns + "." + name;
2057                 }
2058
2059                 public override bool Equals (object obj)
2060                 {
2061                         throw new NotSupportedException ();
2062                 }
2063
2064                 public void EmitAttribute (ConstructorBuilder builder)
2065                 {
2066                         if (ResolveBuilder ())
2067                                 builder.SetCustomAttribute (cab);
2068                 }
2069
2070                 public void EmitAttribute (MethodBuilder builder)
2071                 {
2072                         if (ResolveBuilder ())
2073                                 builder.SetCustomAttribute (cab);
2074                 }
2075
2076                 public void EmitAttribute (PropertyBuilder builder)
2077                 {
2078                         if (ResolveBuilder ())
2079                                 builder.SetCustomAttribute (cab);
2080                 }
2081
2082                 public void EmitAttribute (FieldBuilder builder)
2083                 {
2084                         if (ResolveBuilder ())
2085                                 builder.SetCustomAttribute (cab);
2086                 }
2087
2088                 public void EmitAttribute (TypeBuilder builder)
2089                 {
2090                         if (ResolveBuilder ())
2091                                 builder.SetCustomAttribute (cab);
2092                 }
2093
2094                 public void EmitAttribute (AssemblyBuilder builder)
2095                 {
2096                         if (ResolveBuilder ())
2097                                 builder.SetCustomAttribute (cab);
2098                 }
2099
2100                 public void EmitAttribute (ParameterBuilder builder)
2101                 {
2102                         if (ResolveBuilder ())
2103                                 builder.SetCustomAttribute (cab);
2104                 }
2105
2106                 public bool IsDefined {
2107                         get { return type != null && type != NotFound; }
2108                 }
2109
2110                 public void Initialize (CompilerContext ctx, bool canFail)
2111                 {
2112                         this.compiler = ctx;
2113                         Resolve (canFail);
2114                 }
2115
2116                 public bool Resolve (bool canFail)
2117                 {
2118                         if (type != null) {
2119                                 if (IsDefined)
2120                                         return true;
2121                                 if (canFail)
2122                                         return false;
2123                         }
2124
2125                         type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
2126                         if (type == null) {
2127                                 type = NotFound;
2128                                 return false;
2129                         }
2130
2131                         return true;
2132                 }
2133
2134                 bool ResolveBuilder ()
2135                 {
2136                         if (cab != null)
2137                                 return true;
2138
2139                         //
2140                         // Handle all parameter-less attributes as optional
2141                         //
2142                         if (!Resolve (true))
2143                                 return false;
2144
2145                         ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
2146                         if (ci == null)
2147                                 return false;
2148
2149                         cab = new CustomAttributeBuilder (ci, new object[0]);
2150                         return true;
2151                 }
2152
2153                 public bool ResolveConstructor (Location loc, params Type[] argType)
2154                 {
2155                         if (ctor != null)
2156                                 throw new InternalErrorException ("Predefined ctor redefined");
2157
2158                         if (!Resolve (false))
2159                                 return false;
2160
2161                         ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
2162                         return ctor != null;
2163                 }
2164
2165                 public Type Type {
2166                         get { return type; }
2167                 }
2168         }
2169 }