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