Halve the stack depth for both the new single step tests
[mono.git] / mcs / class / corlib / ReferenceSources / RuntimeType.cs
1 //
2 // RuntimeType.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2015 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Reflection;
30 using System.Runtime.CompilerServices;
31 using System.Threading;
32 using System.Collections.Generic;
33 using System.Runtime.InteropServices;
34 using System.Globalization;
35 #if MONO_COM
36 using System.Reflection.Emit;
37 #endif
38 using System.Diagnostics.Contracts;
39 using System.Security;
40 using System.Runtime.Serialization;
41
42 namespace System
43 {
44         partial class RuntimeType
45         {
46                 internal Object GenericCache;
47
48                 internal virtual MonoCMethod GetDefaultConstructor ()
49                 {
50                         // TODO: Requires MonoType
51                         throw new NotSupportedException ();
52                 }
53
54                 string GetDefaultMemberName ()
55                 {
56                         object [] att = GetCustomAttributes (typeof (DefaultMemberAttribute), true);
57                         return att.Length != 0 ? ((DefaultMemberAttribute) att [0]).MemberName : null;
58                 }
59
60                 RuntimeConstructorInfo m_serializationCtor;
61                 internal RuntimeConstructorInfo GetSerializationCtor()
62                 {
63                         if (m_serializationCtor == null) {
64                                 var s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
65
66                                 m_serializationCtor = GetConstructor(
67                                         BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
68                                         null,
69                                         CallingConventions.Any,
70                                         s_SICtorParamTypes,
71                                         null) as RuntimeConstructorInfo;
72                         }
73
74                         return m_serializationCtor;
75                 }
76
77                 internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
78                 {
79                         bool bNeedSecurityCheck = true;
80                         bool bCanBeCached = false;
81                         bool bSecurityCheckOff = false;
82
83                         if (!skipCheckThis)
84                                 CreateInstanceCheckThis();
85
86                         if (!fillCache)
87                                 bSecurityCheckOff = true;
88
89                         return CreateInstanceMono (!publicOnly);
90                 }
91
92                 object CreateInstanceMono (bool nonPublic)
93                 {
94                         var ctor = GetDefaultConstructor ();
95                         if (!nonPublic && ctor != null && !ctor.IsPublic) {
96                                 ctor = null;
97                         }
98
99                         if (ctor == null) {
100                                 Type elementType = this.GetRootElementType();
101                                 if (ReferenceEquals (elementType, typeof (TypedReference)) || ReferenceEquals (elementType, typeof (RuntimeArgumentHandle)))
102                                         throw new NotSupportedException (Environment.GetResourceString ("NotSupported_ContainsStackPtr"));
103
104                                 if (IsValueType)
105                                         return CreateInstanceInternal (this);
106
107                                 throw new MissingMethodException (Locale.GetText ("Default constructor not found for type " + FullName));
108                         }
109
110                         // TODO: .net does more checks in unmanaged land in RuntimeTypeHandle::CreateInstance
111                         if (IsAbstract) {
112                                 throw new MissingMethodException (Locale.GetText ("Cannot create an abstract class '{0}'.", FullName));
113                         }
114
115                         return ctor.InternalInvoke (null, null);
116                 }
117
118                 internal Object CheckValue (Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
119                 {
120                         bool failed = false;
121                         var res = TryConvertToType (value, ref failed);
122                         if (!failed)
123                                 return res;
124
125                         if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
126                                 throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
127
128                         if (binder != null && binder != Type.DefaultBinder)
129                                 return binder.ChangeType (value, this, culture);
130
131                         throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
132                 }
133
134                 object TryConvertToType (object value, ref bool failed)
135                 {
136                         if (IsInstanceOfType (value)) {
137                                 return value;
138                         }
139
140                         if (IsByRef) {
141                                 var elementType = GetElementType ();
142                                 if (value == null || elementType.IsInstanceOfType (value)) {
143                                         return value;
144                                 }
145                         }
146
147                         if (value == null)
148                                 return value;
149
150                         if (IsEnum) {
151                                 var type = Enum.GetUnderlyingType (this);
152                                 if (type == value.GetType ())
153                                         return value;
154                                 var res = IsConvertibleToPrimitiveType (value, this);
155                                 if (res != null)
156                                         return res;
157                         } else if (IsPrimitive) {
158                                 var res = IsConvertibleToPrimitiveType (value, this);
159                                 if (res != null)
160                                         return res;
161                         } else if (IsPointer) {
162                                 var vtype = value.GetType ();
163                                 if (vtype == typeof (IntPtr) || vtype == typeof (UIntPtr))
164                                         return value;
165                         }
166
167                         failed = true;
168                         return null;
169                 }
170
171                 // Binder uses some incompatible conversion rules. For example
172                 // int value cannot be used with decimal parameter but in other
173                 // ways it's more flexible than normal convertor, for example
174                 // long value can be used with int based enum
175                 static object IsConvertibleToPrimitiveType (object value, Type targetType)
176                 {
177                         var type = value.GetType ();
178                         if (type.IsEnum) {
179                                 type = Enum.GetUnderlyingType (type);
180                                 if (type == targetType)
181                                         return value;
182                         }
183
184                         var from = Type.GetTypeCode (type);
185                         var to = Type.GetTypeCode (targetType);
186
187                         switch (to) {
188                                 case TypeCode.Char:
189                                         switch (from) {
190                                                 case TypeCode.Byte:
191                                                         return (Char) (Byte) value;
192                                                 case TypeCode.UInt16:
193                                                         return value;
194                                         }
195                                         break;
196                                 case TypeCode.Int16:
197                                         switch (from) {
198                                                 case TypeCode.Byte:
199                                                         return (Int16) (Byte) value;
200                                                 case TypeCode.SByte:
201                                                         return (Int16) (SByte) value;
202                                         }
203                                         break;
204                                 case TypeCode.UInt16:
205                                         switch (from) {
206                                                 case TypeCode.Byte:
207                                                         return (UInt16) (Byte) value;
208                                                 case TypeCode.Char:
209                                                         return value;
210                                         }
211                                         break;
212                                 case TypeCode.Int32:
213                                         switch (from) {
214                                                 case TypeCode.Byte:
215                                                         return (Int32) (Byte) value;
216                                                 case TypeCode.SByte:
217                                                         return (Int32) (SByte) value;
218                                                 case TypeCode.Char:
219                                                         return (Int32) (Char) value;
220                                                 case TypeCode.Int16:
221                                                         return (Int32) (Int16) value;
222                                                 case TypeCode.UInt16:
223                                                         return (Int32) (UInt16) value;
224                                         }
225                                         break;
226                                 case TypeCode.UInt32:
227                                         switch (from) {
228                                                 case TypeCode.Byte:
229                                                         return (UInt32) (Byte) value;
230                                                 case TypeCode.Char:
231                                                         return (UInt32) (Char) value;
232                                                 case TypeCode.UInt16:
233                                                         return (UInt32) (UInt16) value;
234                                         }
235                                         break;
236                                 case TypeCode.Int64:
237                                         switch (from) {
238                                                 case TypeCode.Byte:
239                                                         return (Int64) (Byte) value;
240                                                 case TypeCode.SByte:
241                                                         return (Int64) (SByte) value;
242                                                 case TypeCode.Int16:
243                                                         return (Int64) (Int16) value;
244                                                 case TypeCode.Char:
245                                                         return (Int64) (Char) value;
246                                                 case TypeCode.UInt16:
247                                                         return (Int64) (UInt16) value;
248                                                 case TypeCode.Int32:
249                                                         return (Int64) (Int32) value;
250                                                 case TypeCode.UInt32:
251                                                         return (Int64) (UInt32) value;
252                                         }
253                                         break;
254                                 case TypeCode.UInt64:
255                                         switch (from) {
256                                                 case TypeCode.Byte:
257                                                         return (UInt64) (Byte) value;
258                                                 case TypeCode.Char:
259                                                         return (UInt64) (Char) value;
260                                                 case TypeCode.UInt16:
261                                                         return (UInt64) (UInt16) value;
262                                                 case TypeCode.UInt32:
263                                                         return (UInt64) (UInt32) value;
264                                         }
265                                         break;
266                                 case TypeCode.Single:
267                                         switch (from) {
268                                                 case TypeCode.Byte:
269                                                         return (Single) (Byte) value;
270                                                 case TypeCode.SByte:
271                                                         return (Single) (SByte) value;
272                                                 case TypeCode.Int16:
273                                                         return (Single) (Int16) value;
274                                                 case TypeCode.Char:
275                                                         return (Single) (Char) value;
276                                                 case TypeCode.UInt16:
277                                                         return (Single) (UInt16) value;
278                                                 case TypeCode.Int32:
279                                                         return (Single) (Int32) value;
280                                                 case TypeCode.UInt32:
281                                                         return (Single) (UInt32) value;
282                                                 case TypeCode.Int64:
283                                                         return (Single) (Int64) value;
284                                                 case TypeCode.UInt64:
285                                                         return (Single) (UInt64) value;
286                                         }
287                                         break;
288                                 case TypeCode.Double:
289                                         switch (from) {
290                                                 case TypeCode.Byte:
291                                                         return (Double) (Byte) value;
292                                                 case TypeCode.SByte:
293                                                         return (Double) (SByte) value;
294                                                 case TypeCode.Char:
295                                                         return (Double) (Char) value;
296                                                 case TypeCode.Int16:
297                                                         return (Double) (Int16) value;
298                                                 case TypeCode.UInt16:
299                                                         return (Double) (UInt16) value;
300                                                 case TypeCode.Int32:
301                                                         return (Double) (Int32) value;
302                                                 case TypeCode.UInt32:
303                                                         return (Double) (UInt32) value;
304                                                 case TypeCode.Int64:
305                                                         return (Double) (Int64) value;
306                                                 case TypeCode.UInt64:
307                                                         return (Double) (UInt64) value;
308                                                 case TypeCode.Single:
309                                                         return (Double) (Single) value;
310                                         }
311                                         break;
312                         }
313
314                         // Everything else is rejected
315                         return null;
316                 }
317
318                 string GetCachedName (TypeNameKind kind)
319                 {
320                         switch (kind) {
321                         case TypeNameKind.SerializationName:
322                                 return ToString ();
323                         default:
324                                 throw new NotImplementedException ();
325                         }
326                 }
327
328                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
329                 extern Type make_array_type (int rank);
330
331                 public override Type MakeArrayType ()
332                 {
333                         return make_array_type (0);
334                 }
335
336                 public override Type MakeArrayType (int rank)
337                 {
338                         if (rank < 1 || rank > 255)
339                                 throw new IndexOutOfRangeException ();
340                         return make_array_type (rank);
341                 }
342
343                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
344                 extern Type make_byref_type ();
345
346                 public override Type MakeByRefType ()
347                 {
348                         if (IsByRef)
349                                 throw new TypeLoadException ("Can not call MakeByRefType on a ByRef type");
350                         return make_byref_type ();
351                 }
352
353                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
354                 static extern Type MakePointerType (Type type);
355
356                 public override Type MakePointerType ()
357                 {
358                         return MakePointerType (this);
359                 }
360
361                 public override StructLayoutAttribute StructLayoutAttribute {
362                         get {
363                                 return StructLayoutAttribute.GetCustomAttribute (this);
364                         }
365                 }
366
367                 public override bool ContainsGenericParameters {
368                         get {
369                                 if (IsGenericParameter)
370                                         return true;
371
372                                 if (IsGenericType) {
373                                         foreach (Type arg in GetGenericArguments ())
374                                                 if (arg.ContainsGenericParameters)
375                                                         return true;
376                                 }
377
378                                 if (HasElementType)
379                                         return GetElementType ().ContainsGenericParameters;
380
381                                 return false;
382                         }
383                 }
384
385                 public override Type[] GetGenericParameterConstraints()
386                 {
387                         if (!IsGenericParameter)
388                                 throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
389                         Contract.EndContractBlock();
390
391                         Type[] constraints = GetGenericParameterConstraints_impl ();
392
393                         if (constraints == null)
394                                 constraints = EmptyArray<Type>.Value;
395
396                         return constraints;
397                 }
398
399                 internal static object CreateInstanceForAnotherGenericParameter (Type genericType, RuntimeType genericArgument)
400                 {
401                         var gt = (RuntimeType) MakeGenericType (genericType, new Type [] { genericArgument });
402                         var ctor = gt.GetDefaultConstructor ();
403                         return ctor.InternalInvoke (null, null);
404                 }
405
406                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
407                 static extern Type MakeGenericType (Type gt, Type [] types);
408
409                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
410                 internal extern RuntimeMethodInfo[] GetMethodsByName (string name, BindingFlags bindingAttr, bool ignoreCase, Type reflected_type);
411
412                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
413                 extern RuntimePropertyInfo[] GetPropertiesByName (string name, BindingFlags bindingAttr, bool icase, Type reflected_type);              
414
415                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
416                 extern RuntimeConstructorInfo[] GetConstructors_internal (BindingFlags bindingAttr, Type reflected_type);
417
418                 public override InterfaceMapping GetInterfaceMap (Type ifaceType)
419                 {
420                         if (IsGenericParameter)
421                                 throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
422                 
423                         if ((object)ifaceType == null)
424                                 throw new ArgumentNullException("ifaceType");
425                         Contract.EndContractBlock();
426
427                         RuntimeType ifaceRtType = ifaceType as RuntimeType;
428
429                         if (ifaceRtType == null)
430                                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
431
432                         InterfaceMapping res;
433                         if (!ifaceType.IsInterface)
434                                 throw new ArgumentException (Locale.GetText ("Argument must be an interface."), "ifaceType");
435                         if (IsInterface)
436                                 throw new ArgumentException ("'this' type cannot be an interface itself");
437                         res.TargetType = this;
438                         res.InterfaceType = ifaceType;
439                         GetInterfaceMapData (this, ifaceType, out res.TargetMethods, out res.InterfaceMethods);
440                         if (res.TargetMethods == null)
441                                 throw new ArgumentException (Locale.GetText ("Interface not found"), "ifaceType");
442
443                         return res;
444                 }
445
446                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
447                 static extern void GetInterfaceMapData (Type t, Type iface, out MethodInfo[] targets, out MethodInfo[] methods);                
448
449                 public override Guid GUID {
450                         get {
451                                 object[] att = GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), true);
452                                 if (att.Length == 0)
453                                         return Guid.Empty;
454                                 return new Guid(((System.Runtime.InteropServices.GuidAttribute)att[0]).Value);
455                         }
456                 }
457
458                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
459                 internal extern void GetPacking (out int packing, out int size);
460
461 #if MONO_COM
462                 private static Dictionary<Guid, Type> clsid_types;
463                 private static AssemblyBuilder clsid_assemblybuilder;
464 #endif
465
466                 internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
467                 {
468 #if MONO_COM
469                         Type result;
470
471                         if (clsid_types == null)
472                         {
473                                 Dictionary<Guid, Type> new_clsid_types = new Dictionary<Guid, Type> ();
474                                 Interlocked.CompareExchange<Dictionary<Guid, Type>>(
475                                         ref clsid_types, new_clsid_types, null);
476                         }
477
478                         lock (clsid_types) {
479                                 if (clsid_types.TryGetValue(clsid, out result))
480                                         return result;
481
482                                 if (clsid_assemblybuilder == null)
483                                 {
484                                         AssemblyName assemblyname = new AssemblyName ();
485                                         assemblyname.Name = "GetTypeFromCLSIDDummyAssembly";
486                                         clsid_assemblybuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (
487                                                 assemblyname, AssemblyBuilderAccess.Run);
488                                 }
489                                 ModuleBuilder modulebuilder = clsid_assemblybuilder.DefineDynamicModule (
490                                         clsid.ToString ());
491
492                                 TypeBuilder typebuilder = modulebuilder.DefineType ("System.__ComObject",
493                                         TypeAttributes.Public | TypeAttributes.Class, typeof(System.__ComObject));
494
495                                 Type[] guidattrtypes = new Type[] { typeof(string) };
496
497                                 CustomAttributeBuilder customattr = new CustomAttributeBuilder (
498                                         typeof(GuidAttribute).GetConstructor (guidattrtypes),
499                                         new object[] { clsid.ToString () });
500
501                                 typebuilder.SetCustomAttribute (customattr);
502
503                                 customattr = new CustomAttributeBuilder (
504                                         typeof(ComImportAttribute).GetConstructor (EmptyTypes),
505                                         new object[0] {});
506
507                                 typebuilder.SetCustomAttribute (customattr);
508
509                                 result = typebuilder.CreateType ();
510
511                                 clsid_types.Add(clsid, result);
512
513                                 return result;
514                         }
515 #else
516                         throw new NotImplementedException ("Unmanaged activation removed");
517 #endif
518                 }
519
520                 protected override TypeCode GetTypeCodeImpl ()
521                 {
522                         return GetTypeCodeImplInternal (this);
523                 }
524
525                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
526                 extern static TypeCode GetTypeCodeImplInternal (Type type);             
527
528                 internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
529                 {
530                         throw new NotImplementedException ("Unmanaged activation is not supported");
531                 }
532
533                 public override string ToString()
534                 {
535                         return getFullName (false, false);
536                 }
537
538                 bool IsGenericCOMObjectImpl ()
539                 {
540                         return false;
541                 }
542
543                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
544                 static extern object CreateInstanceInternal (Type type);
545
546                 public extern override MethodBase DeclaringMethod {
547                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
548                         get;
549                 }               
550                 
551                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
552                 internal extern string getFullName(bool full_name, bool assembly_qualified);
553
554                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
555                 extern Type[] GetGenericArgumentsInternal (bool runtimeArray);
556
557                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
558                 extern GenericParameterAttributes GetGenericParameterAttributes ();
559
560                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
561                 extern Type[] GetGenericParameterConstraints_impl ();
562
563                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
564                 extern int GetGenericParameterPosition ();
565
566                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
567                 extern RuntimeEventInfo[] GetEvents_internal (string name, BindingFlags bindingAttr, Type reflected_type);
568
569                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
570                 extern RuntimeFieldInfo[] GetFields_internal (string name, BindingFlags bindingAttr, Type reflected_type);
571
572                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
573                 public extern override Type[] GetInterfaces();
574
575                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
576                 extern RuntimeType[] GetNestedTypes_internal (string name, BindingFlags bindingAttr);           
577
578                 public override string AssemblyQualifiedName {
579                         get {
580                                 return getFullName (true, true);
581                         }
582                 }
583
584                 public extern override Type DeclaringType {
585                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
586                         get;
587                 }
588
589                 public override string FullName {
590                         get {
591                                 throw new NotImplementedException ();
592                         }
593                 }
594
595                 public extern override string Name {
596                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
597                         get;
598                 }
599
600                 public extern override string Namespace {
601                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
602                         get;
603                 }
604
605 #if MOBILE
606                 static int get_core_clr_security_level ()
607                 {
608                         return 1;
609                 }
610 #else
611                 //seclevel { transparent = 0, safe-critical = 1, critical = 2}
612                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
613                 public extern int get_core_clr_security_level ();
614
615                 public override bool IsSecurityTransparent {
616                         get { return get_core_clr_security_level () == 0; }
617                 }
618
619                 public override bool IsSecurityCritical {
620                         get { return get_core_clr_security_level () > 0; }
621                 }
622
623                 public override bool IsSecuritySafeCritical {
624                         get { return get_core_clr_security_level () == 1; }
625                 }
626 #endif
627         }
628 }