bcbae60f2dcd9cf11e35a007c6dc010435bd33f2
[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                                         var fi = ((FieldExpr) member).Spec;
601
602                                         if (fi.IsReadOnly || fi.IsStatic) {
603                                                 Error_InvalidNamedArgument (ec, a);
604                                                 return false;
605                                         }
606
607                                         if (!IsValidArgumentType (member.Type)) {
608                                                 ec.Report.SymbolRelatedToPreviousError (fi.MetaInfo);
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.MetaInfo);
618                                         if (fb != null)
619                                                 obsolete_attr = fb.GetObsoleteAttribute ();
620                                         else
621                                                 obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi.MetaInfo);
622
623                                         field_values.Add (value);
624                                         field_infos.Add (fi.MetaInfo);
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                 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1595                 {
1596                         Module[] modules = GlobalRootNamespace.Instance.Modules;
1597                         if (modules == null)
1598                                 return;
1599
1600                         // The first module is generated assembly
1601                         for (int i = 1; i < modules.Length; ++i) {
1602                                 Module module = modules [i];
1603                                 if (!GetClsCompliantAttributeValue (module, null)) {
1604                                         ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1605                                                       "to match the assembly", module.Name);
1606                                         return;
1607                                 }
1608                         }
1609                 }
1610
1611                 public static Type GetImportedIgnoreCaseClsType (string name)
1612                 {
1613                         foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
1614                                 Type t = a.GetType (name, false, true);
1615                                 if (t == null)
1616                                         continue;
1617
1618                                 if (IsClsCompliant (t))
1619                                         return t;
1620                         }
1621                         return null;
1622                 }
1623
1624                 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a) 
1625                 {
1626                         PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
1627                         if (!pa.IsDefined)
1628                                 return false;
1629
1630                         object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
1631                         if (cls_attr.Length == 0) {
1632                                 if (a == null)
1633                                         return false;
1634
1635                                 return GetClsCompliantAttributeValue (a, null);
1636                         }
1637                         
1638                         return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1639                 }
1640
1641                 static bool AnalyzeTypeCompliance (Type type)
1642                 {
1643                         type = TypeManager.DropGenericTypeArguments (type);
1644                         DeclSpace ds = TypeManager.LookupDeclSpace (type);
1645                         if (ds != null) {
1646                                 return ds.IsClsComplianceRequired ();
1647                         }
1648
1649                         if (TypeManager.IsGenericParameter (type))
1650                                 return true;
1651
1652                         return GetClsCompliantAttributeValue (type, type.Assembly);
1653                 }
1654
1655                 /// <summary>
1656                 /// Returns instance of ObsoleteAttribute when type is obsolete
1657                 /// </summary>
1658                 public static ObsoleteAttribute GetObsoleteAttribute (Type type)
1659                 {
1660                         ObsoleteAttribute result;
1661                         if (analyzed_types_obsolete.TryGetValue (type, out result))
1662                                 return result;
1663
1664                         if (TypeManager.HasElementType (type)) {
1665                                 result = GetObsoleteAttribute (TypeManager.GetElementType (type));
1666                         } else if (TypeManager.IsGenericParameter (type))
1667                                 result = null;  // TODO: throw new NotSupportedException ()
1668                         else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
1669                                 return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
1670                         } else {
1671                                 DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
1672
1673                                 // Type is external, we can get attribute directly
1674                                 if (type_ds == null) {
1675                                         PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1676                                         if (pa.IsDefined) {
1677                                                 object[] attribute = type.GetCustomAttributes (pa.Type, false);
1678                                                 if (attribute.Length == 1)
1679                                                         result = (ObsoleteAttribute) attribute[0];
1680                                         }
1681                                 } else {
1682                                         result = type_ds.GetObsoleteAttribute ();
1683                                 }
1684                         }
1685
1686                         // Cannot use .Add because of corlib bootstrap
1687                         analyzed_types_obsolete [type] = result;
1688                         return result;
1689                 }
1690
1691                 /// <summary>
1692                 /// Returns instance of ObsoleteAttribute when method is obsolete
1693                 /// </summary>
1694                 public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
1695                 {
1696                         IMethodData mc = TypeManager.GetMethod (mb);
1697                         if (mc != null) 
1698                                 return mc.GetObsoleteAttribute ();
1699
1700                         // compiler generated methods are not registered by AddMethod
1701                         if (mb.DeclaringType is TypeBuilder)
1702                                 return null;
1703
1704                         MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
1705                         if (mi != null)
1706                                 return GetMemberObsoleteAttribute (mi);
1707
1708                         mi = TypeManager.GetEventFromAccessor (mb);
1709                         if (mi != null)
1710                                 return GetMemberObsoleteAttribute (mi);
1711
1712                         return GetMemberObsoleteAttribute (mb);
1713                 }
1714
1715                 /// <summary>
1716                 /// Returns instance of ObsoleteAttribute when member is obsolete
1717                 /// </summary>
1718                 public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
1719                 {
1720                         ObsoleteAttribute oa;
1721                         if (analyzed_member_obsolete.TryGetValue (mi, out oa))
1722                                 return oa;
1723
1724                         if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
1725                                 return null;
1726
1727                         PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1728                         if (!pa.IsDefined)
1729                                 return null;
1730
1731                         oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false) as ObsoleteAttribute;
1732                         analyzed_member_obsolete.Add (mi, oa);
1733                         return oa;
1734                 }
1735
1736                 /// <summary>
1737                 /// Common method for Obsolete error/warning reporting.
1738                 /// </summary>
1739                 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1740                 {
1741                         if (oa.IsError) {
1742                                 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1743                                 return;
1744                         }
1745
1746                         if (oa.Message == null || oa.Message.Length == 0) {
1747                                 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1748                                 return;
1749                         }
1750                         Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1751                 }
1752
1753                 public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
1754                 {
1755                         bool excluded;
1756                         if (analyzed_method_excluded.TryGetValue (mb, out excluded))
1757                                 return excluded;
1758
1759                         PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1760                         if (!pa.IsDefined)
1761                                 return false;
1762
1763                         ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
1764                                 as ConditionalAttribute[];
1765                         if (attrs.Length == 0) {
1766                                 analyzed_method_excluded.Add (mb, false);
1767                                 return false;
1768                         }
1769
1770                         foreach (ConditionalAttribute a in attrs) {
1771                                 if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
1772                                         analyzed_method_excluded.Add (mb, false);
1773                                         return false;
1774                                 }
1775                         }
1776
1777                         analyzed_method_excluded.Add (mb, true);
1778                         return true;
1779                 }
1780
1781                 /// <summary>
1782                 /// Analyzes class whether it has attribute which has ConditionalAttribute
1783                 /// and its condition is not defined.
1784                 /// </summary>
1785                 public static bool IsAttributeExcluded (Type type, Location loc)
1786                 {
1787                         if (!type.IsClass)
1788                                 return false;
1789
1790                         Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
1791
1792                         // TODO: add caching
1793                         // TODO: merge all Type bases attribute caching to one cache to save memory
1794                         PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1795                         if (class_decl == null && pa.IsDefined) {
1796                                 object[] attributes = type.GetCustomAttributes (pa.Type, false);
1797                                 foreach (ConditionalAttribute ca in attributes) {
1798                                         if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
1799                                                 return false;
1800                                 }
1801                                 return attributes.Length > 0;
1802                         }
1803
1804                         return class_decl.IsExcluded ();
1805                 }
1806
1807                 public static Type GetCoClassAttribute (Type type)
1808                 {
1809                         TypeContainer tc = TypeManager.LookupInterface (type);
1810                         PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
1811                         if (tc == null) {
1812                                 if (!pa.IsDefined)
1813                                         return null;
1814
1815                                 object[] o = type.GetCustomAttributes (pa.Type, false);
1816                                 if (o.Length < 1)
1817                                         return null;
1818                                 return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
1819                         }
1820
1821                         if (tc.OptAttributes == null)
1822                                 return null;
1823
1824                         Attribute a = tc.OptAttributes.Search (pa);
1825                         if (a == null)
1826                                 return null;
1827
1828                         return a.GetCoClassAttributeValue ();
1829                 }
1830         }
1831
1832         public class PredefinedAttributes
1833         {
1834                 // Core types
1835                 public readonly PredefinedAttribute ParamArray;
1836                 public readonly PredefinedAttribute Out;
1837
1838                 // Optional types
1839                 public readonly PredefinedAttribute Obsolete;
1840                 public readonly PredefinedAttribute DllImport;
1841                 public readonly PredefinedAttribute MethodImpl;
1842                 public readonly PredefinedAttribute MarshalAs;
1843                 public readonly PredefinedAttribute In;
1844                 public readonly PredefinedAttribute IndexerName;
1845                 public readonly PredefinedAttribute Conditional;
1846                 public readonly PredefinedAttribute CLSCompliant;
1847                 public readonly PredefinedAttribute Security;
1848                 public readonly PredefinedAttribute Required;
1849                 public readonly PredefinedAttribute Guid;
1850                 public readonly PredefinedAttribute AssemblyCulture;
1851                 public readonly PredefinedAttribute AssemblyVersion;
1852                 public readonly PredefinedAttribute ComImport;
1853                 public readonly PredefinedAttribute CoClass;
1854                 public readonly PredefinedAttribute AttributeUsage;
1855                 public readonly PredefinedAttribute DefaultParameterValue;
1856                 public readonly PredefinedAttribute OptionalParameter;
1857
1858                 // New in .NET 2.0
1859                 public readonly PredefinedAttribute DefaultCharset;
1860                 public readonly PredefinedAttribute TypeForwarder;
1861                 public readonly PredefinedAttribute FixedBuffer;
1862                 public readonly PredefinedAttribute CompilerGenerated;
1863                 public readonly PredefinedAttribute InternalsVisibleTo;
1864                 public readonly PredefinedAttribute RuntimeCompatibility;
1865                 public readonly PredefinedAttribute DebuggerHidden;
1866                 public readonly PredefinedAttribute UnsafeValueType;
1867
1868                 // New in .NET 3.5
1869                 public readonly PredefinedAttribute Extension;
1870
1871                 // New in .NET 4.0
1872                 public readonly PredefinedAttribute Dynamic;
1873                 public readonly PredefinedAttribute DynamicTransform;   // DynamicAttribute with transform arguments
1874
1875                 //
1876                 // Optional types which are used as types and for member lookup
1877                 //
1878                 public readonly PredefinedAttribute DefaultMember;
1879                 public readonly PredefinedAttribute DecimalConstant;
1880                 public readonly PredefinedAttribute StructLayout;
1881                 public readonly PredefinedAttribute FieldOffset;
1882
1883                 public static PredefinedAttributes Get = new PredefinedAttributes ();
1884
1885                 private PredefinedAttributes ()
1886                 {
1887                         ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1888                         Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1889
1890                         Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1891                         DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1892                         MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1893                         MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1894                         In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1895                         IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1896                         Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1897                         CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1898                         Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1899                         Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1900                         Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1901                         AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1902                         AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1903                         ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1904                         CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1905                         AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1906                         DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1907                         OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1908
1909                         DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1910                         TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1911                         FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1912                         CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1913                         InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1914                         RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1915                         DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1916                         UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1917
1918                         Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1919
1920                         Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1921                         DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1922
1923                         DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
1924                         DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1925                         StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
1926                         FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1927                 }
1928
1929                 public void Initialize (CompilerContext ctx)
1930                 {
1931                         foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
1932                                 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
1933                         }
1934                 }
1935
1936                 public static void Reset ()
1937                 {
1938                         Get = new PredefinedAttributes ();
1939                 }
1940         }
1941
1942         public class PredefinedAttribute
1943         {
1944                 Type type;
1945                 CustomAttributeBuilder cab;
1946                 ConstructorInfo ctor;
1947                 readonly string ns, name;
1948                 CompilerContext compiler;
1949
1950                 static readonly Type NotFound = typeof (PredefinedAttribute);
1951
1952                 public PredefinedAttribute (string ns, string name)
1953                 {
1954                         this.ns = ns;
1955                         this.name = name;
1956                 }
1957
1958                 public static bool operator == (Type type, PredefinedAttribute pa)
1959                 {
1960                         return type == pa.type;
1961                 }
1962
1963                 public static bool operator != (Type type, PredefinedAttribute pa)
1964                 {
1965                         return type != pa.type;
1966                 }
1967
1968                 public ConstructorInfo Constructor {
1969                         get { return ctor; }
1970                 }
1971
1972                 public override int GetHashCode ()
1973                 {
1974                         return base.GetHashCode ();
1975                 }
1976
1977                 public string GetSignatureForError ()
1978                 {
1979                         return ns + "." + name;
1980                 }
1981
1982                 public override bool Equals (object obj)
1983                 {
1984                         throw new NotSupportedException ();
1985                 }
1986
1987                 public void EmitAttribute (ConstructorBuilder builder)
1988                 {
1989                         if (ResolveBuilder ())
1990                                 builder.SetCustomAttribute (cab);
1991                 }
1992
1993                 public void EmitAttribute (MethodBuilder builder)
1994                 {
1995                         if (ResolveBuilder ())
1996                                 builder.SetCustomAttribute (cab);
1997                 }
1998
1999                 public void EmitAttribute (PropertyBuilder builder)
2000                 {
2001                         if (ResolveBuilder ())
2002                                 builder.SetCustomAttribute (cab);
2003                 }
2004
2005                 public void EmitAttribute (FieldBuilder builder)
2006                 {
2007                         if (ResolveBuilder ())
2008                                 builder.SetCustomAttribute (cab);
2009                 }
2010
2011                 public void EmitAttribute (TypeBuilder builder)
2012                 {
2013                         if (ResolveBuilder ())
2014                                 builder.SetCustomAttribute (cab);
2015                 }
2016
2017                 public void EmitAttribute (AssemblyBuilder builder)
2018                 {
2019                         if (ResolveBuilder ())
2020                                 builder.SetCustomAttribute (cab);
2021                 }
2022
2023                 public void EmitAttribute (ParameterBuilder builder)
2024                 {
2025                         if (ResolveBuilder ())
2026                                 builder.SetCustomAttribute (cab);
2027                 }
2028
2029                 public bool IsDefined {
2030                         get { return type != null && type != NotFound; }
2031                 }
2032
2033                 public void Initialize (CompilerContext ctx, bool canFail)
2034                 {
2035                         this.compiler = ctx;
2036                         Resolve (canFail);
2037                 }
2038
2039                 public bool Resolve (bool canFail)
2040                 {
2041                         if (type != null) {
2042                                 if (IsDefined)
2043                                         return true;
2044                                 if (canFail)
2045                                         return false;
2046                         }
2047
2048                         type = TypeManager.CoreLookupType (compiler, ns, name, Kind.Class, !canFail);
2049                         if (type == null) {
2050                                 type = NotFound;
2051                                 return false;
2052                         }
2053
2054                         return true;
2055                 }
2056
2057                 bool ResolveBuilder ()
2058                 {
2059                         if (cab != null)
2060                                 return true;
2061
2062                         //
2063                         // Handle all parameter-less attributes as optional
2064                         //
2065                         if (!Resolve (true))
2066                                 return false;
2067
2068                         ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
2069                         if (ci == null)
2070                                 return false;
2071
2072                         cab = new CustomAttributeBuilder (ci, new object[0]);
2073                         return true;
2074                 }
2075
2076                 public bool ResolveConstructor (Location loc, params Type[] argType)
2077                 {
2078                         if (ctor != null)
2079                                 throw new InternalErrorException ("Predefined ctor redefined");
2080
2081                         if (!Resolve (false))
2082                                 return false;
2083
2084                         ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
2085                         return ctor != null;
2086                 }
2087
2088                 public Type Type {
2089                         get { return type; }
2090                 }
2091         }
2092 }