4ea3e77cbf757b2cc4e29ce0234176af623b156b
[mono.git] / mcs / mcs / typemanager.cs
1 //
2 // typemanager.cs: C# type manager
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //         Ravi Pratap     (ravi@ximian.com)
6 //         Marek Safar     (marek.safar@seznam.cz)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2003-2008 Novell, Inc.
12 //
13
14 using System;
15 using System.Globalization;
16 using System.Collections.Generic;
17 using System.Text;
18
19 namespace Mono.CSharp
20 {
21         //
22         // All compiler build-in types (they have to exist otherwise the compile will not work)
23         //
24         public class BuildinTypes
25         {
26                 public readonly BuildinTypeSpec Object;
27                 public readonly BuildinTypeSpec ValueType;
28                 public readonly BuildinTypeSpec Attribute;
29
30                 public readonly BuildinTypeSpec Int;
31                 public readonly BuildinTypeSpec UInt;
32                 public readonly BuildinTypeSpec Long;
33                 public readonly BuildinTypeSpec ULong;
34                 public readonly BuildinTypeSpec Float;
35                 public readonly BuildinTypeSpec Double;
36                 public readonly BuildinTypeSpec Char;
37                 public readonly BuildinTypeSpec Short;
38                 public readonly BuildinTypeSpec Decimal;
39                 public readonly BuildinTypeSpec Bool;
40                 public readonly BuildinTypeSpec SByte;
41                 public readonly BuildinTypeSpec Byte;
42                 public readonly BuildinTypeSpec UShort;
43                 public readonly BuildinTypeSpec String;
44
45                 public readonly BuildinTypeSpec Enum;
46                 public readonly BuildinTypeSpec Delegate;
47                 public readonly BuildinTypeSpec MulticastDelegate;
48                 public readonly BuildinTypeSpec Void;
49                 public readonly BuildinTypeSpec Array;
50                 public readonly BuildinTypeSpec Type;
51                 public readonly BuildinTypeSpec IEnumerator;
52                 public readonly BuildinTypeSpec IEnumerable;
53                 public readonly BuildinTypeSpec IDisposable;
54                 public readonly BuildinTypeSpec IntPtr;
55                 public readonly BuildinTypeSpec UIntPtr;
56                 public readonly BuildinTypeSpec RuntimeFieldHandle;
57                 public readonly BuildinTypeSpec RuntimeTypeHandle;
58                 public readonly BuildinTypeSpec Exception;
59
60                 //
61                 // These are internal buil-in types which depend on other
62                 // build-in type (mostly object)
63                 //
64                 public readonly BuildinTypeSpec Dynamic;
65
66                 // Predefined operators tables
67                 public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard;
68                 public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality;
69                 public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe;
70                 public readonly TypeSpec[][] OperatorsUnary;
71                 public readonly TypeSpec[] OperatorsUnaryMutator;
72
73                 public readonly TypeSpec[] BinaryPromotionsTypes;
74                 public readonly TypeSpec[] SwitchUserTypes;
75
76                 readonly BuildinTypeSpec[] types;
77
78                 public BuildinTypes ()
79                 {
80                         Object = new BuildinTypeSpec (MemberKind.Class, "System", "Object", BuildinTypeSpec.Type.Object);
81                         ValueType = new BuildinTypeSpec (MemberKind.Class, "System", "ValueType", BuildinTypeSpec.Type.ValueType);
82                         Attribute = new BuildinTypeSpec (MemberKind.Class, "System", "Attribute", BuildinTypeSpec.Type.Attribute);
83
84                         Int = new BuildinTypeSpec (MemberKind.Struct, "System", "Int32", BuildinTypeSpec.Type.Int);
85                         Long = new BuildinTypeSpec (MemberKind.Struct, "System", "Int64", BuildinTypeSpec.Type.Long);
86                         UInt = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt32", BuildinTypeSpec.Type.UInt);
87                         ULong = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt64", BuildinTypeSpec.Type.ULong);
88                         Byte = new BuildinTypeSpec (MemberKind.Struct, "System", "Byte", BuildinTypeSpec.Type.Byte);
89                         SByte = new BuildinTypeSpec (MemberKind.Struct, "System", "SByte", BuildinTypeSpec.Type.SByte);
90                         Short = new BuildinTypeSpec (MemberKind.Struct, "System", "Int16", BuildinTypeSpec.Type.Short);
91                         UShort = new BuildinTypeSpec (MemberKind.Struct, "System", "UInt16", BuildinTypeSpec.Type.UShort);
92
93                         IEnumerator = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuildinTypeSpec.Type.IEnumerator);
94                         IEnumerable = new BuildinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuildinTypeSpec.Type.IEnumerable);
95                         IDisposable = new BuildinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuildinTypeSpec.Type.IDisposable);
96
97                         Char = new BuildinTypeSpec (MemberKind.Struct, "System", "Char", BuildinTypeSpec.Type.Char);
98                         String = new BuildinTypeSpec (MemberKind.Class, "System", "String", BuildinTypeSpec.Type.String);
99                         Float = new BuildinTypeSpec (MemberKind.Struct, "System", "Single", BuildinTypeSpec.Type.Float);
100                         Double = new BuildinTypeSpec (MemberKind.Struct, "System", "Double", BuildinTypeSpec.Type.Double);
101                         Decimal = new BuildinTypeSpec (MemberKind.Struct, "System", "Decimal", BuildinTypeSpec.Type.Decimal);
102                         Bool = new BuildinTypeSpec (MemberKind.Struct, "System", "Boolean", BuildinTypeSpec.Type.Bool);
103                         IntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuildinTypeSpec.Type.IntPtr);
104                         UIntPtr = new BuildinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuildinTypeSpec.Type.UIntPtr);
105
106                         MulticastDelegate = new BuildinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuildinTypeSpec.Type.MulticastDelegate);
107                         Delegate = new BuildinTypeSpec (MemberKind.Class, "System", "Delegate", BuildinTypeSpec.Type.Delegate);
108                         Enum = new BuildinTypeSpec (MemberKind.Class, "System", "Enum", BuildinTypeSpec.Type.Enum);
109                         Array = new BuildinTypeSpec (MemberKind.Class, "System", "Array", BuildinTypeSpec.Type.Array);
110                         Void = new BuildinTypeSpec (MemberKind.Void, "System", "Void", BuildinTypeSpec.Type.Other);
111                         Type = new BuildinTypeSpec (MemberKind.Class, "System", "Type", BuildinTypeSpec.Type.Type);
112                         Exception = new BuildinTypeSpec (MemberKind.Class, "System", "Exception", BuildinTypeSpec.Type.Exception);
113                         RuntimeFieldHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuildinTypeSpec.Type.Other);
114                         RuntimeTypeHandle = new BuildinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuildinTypeSpec.Type.Other);
115
116                         // TODO: Maybe I should promote it to different kind for faster compares
117                         Dynamic = new BuildinTypeSpec ("dynamic", BuildinTypeSpec.Type.Dynamic);
118
119                         OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this);
120                         OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this);
121                         OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this);
122                         OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this);
123                         OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this);
124
125                         BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this);
126                         SwitchUserTypes = Switch.CreateSwitchUserTypes (this);
127
128                         types = new BuildinTypeSpec[] {
129                                 Object, ValueType, Attribute,
130                                 Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
131                                 Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
132                                 IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
133
134                         // Deal with obsolete static types
135                         // TODO: remove
136                         TypeManager.object_type = Object;
137                         TypeManager.value_type = ValueType;
138                 }
139
140                 public BuildinTypeSpec[] AllTypes {
141                         get {
142                                 return types;
143                         }
144                 }
145
146                 public bool CheckDefinitions (ModuleContainer module)
147                 {
148                         var ctx = module.Compiler;
149                         foreach (var p in types) {
150                                 var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity, Location.Null);
151                                 if (found == null || found == p)
152                                         continue;
153
154                                 var tc = found.MemberDefinition as TypeContainer;
155                                 if (tc != null) {
156                                         var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
157                                         ns.ReplaceTypeWithPredefined (found, p);
158
159                                         tc.SetPredefinedSpec (p);
160                                         p.SetDefinition (found);
161                                 }
162                         }
163
164                         if (ctx.Report.Errors != 0)
165                                 return false;
166
167                         // Set internal build-in types
168                         Dynamic.SetDefinition (Object);
169
170                         return true;
171                 }
172         }
173
174         //
175         // Compiler predefined types. Usually used for compiler generated
176         // code or for comparison against well known framework type
177         //
178         class PredefinedTypes
179         {
180                 // TODO: These two exist only to reject type comparison
181                 public readonly PredefinedType TypedReference;
182                 public readonly PredefinedType ArgIterator;
183
184                 public readonly PredefinedType MarshalByRefObject;
185                 public readonly PredefinedType RuntimeHelpers;
186                 public readonly PredefinedType IAsyncResult;
187                 public readonly PredefinedType AsyncCallback;
188                 public readonly PredefinedType RuntimeArgumentHandle;
189                 public readonly PredefinedType CharSet;
190                 public readonly PredefinedType IsVolatile;
191                 public readonly PredefinedType IEnumeratorGeneric;
192                 public readonly PredefinedType IListGeneric;
193                 public readonly PredefinedType ICollectionGeneric;
194                 public readonly PredefinedType IEnumerableGeneric;
195                 public readonly PredefinedType Nullable;
196                 public readonly PredefinedType Activator;
197                 public readonly PredefinedType Interlocked;
198                 public readonly PredefinedType Monitor;
199                 public readonly PredefinedType NotSupportedException;
200                 public readonly PredefinedType RuntimeFieldHandle;
201                 public readonly PredefinedType RuntimeMethodHandle;
202                 public readonly PredefinedType SecurityAction;
203
204                 //
205                 // C# 3.0
206                 //
207                 public readonly PredefinedType Expression;
208                 public readonly PredefinedType ExpressionGeneric;
209                 public readonly PredefinedType ParameterExpression;
210                 public readonly PredefinedType FieldInfo;
211                 public readonly PredefinedType MethodBase;
212                 public readonly PredefinedType MethodInfo;
213                 public readonly PredefinedType ConstructorInfo;
214
215                 //
216                 // C# 4.0
217                 //
218                 public readonly PredefinedType Binder;
219                 public readonly PredefinedType CallSite;
220                 public readonly PredefinedType CallSiteGeneric;
221                 public readonly PredefinedType BinderFlags;
222
223                 public PredefinedTypes (ModuleContainer module)
224                 {
225                         TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
226                         ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
227                         MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
228                         RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
229                         IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
230                         AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
231                         RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
232                         CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
233                         IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
234                         IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
235                         IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
236                         ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
237                         IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
238                         Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
239                         Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
240                         Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
241                         Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
242                         NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
243                         RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
244                         RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
245                         SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
246
247                         Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression");
248                         ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1);
249                         ParameterExpression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "ParameterExpression");
250                         FieldInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "FieldInfo");
251                         MethodBase = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodBase");
252                         MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo");
253                         ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo");
254
255                         CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite");
256                         CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1);
257                         Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder");
258                         BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags");
259
260                         //
261                         // Define types which are used for comparison. It does not matter
262                         // if they don't exist as no error report is needed
263                         //
264                         TypedReference.Define ();
265                         ArgIterator.Define ();
266                         MarshalByRefObject.Define ();
267                         CharSet.Define ();
268
269                         IEnumerableGeneric.Define ();
270                         IListGeneric.Define ();
271                         ICollectionGeneric.Define ();
272                         IEnumerableGeneric.Define ();
273                         IEnumeratorGeneric.Define ();
274                         Nullable.Define ();
275                         ExpressionGeneric.Define ();
276
277                         // Deal with obsolete static types
278                         // TODO: remove
279                         TypeManager.typed_reference_type = TypedReference.TypeSpec;
280                         TypeManager.arg_iterator_type = ArgIterator.TypeSpec;
281                         TypeManager.mbr_type = MarshalByRefObject.TypeSpec;
282                         TypeManager.generic_ilist_type = IListGeneric.TypeSpec;
283                         TypeManager.generic_icollection_type = ICollectionGeneric.TypeSpec;
284                         TypeManager.generic_ienumerator_type = IEnumeratorGeneric.TypeSpec;
285                         TypeManager.generic_ienumerable_type = IEnumerableGeneric.TypeSpec;
286                         TypeManager.generic_nullable_type = Nullable.TypeSpec;
287                         TypeManager.expression_type = ExpressionGeneric.TypeSpec;
288                 }
289         }
290
291         public class PredefinedType
292         {
293                 string name;
294                 string ns;
295                 int arity;
296                 MemberKind kind;
297                 protected readonly ModuleContainer module;
298                 protected TypeSpec type;
299
300                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
301                         : this (module, kind, ns, name)
302                 {
303                         this.arity = arity;
304                 }
305
306                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
307                 {
308                         this.module = module;
309                         this.kind = kind;
310                         this.name = name;
311                         this.ns = ns;
312                 }
313
314                 #region Properties
315
316                 public int Arity {
317                         get {
318                                 return arity;
319                         }
320                 }
321
322                 public bool IsDefined {
323                         get {
324                                 return type != null;
325                         }
326                 }
327
328                 public string Name {
329                         get {
330                                 return name;
331                         }
332                 }
333
334                 public string Namespace {
335                         get {
336                                 return ns;
337                         }
338                 }
339
340                 public TypeSpec TypeSpec {
341                         get {
342                                 return type;
343                         }
344                 }
345
346                 #endregion
347
348                 public bool Define ()
349                 {
350                         if (type != null)
351                                 return true;
352
353                         Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
354                         var te = type_ns.LookupType (module, name, arity, true, Location.Null);
355                         if (te == null)
356                                 return false;
357
358                         if (te.Type.Kind != kind)
359                                 return false;
360
361                         type = te.Type;
362                         return true;
363                 }
364
365                 public FieldSpec GetField (string name, TypeSpec memberType, Location loc)
366                 {
367                         return TypeManager.GetPredefinedField (type, name, loc, memberType);
368                 }
369
370                 public string GetSignatureForError ()
371                 {
372                         return ns + "." + name;
373                 }
374
375                 public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, Location loc)
376                 {
377                         Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
378                         var te = type_ns.LookupType (module, name, arity, false, Location.Null);
379                         if (te == null) {
380                                 module.Compiler.Report.Error (518, loc, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
381                                 return null;
382                         }
383
384                         var type = te.Type;
385                         if (type.Kind != kind) {
386                                 if (type.Kind == MemberKind.Struct && kind == MemberKind.Void && type.MemberDefinition is TypeContainer) {
387                                         // Void is declared as struct but we keep it internally as
388                                         // special kind, the swap will happen at caller
389                                 } else {
390                                         module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
391                                         return null;
392                                 }
393                         }
394
395                         return type;
396                 }
397
398                 public TypeSpec Resolve (Location loc)
399                 {
400                         if (type == null)
401                                 type = Resolve (module, kind, ns, name, arity, loc);
402
403                         return type;
404                 }
405         }
406
407         partial class TypeManager {
408         //
409         // A list of core types that the compiler requires or uses
410         //
411         static public BuildinTypeSpec object_type;
412         static public BuildinTypeSpec value_type;
413
414         static public TypeSpec typed_reference_type;
415         static public TypeSpec arg_iterator_type;
416         static public TypeSpec mbr_type;
417         static public TypeSpec generic_ilist_type;
418         static public TypeSpec generic_icollection_type;
419         static public TypeSpec generic_ienumerator_type;
420         static public TypeSpec generic_ienumerable_type;
421         static public TypeSpec generic_nullable_type;
422         static internal TypeSpec expression_type;
423
424         //
425         // These methods are called by code generated by the compiler
426         //
427         static public FieldSpec string_empty;
428         static public MethodSpec system_type_get_type_from_handle;
429         static public MethodSpec bool_movenext_void;
430         static public MethodSpec void_dispose_void;
431         static public MethodSpec void_monitor_enter_object;
432         static public MethodSpec void_monitor_exit_object;
433         static public MethodSpec void_initializearray_array_fieldhandle;
434         static public MethodSpec delegate_combine_delegate_delegate;
435         static public MethodSpec delegate_remove_delegate_delegate;
436         static public PropertySpec int_get_offset_to_string_data;
437         static public MethodSpec int_interlocked_compare_exchange;
438         public static MethodSpec gen_interlocked_compare_exchange;
439         static public PropertySpec ienumerator_getcurrent;
440         public static MethodSpec methodbase_get_type_from_handle;
441         public static MethodSpec methodbase_get_type_from_handle_generic;
442         public static MethodSpec fieldinfo_get_field_from_handle;
443         public static MethodSpec fieldinfo_get_field_from_handle_generic;
444         public static MethodSpec activator_create_instance;
445
446         //
447         // The constructors.
448         //
449         static public MethodSpec void_decimal_ctor_five_args;
450         static public MethodSpec void_decimal_ctor_int_arg;
451         public static MethodSpec void_decimal_ctor_long_arg;
452
453         static TypeManager ()
454         {
455                 Reset ();
456         }
457
458         static public void Reset ()
459         {
460 //              object_type = null;
461         
462                 // TODO: I am really bored by all this static stuff
463                 system_type_get_type_from_handle =
464                 bool_movenext_void =
465                 void_dispose_void =
466                 void_monitor_enter_object =
467                 void_monitor_exit_object =
468                 void_initializearray_array_fieldhandle =
469                 int_interlocked_compare_exchange =
470                 gen_interlocked_compare_exchange =
471                 methodbase_get_type_from_handle =
472                 methodbase_get_type_from_handle_generic =
473                 fieldinfo_get_field_from_handle =
474                 fieldinfo_get_field_from_handle_generic =
475                 activator_create_instance =
476                 delegate_combine_delegate_delegate =
477                 delegate_remove_delegate_delegate = null;
478
479                 int_get_offset_to_string_data =
480                 ienumerator_getcurrent = null;
481
482                 void_decimal_ctor_five_args =
483                 void_decimal_ctor_int_arg =
484                 void_decimal_ctor_long_arg = null;
485
486                 string_empty = null;
487
488                 typed_reference_type = arg_iterator_type = mbr_type =
489                 generic_ilist_type = generic_icollection_type = generic_ienumerator_type =
490                 generic_ienumerable_type = generic_nullable_type = expression_type = null;
491         }
492
493         /// <summary>
494         ///   Returns the C# name of a type if possible, or the full type name otherwise
495         /// </summary>
496         static public string CSharpName (TypeSpec t)
497         {
498                 return t.GetSignatureForError ();
499         }
500
501         static public string CSharpName (IList<TypeSpec> types)
502         {
503                 if (types.Count == 0)
504                         return string.Empty;
505
506                 StringBuilder sb = new StringBuilder ();
507                 for (int i = 0; i < types.Count; ++i) {
508                         if (i > 0)
509                                 sb.Append (",");
510
511                         sb.Append (CSharpName (types [i]));
512                 }
513                 return sb.ToString ();
514         }
515
516         static public string GetFullNameSignature (MemberSpec mi)
517         {
518                 return mi.GetSignatureForError ();
519         }
520
521         static public string CSharpSignature (MemberSpec mb)
522         {
523                 return mb.GetSignatureForError ();
524         }
525
526         static MemberSpec GetPredefinedMember (TypeSpec t, MemberFilter filter, bool optional, Location loc)
527         {
528                 var member = MemberCache.FindMember (t, filter, BindingRestriction.DeclaredOnly);
529
530                 if (member != null && member.IsAccessible (InternalType.FakeInternalType))
531                         return member;
532
533                 if (optional)
534                         return member;
535
536                 string method_args = null;
537                 if (filter.Parameters != null)
538                         method_args = filter.Parameters.GetSignatureForError ();
539
540                 RootContext.ToplevelTypes.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
541                         TypeManager.CSharpName (t), filter.Name, method_args);
542
543                 return null;
544         }
545
546         //
547         // Returns the ConstructorInfo for "args"
548         //
549         public static MethodSpec GetPredefinedConstructor (TypeSpec t, Location loc, params TypeSpec [] args)
550         {
551                 var pc = ParametersCompiled.CreateFullyResolved (args);
552                 return GetPredefinedMember (t, MemberFilter.Constructor (pc), false, loc) as MethodSpec;
553         }
554
555         //
556         // Returns the method specification for a method named `name' defined
557         // in type `t' which takes arguments of types `args'
558         //
559         public static MethodSpec GetPredefinedMethod (TypeSpec t, string name, Location loc, params TypeSpec [] args)
560         {
561                 var pc = ParametersCompiled.CreateFullyResolved (args);
562                 return GetPredefinedMethod (t, MemberFilter.Method (name, 0, pc, null), false, loc);
563         }
564
565         public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, Location loc)
566         {
567                 return GetPredefinedMethod (t, filter, false, loc);
568         }
569
570         public static MethodSpec GetPredefinedMethod (TypeSpec t, MemberFilter filter, bool optional, Location loc)
571         {
572                 return GetPredefinedMember (t, filter, optional, loc) as MethodSpec;
573         }
574
575         public static FieldSpec GetPredefinedField (TypeSpec t, string name, Location loc, TypeSpec type)
576         {
577                 return GetPredefinedMember (t, MemberFilter.Field (name, type), false, loc) as FieldSpec;
578         }
579
580         public static PropertySpec GetPredefinedProperty (TypeSpec t, string name, Location loc, TypeSpec type)
581         {
582                 return GetPredefinedMember (t, MemberFilter.Property (name, type), false, loc) as PropertySpec;
583         }
584
585         // Obsolete
586         public static bool IsDelegateType (TypeSpec t)
587         {
588                 return t.IsDelegate;
589         }
590         
591         // Obsolete
592         public static bool IsEnumType (TypeSpec t)
593         {
594                 return t.IsEnum;
595         }
596
597         //
598         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
599         //
600         public static bool IsUnmanagedType (TypeSpec t)
601         {
602                 var ds = t.MemberDefinition as DeclSpace;
603                 if (ds != null)
604                         return ds.IsUnmanagedType ();
605
606                 if (t.Kind == MemberKind.Void)
607                         return true;
608
609                 // Someone did the work of checking if the ElementType of t is unmanaged.  Let's not repeat it.
610                 if (t.IsPointer)
611                         return IsUnmanagedType (GetElementType (t));
612
613                 if (!IsValueType (t))
614                         return false;
615
616                 if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
617                         return false;
618
619                 return true;
620         }
621
622         //
623         // Null is considered to be a reference type
624         //                      
625         public static bool IsReferenceType (TypeSpec t)
626         {
627                 if (t.IsGenericParameter)
628                         return ((TypeParameterSpec) t).IsReferenceType;
629
630                 return !t.IsStruct && !IsEnumType (t);
631         }                       
632                 
633         public static bool IsValueType (TypeSpec t)
634         {
635                 if (t.IsGenericParameter)
636                         return ((TypeParameterSpec) t).IsValueType;
637
638                 return t.IsStruct || IsEnumType (t);
639         }
640
641         public static bool IsStruct (TypeSpec t)
642         {
643                 return t.IsStruct;
644         }
645
646         public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
647         {
648 //              TypeParameter tparam = LookupTypeParameter (type);
649 //              TypeParameter pparam = LookupTypeParameter (parent);
650
651                 if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
652                         if (type == parent)
653                                 return true;
654
655                         throw new NotImplementedException ("net");
656 //                      return tparam.IsSubclassOf (parent);
657                 }
658
659                 do {
660                         if (IsInstantiationOfSameGenericType (type, parent))
661                                 return true;
662
663                         type = type.BaseType;
664                 } while (type != null);
665
666                 return false;
667         }
668
669         //
670         // Checks whether `type' is a subclass or nested child of `base_type'.
671         //
672         public static bool IsNestedFamilyAccessible (TypeSpec type, TypeSpec base_type)
673         {
674                 do {
675                         if (IsFamilyAccessible (type, base_type))
676                                 return true;
677
678                         // Handle nested types.
679                         type = type.DeclaringType;
680                 } while (type != null);
681
682                 return false;
683         }
684
685         //
686         // Checks whether `type' is a nested child of `parent'.
687         //
688         public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent)
689         {
690                 if (type == null)
691                         return false;
692
693                 if (type.MemberDefinition == parent)
694                         return false;
695
696                 type = type.DeclaringType;
697                 while (type != null) {
698                         if (type.MemberDefinition == parent)
699                                 return true;
700
701                         type = type.DeclaringType;
702                 }
703
704                 return false;
705         }
706
707         public static bool IsSpecialType (TypeSpec t)
708         {
709                 return t == arg_iterator_type || t == typed_reference_type;
710         }
711
712         public static TypeSpec GetElementType (TypeSpec t)
713         {
714                 return ((ElementTypeSpec)t).Element;
715         }
716
717         /// <summary>
718         /// This method is not implemented by MS runtime for dynamic types
719         /// </summary>
720         public static bool HasElementType (TypeSpec t)
721         {
722                 return t is ElementTypeSpec;
723         }
724
725         /// <summary>
726         ///   Utility function that can be used to probe whether a type
727         ///   is managed or not.  
728         /// </summary>
729         public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc)
730         {
731                 while (t.IsPointer)
732                         t = GetElementType (t);
733
734                 if (IsUnmanagedType (t))
735                         return true;
736
737                 rc.Compiler.Report.SymbolRelatedToPreviousError (t);
738                 rc.Compiler.Report.Error (208, loc,
739                         "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
740                         CSharpName (t));
741
742                 return false;   
743         }
744 #region Generics
745         // This method always return false for non-generic compiler,
746         // while Type.IsGenericParameter is returned if it is supported.
747         public static bool IsGenericParameter (TypeSpec type)
748         {
749                 return type.IsGenericParameter;
750         }
751
752         public static bool IsGenericType (TypeSpec type)
753         {
754                 return type.IsGeneric;
755         }
756
757         public static TypeSpec[] GetTypeArguments (TypeSpec t)
758         {
759                 // TODO: return empty array !!
760                 return t.TypeArguments;
761         }
762
763         /// <summary>
764         ///   Check whether `type' and `parent' are both instantiations of the same
765         ///   generic type.  Note that we do not check the type parameters here.
766         /// </summary>
767         public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
768         {
769                 return type == parent || type.MemberDefinition == parent.MemberDefinition;
770         }
771
772         public static bool IsNullableType (TypeSpec t)
773         {
774                 return generic_nullable_type == t.GetDefinition ();
775         }
776 #endregion
777 }
778
779 }