f7bb202070dce9da21f396e376bbdd54bfad3bb8
[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 using System.IO;
19
20 namespace Mono.CSharp
21 {
22         //
23         // All compiler built-in types (they have to exist otherwise the compiler will not work)
24         //
25         public class BuiltinTypes
26         {
27                 public readonly BuiltinTypeSpec Object;
28                 public readonly BuiltinTypeSpec ValueType;
29                 public readonly BuiltinTypeSpec Attribute;
30
31                 public readonly BuiltinTypeSpec Int;
32                 public readonly BuiltinTypeSpec UInt;
33                 public readonly BuiltinTypeSpec Long;
34                 public readonly BuiltinTypeSpec ULong;
35                 public readonly BuiltinTypeSpec Float;
36                 public readonly BuiltinTypeSpec Double;
37                 public readonly BuiltinTypeSpec Char;
38                 public readonly BuiltinTypeSpec Short;
39                 public readonly BuiltinTypeSpec Decimal;
40                 public readonly BuiltinTypeSpec Bool;
41                 public readonly BuiltinTypeSpec SByte;
42                 public readonly BuiltinTypeSpec Byte;
43                 public readonly BuiltinTypeSpec UShort;
44                 public readonly BuiltinTypeSpec String;
45
46                 public readonly BuiltinTypeSpec Enum;
47                 public readonly BuiltinTypeSpec Delegate;
48                 public readonly BuiltinTypeSpec MulticastDelegate;
49                 public readonly BuiltinTypeSpec Void;
50                 public readonly BuiltinTypeSpec Array;
51                 public readonly BuiltinTypeSpec Type;
52                 public readonly BuiltinTypeSpec IEnumerator;
53                 public readonly BuiltinTypeSpec IEnumerable;
54                 public readonly BuiltinTypeSpec IDisposable;
55                 public readonly BuiltinTypeSpec IntPtr;
56                 public readonly BuiltinTypeSpec UIntPtr;
57                 public readonly BuiltinTypeSpec RuntimeFieldHandle;
58                 public readonly BuiltinTypeSpec RuntimeTypeHandle;
59                 public readonly BuiltinTypeSpec Exception;
60
61                 //
62                 // These are internal buil-in types which depend on other
63                 // build-in type (mostly object)
64                 //
65                 public readonly BuiltinTypeSpec Dynamic;
66
67                 // Predefined operators tables
68                 public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard;
69                 public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality;
70                 public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe;
71                 public readonly TypeSpec[][] OperatorsUnary;
72                 public readonly TypeSpec[] OperatorsUnaryMutator;
73
74                 public readonly TypeSpec[] BinaryPromotionsTypes;
75                 public readonly TypeSpec[] SwitchUserTypes;
76
77                 readonly BuiltinTypeSpec[] types;
78
79                 public BuiltinTypes ()
80                 {
81                         Object = new BuiltinTypeSpec (MemberKind.Class, "System", "Object", BuiltinTypeSpec.Type.Object);
82                         ValueType = new BuiltinTypeSpec (MemberKind.Class, "System", "ValueType", BuiltinTypeSpec.Type.ValueType);
83                         Attribute = new BuiltinTypeSpec (MemberKind.Class, "System", "Attribute", BuiltinTypeSpec.Type.Attribute);
84
85                         Int = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int32", BuiltinTypeSpec.Type.Int);
86                         Long = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int64", BuiltinTypeSpec.Type.Long);
87                         UInt = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt32", BuiltinTypeSpec.Type.UInt);
88                         ULong = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt64", BuiltinTypeSpec.Type.ULong);
89                         Byte = new BuiltinTypeSpec (MemberKind.Struct, "System", "Byte", BuiltinTypeSpec.Type.Byte);
90                         SByte = new BuiltinTypeSpec (MemberKind.Struct, "System", "SByte", BuiltinTypeSpec.Type.SByte);
91                         Short = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int16", BuiltinTypeSpec.Type.Short);
92                         UShort = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt16", BuiltinTypeSpec.Type.UShort);
93
94                         IEnumerator = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuiltinTypeSpec.Type.IEnumerator);
95                         IEnumerable = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuiltinTypeSpec.Type.IEnumerable);
96                         IDisposable = new BuiltinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuiltinTypeSpec.Type.IDisposable);
97
98                         Char = new BuiltinTypeSpec (MemberKind.Struct, "System", "Char", BuiltinTypeSpec.Type.Char);
99                         String = new BuiltinTypeSpec (MemberKind.Class, "System", "String", BuiltinTypeSpec.Type.String);
100                         Float = new BuiltinTypeSpec (MemberKind.Struct, "System", "Single", BuiltinTypeSpec.Type.Float);
101                         Double = new BuiltinTypeSpec (MemberKind.Struct, "System", "Double", BuiltinTypeSpec.Type.Double);
102                         Decimal = new BuiltinTypeSpec (MemberKind.Struct, "System", "Decimal", BuiltinTypeSpec.Type.Decimal);
103                         Bool = new BuiltinTypeSpec (MemberKind.Struct, "System", "Boolean", BuiltinTypeSpec.Type.Bool);
104                         IntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuiltinTypeSpec.Type.IntPtr);
105                         UIntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuiltinTypeSpec.Type.UIntPtr);
106
107                         MulticastDelegate = new BuiltinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuiltinTypeSpec.Type.MulticastDelegate);
108                         Delegate = new BuiltinTypeSpec (MemberKind.Class, "System", "Delegate", BuiltinTypeSpec.Type.Delegate);
109                         Enum = new BuiltinTypeSpec (MemberKind.Class, "System", "Enum", BuiltinTypeSpec.Type.Enum);
110                         Array = new BuiltinTypeSpec (MemberKind.Class, "System", "Array", BuiltinTypeSpec.Type.Array);
111                         Void = new BuiltinTypeSpec (MemberKind.Void, "System", "Void", BuiltinTypeSpec.Type.Other);
112                         Type = new BuiltinTypeSpec (MemberKind.Class, "System", "Type", BuiltinTypeSpec.Type.Type);
113                         Exception = new BuiltinTypeSpec (MemberKind.Class, "System", "Exception", BuiltinTypeSpec.Type.Exception);
114                         RuntimeFieldHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuiltinTypeSpec.Type.Other);
115                         RuntimeTypeHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuiltinTypeSpec.Type.Other);
116
117                         // TODO: Maybe I should promote it to different kind for faster compares
118                         Dynamic = new BuiltinTypeSpec ("dynamic", BuiltinTypeSpec.Type.Dynamic);
119
120                         OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this);
121                         OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this);
122                         OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this);
123                         OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this);
124                         OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this);
125
126                         BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this);
127                         SwitchUserTypes = Switch.CreateSwitchUserTypes (this);
128
129                         types = new BuiltinTypeSpec[] {
130                                 Object, ValueType, Attribute,
131                                 Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String,
132                                 Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable,
133                                 IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception };
134                 }
135
136                 public BuiltinTypeSpec[] AllTypes {
137                         get {
138                                 return types;
139                         }
140                 }
141
142                 public bool CheckDefinitions (ModuleContainer module)
143                 {
144                         var ctx = module.Compiler;
145                         foreach (var p in types) {
146                                 var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity);
147                                 if (found == null || found == p)
148                                         continue;
149
150                                 var tc = found.MemberDefinition as TypeContainer;
151                                 if (tc != null) {
152                                         var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false);
153                                         ns.SetBuiltinType (p);
154
155                                         tc.SetPredefinedSpec (p);
156                                         p.SetDefinition (found);
157                                 }
158                         }
159
160                         if (ctx.Report.Errors != 0)
161                                 return false;
162
163                         // Set internal build-in types
164                         Dynamic.SetDefinition (Object);
165
166                         return true;
167                 }
168         }
169
170         //
171         // Compiler predefined types. Usually used for compiler generated
172         // code or for comparison against well known framework type. They
173         // may not exist as they are optional
174         //
175         class PredefinedTypes
176         {
177                 public readonly PredefinedType ArgIterator;
178                 public readonly PredefinedType TypedReference;
179                 public readonly PredefinedType MarshalByRefObject;
180                 public readonly PredefinedType RuntimeHelpers;
181                 public readonly PredefinedType IAsyncResult;
182                 public readonly PredefinedType AsyncCallback;
183                 public readonly PredefinedType RuntimeArgumentHandle;
184                 public readonly PredefinedType CharSet;
185                 public readonly PredefinedType IsVolatile;
186                 public readonly PredefinedType IEnumeratorGeneric;
187                 public readonly PredefinedType IListGeneric;
188                 public readonly PredefinedType ICollectionGeneric;
189                 public readonly PredefinedType IEnumerableGeneric;
190                 public readonly PredefinedType Nullable;
191                 public readonly PredefinedType Activator;
192                 public readonly PredefinedType Interlocked;
193                 public readonly PredefinedType Monitor;
194                 public readonly PredefinedType NotSupportedException;
195                 public readonly PredefinedType RuntimeFieldHandle;
196                 public readonly PredefinedType RuntimeMethodHandle;
197                 public readonly PredefinedType SecurityAction;
198                 public readonly PredefinedType Dictionary;
199                 public readonly PredefinedType Hashtable;
200
201                 //
202                 // C# 3.0
203                 //
204                 public readonly PredefinedType Expression;
205                 public readonly PredefinedType ExpressionGeneric;
206                 public readonly PredefinedType ParameterExpression;
207                 public readonly PredefinedType FieldInfo;
208                 public readonly PredefinedType MethodBase;
209                 public readonly PredefinedType MethodInfo;
210                 public readonly PredefinedType ConstructorInfo;
211
212                 //
213                 // C# 4.0
214                 //
215                 public readonly PredefinedType Binder;
216                 public readonly PredefinedType CallSite;
217                 public readonly PredefinedType CallSiteGeneric;
218                 public readonly PredefinedType BinderFlags;
219
220                 public PredefinedTypes (ModuleContainer module)
221                 {
222                         TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference");
223                         ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator");
224
225                         MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject");
226                         RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers");
227                         IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult");
228                         AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback");
229                         RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle");
230                         CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet");
231                         IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile");
232                         IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1);
233                         IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1);
234                         ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1);
235                         IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1);
236                         Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1);
237                         Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator");
238                         Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked");
239                         Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor");
240                         NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException");
241                         RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle");
242                         RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle");
243                         SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction");
244                         Dictionary = new PredefinedType (module, MemberKind.Class, "System.Collections.Generic", "Dictionary", 2);
245                         Hashtable = new PredefinedType (module, MemberKind.Class, "System.Collections", "Hashtable");
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                         if (TypedReference.Define ())
265                                 TypedReference.TypeSpec.IsSpecialRuntimeType = true;
266
267                         if (ArgIterator.Define ())
268                                 ArgIterator.TypeSpec.IsSpecialRuntimeType = true;
269
270                         if (IEnumerableGeneric.Define ())
271                                 IEnumerableGeneric.TypeSpec.IsGenericIterateInterface = true;
272
273                         if (IListGeneric.Define ())
274                                 IListGeneric.TypeSpec.IsGenericIterateInterface = true;
275
276                         if (ICollectionGeneric.Define ())
277                                 ICollectionGeneric.TypeSpec.IsGenericIterateInterface = true;
278
279                         if (Nullable.Define ())
280                                 Nullable.TypeSpec.IsNullableType = true;
281
282                         if (ExpressionGeneric.Define ())
283                                 ExpressionGeneric.TypeSpec.IsExpressionTreeType = true;
284                 }
285         }
286
287         class PredefinedMembers
288         {
289                 public readonly PredefinedMember<MethodSpec> ActivatorCreateInstance;
290                 public readonly PredefinedMember<MethodSpec> DecimalCtor;
291                 public readonly PredefinedMember<MethodSpec> DecimalCtorInt;
292                 public readonly PredefinedMember<MethodSpec> DecimalCtorLong;
293                 public readonly PredefinedMember<MethodSpec> DecimalConstantAttributeCtor;
294                 public readonly PredefinedMember<MethodSpec> DefaultMemberAttributeCtor;
295                 public readonly PredefinedMember<MethodSpec> DelegateCombine;
296                 public readonly PredefinedMember<MethodSpec> DelegateEqual;
297                 public readonly PredefinedMember<MethodSpec> DelegateInequal;
298                 public readonly PredefinedMember<MethodSpec> DelegateRemove;
299                 public readonly PredefinedMember<MethodSpec> DynamicAttributeCtor;
300                 public readonly PredefinedMember<MethodSpec> FieldInfoGetFieldFromHandle;
301                 public readonly PredefinedMember<MethodSpec> FieldInfoGetFieldFromHandle2;
302                 public readonly PredefinedMember<MethodSpec> IDisposableDispose;
303                 public readonly PredefinedMember<MethodSpec> IEnumerableGetEnumerator;
304                 public readonly PredefinedMember<MethodSpec> InterlockedCompareExchange;
305                 public readonly PredefinedMember<MethodSpec> InterlockedCompareExchange_T;
306                 public readonly PredefinedMember<MethodSpec> FixedBufferAttributeCtor;
307                 public readonly PredefinedMember<MethodSpec> MethodInfoGetMethodFromHandle;
308                 public readonly PredefinedMember<MethodSpec> MethodInfoGetMethodFromHandle2;
309                 public readonly PredefinedMember<MethodSpec> MonitorEnter;
310                 public readonly PredefinedMember<MethodSpec> MonitorEnter_v4;
311                 public readonly PredefinedMember<MethodSpec> MonitorExit;
312                 public readonly PredefinedMember<PropertySpec> RuntimeCompatibilityWrapNonExceptionThrows;
313                 public readonly PredefinedMember<MethodSpec> RuntimeHelpersInitializeArray;
314                 public readonly PredefinedMember<PropertySpec> RuntimeHelpersOffsetToStringData;
315                 public readonly PredefinedMember<ConstSpec> SecurityActionRequestMinimum;
316                 public readonly PredefinedMember<FieldSpec> StringEmpty;
317                 public readonly PredefinedMember<MethodSpec> StringEqual;
318                 public readonly PredefinedMember<MethodSpec> StringInequal;
319                 public readonly PredefinedMember<MethodSpec> StructLayoutAttributeCtor;
320                 public readonly PredefinedMember<FieldSpec> StructLayoutCharSet;
321                 public readonly PredefinedMember<FieldSpec> StructLayoutPack;
322                 public readonly PredefinedMember<FieldSpec> StructLayoutSize;
323                 public readonly PredefinedMember<MethodSpec> TypeGetTypeFromHandle;
324
325                 public PredefinedMembers (ModuleContainer module)
326                 {
327                         var types = module.PredefinedTypes;
328                         var atypes = module.PredefinedAttributes;
329                         var btypes = module.Compiler.BuiltinTypes;
330
331                         ActivatorCreateInstance = new PredefinedMember<MethodSpec> (module, types.Activator,
332                                 MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null));
333
334                         DecimalCtor = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
335                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
336                                         btypes.Int, btypes.Int, btypes.Int, btypes.Bool, btypes.Byte)));
337
338                         DecimalCtorInt = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
339                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Int)));
340
341                         DecimalCtorLong = new PredefinedMember<MethodSpec> (module, btypes.Decimal,
342                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Long)));
343
344                         DecimalConstantAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DecimalConstant,
345                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
346                                         btypes.Byte, btypes.Byte, btypes.UInt, btypes.UInt, btypes.UInt)));
347
348                         DefaultMemberAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.DefaultMember,
349                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.String)));
350
351                         DelegateCombine = new PredefinedMember<MethodSpec> (module, btypes.Delegate, "Combine", btypes.Delegate, btypes.Delegate);
352                         DelegateRemove = new PredefinedMember<MethodSpec> (module, btypes.Delegate, "Remove", btypes.Delegate, btypes.Delegate);
353
354                         DelegateEqual = new PredefinedMember<MethodSpec> (module, btypes.Delegate,
355                                 new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool));
356
357                         DelegateInequal = new PredefinedMember<MethodSpec> (module, btypes.Delegate,
358                                 new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool));
359
360                         DynamicAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.Dynamic,
361                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (
362                                         ArrayContainer.MakeType (module, btypes.Bool))));
363
364                         FieldInfoGetFieldFromHandle = new PredefinedMember<MethodSpec> (module, types.FieldInfo,
365                                 "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle);
366
367                         FieldInfoGetFieldFromHandle2 = new PredefinedMember<MethodSpec> (module, types.FieldInfo,
368                                 "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle, new PredefinedType (btypes.RuntimeTypeHandle));
369
370                         FixedBufferAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.FixedBuffer,
371                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Type, btypes.Int)));
372
373                         IDisposableDispose = new PredefinedMember<MethodSpec> (module, btypes.IDisposable, "Dispose", TypeSpec.EmptyTypes);
374
375                         IEnumerableGetEnumerator = new PredefinedMember<MethodSpec> (module, btypes.IEnumerable,
376                                 "GetEnumerator", TypeSpec.EmptyTypes);
377
378                         InterlockedCompareExchange = new PredefinedMember<MethodSpec> (module, types.Interlocked,
379                                 MemberFilter.Method ("CompareExchange", 0,
380                                         new ParametersImported (
381                                                 new[] {
382                                                                 new ParameterData (null, Parameter.Modifier.REF),
383                                                                 new ParameterData (null, Parameter.Modifier.NONE),
384                                                                 new ParameterData (null, Parameter.Modifier.NONE)
385                                                         },
386                                                 new[] {
387                                                                 btypes.Int, btypes.Int, btypes.Int
388                                                         },
389                                                 false),
390                                 btypes.Int));
391
392                         InterlockedCompareExchange_T = new PredefinedMember<MethodSpec> (module, types.Interlocked,
393                                 MemberFilter.Method ("CompareExchange", 1,
394                                         new ParametersImported (
395                                                 new[] {
396                                                                 new ParameterData (null, Parameter.Modifier.REF),
397                                                                 new ParameterData (null, Parameter.Modifier.NONE),
398                                                                 new ParameterData (null, Parameter.Modifier.NONE)
399                                                         },
400                                                 new[] {
401                                                                 new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
402                                                                 new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
403                                                                 new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null),
404                                                         }, false),
405                                         null));
406
407                         MethodInfoGetMethodFromHandle = new PredefinedMember<MethodSpec> (module, types.MethodBase,
408                                 "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle);
409
410                         MethodInfoGetMethodFromHandle2 = new PredefinedMember<MethodSpec> (module, types.MethodBase,
411                                 "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle, new PredefinedType (btypes.RuntimeTypeHandle));
412
413                         MonitorEnter = new PredefinedMember<MethodSpec> (module, types.Monitor, "Enter", btypes.Object);
414
415                         MonitorEnter_v4 = new PredefinedMember<MethodSpec> (module, types.Monitor,
416                                 MemberFilter.Method ("Enter", 0,
417                                         new ParametersImported (new[] {
418                                                         new ParameterData (null, Parameter.Modifier.NONE),
419                                                         new ParameterData (null, Parameter.Modifier.REF)
420                                                 },
421                                         new[] {
422                                                         btypes.Object, btypes.Bool
423                                                 }, false), null));
424
425                         MonitorExit = new PredefinedMember<MethodSpec> (module, types.Monitor, "Exit", btypes.Object);
426
427                         RuntimeCompatibilityWrapNonExceptionThrows = new PredefinedMember<PropertySpec> (module, atypes.RuntimeCompatibility,
428                                 MemberFilter.Property ("WrapNonExceptionThrows", btypes.Bool));
429
430                         RuntimeHelpersInitializeArray = new PredefinedMember<MethodSpec> (module, types.RuntimeHelpers,
431                                 "InitializeArray", btypes.Array, btypes.RuntimeFieldHandle);
432
433                         RuntimeHelpersOffsetToStringData = new PredefinedMember<PropertySpec> (module, types.RuntimeHelpers,
434                                 MemberFilter.Property ("OffsetToStringData", btypes.Int));
435
436                         SecurityActionRequestMinimum = new PredefinedMember<ConstSpec> (module, types.SecurityAction, "RequestMinimum",
437                                 MemberKind.Field, types.SecurityAction);
438
439                         StringEmpty = new PredefinedMember<FieldSpec> (module, btypes.String, MemberFilter.Field ("Empty", btypes.String));
440
441                         StringEqual = new PredefinedMember<MethodSpec> (module, btypes.String,
442                                 new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool));
443
444                         StringInequal = new PredefinedMember<MethodSpec> (module, btypes.String,
445                                 new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool));
446
447                         StructLayoutAttributeCtor = new PredefinedMember<MethodSpec> (module, atypes.StructLayout,
448                                 MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Short)));
449
450                         StructLayoutCharSet = new PredefinedMember<FieldSpec> (module, atypes.StructLayout, "CharSet",
451                                 MemberKind.Field, types.CharSet);
452
453                         StructLayoutPack = new PredefinedMember<FieldSpec> (module, atypes.StructLayout,
454                                 MemberFilter.Field ("Pack", btypes.Int));
455
456                         StructLayoutSize = new PredefinedMember<FieldSpec> (module, atypes.StructLayout,
457                                 MemberFilter.Field ("Size", btypes.Int));
458
459                         TypeGetTypeFromHandle = new PredefinedMember<MethodSpec> (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle);
460                 }
461         }
462
463         public class PredefinedType
464         {
465                 readonly string name;
466                 readonly string ns;
467                 readonly int arity;
468                 readonly MemberKind kind;
469                 protected readonly ModuleContainer module;
470                 protected TypeSpec type;
471
472                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
473                         : this (module, kind, ns, name)
474                 {
475                         this.arity = arity;
476                 }
477
478                 public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name)
479                 {
480                         this.module = module;
481                         this.kind = kind;
482                         this.name = name;
483                         this.ns = ns;
484                 }
485
486                 public PredefinedType (BuiltinTypeSpec type)
487                 {
488                         this.kind = type.Kind;
489                         this.name = type.Name;
490                         this.ns = type.Namespace;
491                         this.type = type;
492                 }
493
494                 #region Properties
495
496                 public int Arity {
497                         get {
498                                 return arity;
499                         }
500                 }
501
502                 public bool IsDefined {
503                         get {
504                                 return type != null;
505                         }
506                 }
507
508                 public string Name {
509                         get {
510                                 return name;
511                         }
512                 }
513
514                 public string Namespace {
515                         get {
516                                 return ns;
517                         }
518                 }
519
520                 public TypeSpec TypeSpec {
521                         get {
522                                 return type;
523                         }
524                 }
525
526                 #endregion
527
528                 public bool Define ()
529                 {
530                         if (type != null)
531                                 return true;
532
533                         type = Resolve (module, kind, ns, name, arity, false);
534                         return type != null;
535                 }
536
537                 public string GetSignatureForError ()
538                 {
539                         return ns + "." + name;
540                 }
541
542                 public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity)
543                 {
544                         return Resolve (module, kind, ns, name, arity, true);
545                 }
546
547                 public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, bool reportErrors)
548                 {
549                         Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true);
550                         var found = type_ns.GetAllTypes (name);
551                         if (found == null) {
552                                 if (reportErrors)
553                                         module.Compiler.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", ns, name);
554
555                                 return null;
556                         }
557
558                         TypeSpec best_match = null;
559                         foreach (var candidate in found) {
560                                 if (candidate.Kind != kind) {
561                                         if (candidate.Kind == MemberKind.Struct && kind == MemberKind.Void && candidate.MemberDefinition is TypeContainer) {
562                                                 // Void is declared as struct but we keep it internally as
563                                                 // special kind, the swap will be done by caller
564                                         } else {
565                                                 continue;
566                                         }
567                                 }
568
569                                 if (candidate.Arity != arity)
570                                         continue;
571
572                                 if ((candidate.Modifiers & Modifiers.INTERNAL) != 0 && !candidate.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly))
573                                         continue;
574
575                                 if (best_match == null) {
576                                         best_match = candidate;
577                                         continue;
578                                 }
579
580                                 var other_match = best_match;
581                                 if (!best_match.MemberDefinition.IsImported &&
582                                         module.Compiler.BuiltinTypes.Object.MemberDefinition.DeclaringAssembly == candidate.MemberDefinition.DeclaringAssembly) {
583                                         best_match = candidate;
584                                 }
585
586                                 string location;
587                                 if (best_match.MemberDefinition is MemberCore) {
588                                         location = ((MemberCore) best_match.MemberDefinition).Location.Name;
589                                 } else {
590                                         var assembly = (ImportedAssemblyDefinition) best_match.MemberDefinition.DeclaringAssembly;
591                                         location = Path.GetFileName (assembly.Location);
592                                 }
593
594                                 module.Compiler.Report.SymbolRelatedToPreviousError (other_match);
595                                 module.Compiler.Report.SymbolRelatedToPreviousError (candidate);
596
597                                 module.Compiler.Report.Warning (1685, 1,
598                                         "The predefined type `{0}.{1}' is defined multiple times. Using definition from `{2}'",
599                                         ns, name, location);
600
601                                 break;
602                         }
603
604                         if (best_match == null && reportErrors) {
605                                 Location loc;
606                                 if (found[0].MemberDefinition is MemberCore) {
607                                         loc = ((MemberCore) found[0].MemberDefinition).Location;
608                                 } else {
609                                         loc = Location.Null;
610                                         module.Compiler.Report.SymbolRelatedToPreviousError (found[0]);
611                                 }
612
613                                 module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name);
614                         }
615
616                         return best_match;
617                 }
618
619                 public TypeSpec Resolve ()
620                 {
621                         if (type == null)
622                                 type = Resolve (module, kind, ns, name, arity);
623
624                         return type;
625                 }
626         }
627
628         class PredefinedMember<T> where T : MemberSpec
629         {
630                 readonly ModuleContainer module;
631                 T member;
632                 TypeSpec declaring_type;
633                 readonly PredefinedType declaring_type_predefined;
634                 readonly PredefinedType[] parameters_predefined;
635                 MemberFilter filter;
636
637                 public PredefinedMember (ModuleContainer module, PredefinedType type, MemberFilter filter)
638                 {
639                         this.module = module;
640                         this.declaring_type_predefined = type;
641                         this.filter = filter;
642                 }
643
644                 public PredefinedMember (ModuleContainer module, TypeSpec type, MemberFilter filter)
645                 {
646                         this.module = module;
647                         this.declaring_type = type;
648                         this.filter = filter;
649                 }
650
651                 public PredefinedMember (ModuleContainer module, PredefinedType type, string name, params TypeSpec[] types)
652                         : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null))
653                 {
654                 }
655
656                 public PredefinedMember (ModuleContainer module, PredefinedType type, string name, MemberKind kind, params PredefinedType[] types)
657                         : this (module, type, new MemberFilter (name, 0, kind, null, null))
658                 {
659                         parameters_predefined = types;
660                 }
661
662                 public PredefinedMember (ModuleContainer module, BuiltinTypeSpec type, string name, params TypeSpec[] types)
663                         : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null))
664                 {
665                 }
666
667                 public T Get ()
668                 {
669                         if (member != null)
670                                 return member;
671
672                         if (declaring_type == null) {
673                                 if (!declaring_type_predefined.Define ())
674                                         return null;
675
676                                 declaring_type = declaring_type_predefined.TypeSpec;
677                         }
678
679                         if (parameters_predefined != null) {
680                                 TypeSpec[] types = new TypeSpec [parameters_predefined.Length];
681                                 for (int i = 0; i < types.Length; ++i) {
682                                         var p = parameters_predefined [i];
683                                         if (!p.Define ())
684                                                 return null;
685
686                                         types[i] = p.TypeSpec;
687                                 }
688
689                                 if (filter.Kind == MemberKind.Field)
690                                         filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, null, types [0]);
691                                 else
692                                         filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType);
693                         }
694
695                         member = MemberCache.FindMember (declaring_type, filter, BindingRestriction.DeclaredOnly) as T;
696                         if (member == null)
697                                 return null;
698
699                         if (!member.IsAccessible (module))
700                                 return null;
701
702                         return member;
703                 }
704
705                 public T Resolve (Location loc)
706                 {
707                         if (member != null)
708                                 return member;
709
710                         if (Get () != null)
711                                 return member;
712
713                         if (declaring_type == null) {
714                                 if (declaring_type_predefined.Resolve () == null)
715                                         return null;
716                         }
717
718                         if (parameters_predefined != null) {
719                                 TypeSpec[] types = new TypeSpec[parameters_predefined.Length];
720                                 for (int i = 0; i < types.Length; ++i) {
721                                         var p = parameters_predefined[i];
722                                         types[i] = p.Resolve ();
723                                         if (types[i] == null)
724                                                 return null;
725                                 }
726
727                                 filter = new MemberFilter (filter.Name, filter.Arity, filter.Kind, ParametersCompiled.CreateFullyResolved (types), filter.MemberType);
728                         }
729
730                         string method_args = null;
731                         if (filter.Parameters != null)
732                                 method_args = filter.Parameters.GetSignatureForError ();
733
734                         module.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible",
735                                 declaring_type.GetSignatureForError (), filter.Name, method_args);
736
737                         return null;
738                 }
739         }
740
741         partial class TypeManager {
742
743         /// <summary>
744         ///   Returns the C# name of a type if possible, or the full type name otherwise
745         /// </summary>
746         static public string CSharpName (TypeSpec t)
747         {
748                 return t.GetSignatureForError ();
749         }
750
751         static public string CSharpName (IList<TypeSpec> types)
752         {
753                 if (types.Count == 0)
754                         return string.Empty;
755
756                 StringBuilder sb = new StringBuilder ();
757                 for (int i = 0; i < types.Count; ++i) {
758                         if (i > 0)
759                                 sb.Append (",");
760
761                         sb.Append (CSharpName (types [i]));
762                 }
763                 return sb.ToString ();
764         }
765
766         static public string GetFullNameSignature (MemberSpec mi)
767         {
768                 return mi.GetSignatureForError ();
769         }
770
771         static public string CSharpSignature (MemberSpec mb)
772         {
773                 return mb.GetSignatureForError ();
774         }
775
776         // Obsolete
777         public static bool IsDelegateType (TypeSpec t)
778         {
779                 return t.IsDelegate;
780         }
781         
782         // Obsolete
783         public static bool IsEnumType (TypeSpec t)
784         {
785                 return t.IsEnum;
786         }
787
788         //
789         // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
790         //
791         public static bool IsUnmanagedType (TypeSpec t)
792         {
793                 var ds = t.MemberDefinition as DeclSpace;
794                 if (ds != null)
795                         return ds.IsUnmanagedType ();
796
797                 if (t.Kind == MemberKind.Void)
798                         return true;
799
800                 // Someone did the work of checking if the ElementType of t is unmanaged.  Let's not repeat it.
801                 if (t.IsPointer)
802                         return IsUnmanagedType (GetElementType (t));
803
804                 if (!IsValueType (t))
805                         return false;
806
807                 if (t.IsNested && t.DeclaringType.IsGenericOrParentIsGeneric)
808                         return false;
809
810                 return true;
811         }
812
813         //
814         // Null is considered to be a reference type
815         //                      
816         public static bool IsReferenceType (TypeSpec t)
817         {
818                 if (t.IsGenericParameter)
819                         return ((TypeParameterSpec) t).IsReferenceType;
820
821                 return !t.IsStruct && !IsEnumType (t);
822         }                       
823                 
824         public static bool IsValueType (TypeSpec t)
825         {
826                 if (t.IsGenericParameter)
827                         return ((TypeParameterSpec) t).IsValueType;
828
829                 return t.IsStruct || IsEnumType (t);
830         }
831
832         public static bool IsFamilyAccessible (TypeSpec type, TypeSpec parent)
833         {
834 //              TypeParameter tparam = LookupTypeParameter (type);
835 //              TypeParameter pparam = LookupTypeParameter (parent);
836
837                 if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) {
838                         if (type == parent)
839                                 return true;
840
841                         throw new NotImplementedException ("net");
842 //                      return tparam.IsSubclassOf (parent);
843                 }
844
845                 do {
846                         if (IsInstantiationOfSameGenericType (type, parent))
847                                 return true;
848
849                         type = type.BaseType;
850                 } while (type != null);
851
852                 return false;
853         }
854
855         //
856         // Checks whether `type' is a nested child of `parent'.
857         //
858         public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent)
859         {
860                 if (type == null)
861                         return false;
862
863                 if (type.MemberDefinition == parent)
864                         return false;
865
866                 type = type.DeclaringType;
867                 while (type != null) {
868                         if (type.MemberDefinition == parent)
869                                 return true;
870
871                         type = type.DeclaringType;
872                 }
873
874                 return false;
875         }
876
877         public static TypeSpec GetElementType (TypeSpec t)
878         {
879                 return ((ElementTypeSpec)t).Element;
880         }
881
882         /// <summary>
883         /// This method is not implemented by MS runtime for dynamic types
884         /// </summary>
885         public static bool HasElementType (TypeSpec t)
886         {
887                 return t is ElementTypeSpec;
888         }
889
890         /// <summary>
891         ///   Utility function that can be used to probe whether a type
892         ///   is managed or not.  
893         /// </summary>
894         public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc)
895         {
896                 while (t.IsPointer)
897                         t = GetElementType (t);
898
899                 if (IsUnmanagedType (t))
900                         return true;
901
902                 rc.Compiler.Report.SymbolRelatedToPreviousError (t);
903                 rc.Compiler.Report.Error (208, loc,
904                         "Cannot take the address of, get the size of, or declare a pointer to a managed type `{0}'",
905                         CSharpName (t));
906
907                 return false;   
908         }
909 #region Generics
910         // This method always return false for non-generic compiler,
911         // while Type.IsGenericParameter is returned if it is supported.
912         public static bool IsGenericParameter (TypeSpec type)
913         {
914                 return type.IsGenericParameter;
915         }
916
917         public static bool IsGenericType (TypeSpec type)
918         {
919                 return type.IsGeneric;
920         }
921
922         public static TypeSpec[] GetTypeArguments (TypeSpec t)
923         {
924                 // TODO: return empty array !!
925                 return t.TypeArguments;
926         }
927
928         /// <summary>
929         ///   Check whether `type' and `parent' are both instantiations of the same
930         ///   generic type.  Note that we do not check the type parameters here.
931         /// </summary>
932         public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent)
933         {
934                 return type == parent || type.MemberDefinition == parent.MemberDefinition;
935         }
936 #endregion
937 }
938
939 }