Raise an exception for user types under FULL_AOT_RUNTIME instead of crashing.
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
1 //
2 // MonoMethod.cs: The class used to represent methods from the mono runtime.
3 //
4 // Authors:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections.Generic;
33 using System.Globalization;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Runtime.Serialization;
37 #if !FULL_AOT_RUNTIME
38 using System.Reflection.Emit;
39 #endif
40 using System.Security;
41 using System.Threading;
42 using System.Text;
43 using System.Diagnostics;
44
45 namespace System.Reflection {
46         
47         internal struct MonoMethodInfo 
48         {
49 #pragma warning disable 649     
50                 private Type parent;
51                 private Type ret;
52                 internal MethodAttributes attrs;
53                 internal MethodImplAttributes iattrs;
54                 private CallingConventions callconv;
55 #pragma warning restore 649             
56
57                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58                 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
59                 
60                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
61                 static extern int get_method_attributes (IntPtr handle);
62                 
63                 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
64                 {
65                         MonoMethodInfo info;
66                         MonoMethodInfo.get_method_info (handle, out info);
67                         return info;
68                 }
69
70                 internal static Type GetDeclaringType (IntPtr handle)
71                 {
72                         return GetMethodInfo (handle).parent;
73                 }
74
75                 internal static Type GetReturnType (IntPtr handle)
76                 {
77                         return GetMethodInfo (handle).ret;
78                 }
79
80                 internal static MethodAttributes GetAttributes (IntPtr handle)
81                 {
82                         return (MethodAttributes)get_method_attributes (handle);
83                 }
84
85                 internal static CallingConventions GetCallingConvention (IntPtr handle)
86                 {
87                         return GetMethodInfo (handle).callconv;
88                 }
89
90                 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
91                 {
92                         return GetMethodInfo (handle).iattrs;
93                 }
94
95                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96                 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
97
98                 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
99                 {
100                         return get_parameter_info (handle, member);
101                 }
102
103                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
104                 static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
105
106                 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
107                 {
108                         return new ParameterInfo (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
109                 }
110         };
111         
112         /*
113          * Note: most of this class needs to be duplicated for the contructor, since
114          * the .NET reflection class hierarchy is so broken.
115          */
116         [Serializable()]
117         [StructLayout (LayoutKind.Sequential)]
118         internal class MonoMethod : MethodInfo, ISerializable
119         {
120 #pragma warning disable 649
121                 internal IntPtr mhandle;
122                 string name;
123                 Type reftype;
124 #pragma warning restore 649
125
126                 internal MonoMethod () {
127                 }
128
129                 internal MonoMethod (RuntimeMethodHandle mhandle) {
130                         this.mhandle = mhandle.Value;
131                 }
132                 
133                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
134                 internal static extern string get_name (MethodBase method);
135
136                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
137                 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
138
139                 public override MethodInfo GetBaseDefinition ()
140                 {
141                         return get_base_method (this, true);
142                 }
143
144                 internal override MethodInfo GetBaseMethod ()
145                 {
146                         return get_base_method (this, false);
147                 }
148
149                 public override ParameterInfo ReturnParameter {
150                         get {
151                                 return MonoMethodInfo.GetReturnParameterInfo (this);
152                         }
153                 }
154
155                 public override Type ReturnType {
156                         get {
157                                 return MonoMethodInfo.GetReturnType (mhandle);
158                         }
159                 }
160                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
161                         get {
162                                 return MonoMethodInfo.GetReturnParameterInfo (this);
163                         }
164                 }
165                 
166                 public override MethodImplAttributes GetMethodImplementationFlags ()
167                 {
168                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
169                 }
170
171                 public override ParameterInfo[] GetParameters ()
172                 {
173                         ParameterInfo[] src = MonoMethodInfo.GetParametersInfo (mhandle, this);
174                         ParameterInfo[] res = new ParameterInfo [src.Length];
175                         src.CopyTo (res, 0);
176                         return res;
177                 }
178                 
179                 internal override int GetParameterCount ()
180                 {
181                         var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
182                         return pi == null ? 0 : pi.Length;
183                 }
184
185                 /*
186                  * InternalInvoke() receives the parameters correctly converted by the 
187                  * binder to match the types of the method signature.
188                  */
189                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
190                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
191
192                 [DebuggerHidden]
193                 [DebuggerStepThrough]
194                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
195                 {
196                         if (binder == null)
197                                 binder = Binder.DefaultBinder;
198
199                         /*Avoid allocating an array every time*/
200                         ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
201                         if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
202                                 throw new ArgumentException ("failed to convert parameters");
203
204 #if !NET_2_1
205                         if (SecurityManager.SecurityEnabled) {
206                                 // sadly Attributes doesn't tell us which kind of security action this is so
207                                 // we must do it the hard way - and it also means that we can skip calling
208                                 // Attribute (which is another an icall)
209                                 SecurityManager.ReflectedLinkDemandInvoke (this);
210                         }
211 #endif
212
213                         if (ContainsGenericParameters)
214                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
215
216                         Exception exc;
217                         object o = null;
218
219                         try {
220                                 // The ex argument is used to distinguish exceptions thrown by the icall
221                                 // from the exceptions thrown by the called method (which need to be
222                                 // wrapped in TargetInvocationException).
223                                 o = InternalInvoke (obj, parameters, out exc);
224                         } catch (ThreadAbortException) {
225                                 throw;
226 #if NET_2_1
227                         } catch (MethodAccessException) {
228                                 throw;
229 #endif
230                         } catch (Exception e) {
231                                 throw new TargetInvocationException (e);
232                         }
233
234                         if (exc != null)
235                                 throw exc;
236                         return o;
237                 }
238
239                 public override RuntimeMethodHandle MethodHandle { 
240                         get {
241                                 return new RuntimeMethodHandle (mhandle);
242                         } 
243                 }
244                 
245                 public override MethodAttributes Attributes { 
246                         get {
247                                 return MonoMethodInfo.GetAttributes (mhandle);
248                         } 
249                 }
250
251                 public override CallingConventions CallingConvention { 
252                         get {
253                                 return MonoMethodInfo.GetCallingConvention (mhandle);
254                         }
255                 }
256                 
257                 public override Type ReflectedType {
258                         get {
259                                 return reftype;
260                         }
261                 }
262                 public override Type DeclaringType {
263                         get {
264                                 return MonoMethodInfo.GetDeclaringType (mhandle);
265                         }
266                 }
267                 public override string Name {
268                         get {
269                                 if (name != null)
270                                         return name;
271                                 return get_name (this);
272                         }
273                 }
274                 
275                 public override bool IsDefined (Type attributeType, bool inherit) {
276                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
277                 }
278
279                 public override object[] GetCustomAttributes( bool inherit) {
280                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
281                 }
282                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
283                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
284                 }
285
286                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
287                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
288
289                 internal object[] GetPseudoCustomAttributes ()
290                 {
291                         int count = 0;
292
293                         /* MS.NET doesn't report MethodImplAttribute */
294
295                         MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
296                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
297                                 count ++;
298                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
299                                 count ++;
300                         
301                         if (count == 0)
302                                 return null;
303                         object[] attrs = new object [count];
304                         count = 0;
305
306                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
307                                 attrs [count ++] = new PreserveSigAttribute ();
308                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
309                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
310                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
311                                         attr.PreserveSig = true;
312                                 attrs [count ++] = attr;
313                         }
314
315                         return attrs;
316                 }
317
318                 static bool ShouldPrintFullName (Type type) {
319                         return type.IsClass && (!type.IsPointer ||
320                                 (!type.GetElementType ().IsPrimitive && !type.GetElementType ().IsNested));
321                 }
322
323                 public override string ToString () {
324                         StringBuilder sb = new StringBuilder ();
325                         Type retType = ReturnType;
326                         if (ShouldPrintFullName (retType))
327                                 sb.Append (retType.ToString ());
328                         else
329                                 sb.Append (retType.Name);
330                         sb.Append (" ");
331                         sb.Append (Name);
332                         if (IsGenericMethod) {
333                                 Type[] gen_params = GetGenericArguments ();
334                                 sb.Append ("[");
335                                 for (int j = 0; j < gen_params.Length; j++) {
336                                         if (j > 0)
337                                                 sb.Append (",");
338                                         sb.Append (gen_params [j].Name);
339                                 }
340                                 sb.Append ("]");
341                         }
342                         sb.Append ("(");
343                         ParameterInfo[] p = GetParameters ();
344                         for (int i = 0; i < p.Length; ++i) {
345                                 if (i > 0)
346                                         sb.Append (", ");
347                                 Type pt = p[i].ParameterType;
348                                 bool byref = pt.IsByRef;
349                                 if (byref)
350                                         pt = pt.GetElementType ();
351                                 if (ShouldPrintFullName (pt))
352                                         sb.Append (pt.ToString ());
353                                 else
354                                         sb.Append (pt.Name);
355                                 if (byref)
356                                         sb.Append (" ByRef");
357                         }
358                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
359                                 if (p.Length > 0)
360                                         sb.Append (", ");
361                                 sb.Append ("...");
362                         }
363                         
364                         sb.Append (")");
365                         return sb.ToString ();
366                 }
367
368         
369                 // ISerializable
370                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
371                 {
372                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
373                                 ? GetGenericArguments () : null;
374                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
375                 }
376
377                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
378                 {
379                         if (methodInstantiation == null)
380                                 throw new ArgumentNullException ("methodInstantiation");
381
382                         if (!IsGenericMethodDefinition)
383                                 throw new InvalidOperationException ("not a generic method definition");
384
385                         /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
386                         if (GetGenericArguments ().Length != methodInstantiation.Length)
387                                 throw new ArgumentException ("Incorrect length");
388
389                         bool hasUserType = false;
390                         foreach (Type type in methodInstantiation) {
391                                 if (type == null)
392                                         throw new ArgumentNullException ();
393                                 if (!(type is MonoType))
394                                         hasUserType = true;
395                         }
396
397                         if (hasUserType)
398 #if FULL_AOT_RUNTIME
399                                 throw new NotSupportedException ("User types are not supported under full aot");
400 #else
401                                 return new MethodOnTypeBuilderInst (this, methodInstantiation);
402 #endif
403
404                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
405                         if (ret == null)
406                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
407                         return ret;
408                 }
409
410                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
411                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
412
413                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
414                 public override extern Type [] GetGenericArguments ();
415
416                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
417                 extern MethodInfo GetGenericMethodDefinition_impl ();
418
419                 public override MethodInfo GetGenericMethodDefinition ()
420                 {
421                         MethodInfo res = GetGenericMethodDefinition_impl ();
422                         if (res == null)
423                                 throw new InvalidOperationException ();
424
425                         return res;
426                 }
427
428                 public override extern bool IsGenericMethodDefinition {
429                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
430                         get;
431                 }
432
433                 public override extern bool IsGenericMethod {
434                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
435                         get;
436                 }
437
438                 public override bool ContainsGenericParameters {
439                         get {
440                                 if (IsGenericMethod) {
441                                         foreach (Type arg in GetGenericArguments ())
442                                                 if (arg.ContainsGenericParameters)
443                                                         return true;
444                                 }
445                                 return DeclaringType.ContainsGenericParameters;
446                         }
447                 }
448
449                 public override MethodBody GetMethodBody () {
450                         return GetMethodBody (mhandle);
451                 }
452
453 #if NET_4_0
454                 public override IList<CustomAttributeData> GetCustomAttributesData () {
455                         return CustomAttributeData.GetCustomAttributes (this);
456                 }
457 #endif
458         }
459         
460         [StructLayout (LayoutKind.Sequential)]
461         internal class MonoCMethod : ConstructorInfo, ISerializable
462         {
463 #pragma warning disable 649             
464                 internal IntPtr mhandle;
465                 string name;
466                 Type reftype;
467 #pragma warning restore 649             
468                 
469                 public override MethodImplAttributes GetMethodImplementationFlags ()
470                 {
471                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
472                 }
473
474                 public override ParameterInfo[] GetParameters ()
475                 {
476                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
477                 }
478
479                 internal override int GetParameterCount ()
480                 {
481                         var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
482                         return pi == null ? 0 : pi.Length;
483                 }
484
485                 /*
486                  * InternalInvoke() receives the parameters corretcly converted by the binder
487                  * to match the types of the method signature.
488                  */
489                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
490                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
491
492                 [DebuggerHidden]
493                 [DebuggerStepThrough]
494                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
495                 {
496                         if (binder == null)
497                                 binder = Binder.DefaultBinder;
498
499                         ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
500
501                         if (!binder.ConvertArgs (parameters, pinfo, culture, (invokeAttr & BindingFlags.ExactBinding) != 0))
502                                 throw new ArgumentException ("failed to convert parameters");
503
504 #if !NET_2_1
505                         if (SecurityManager.SecurityEnabled) {
506                                 // sadly Attributes doesn't tell us which kind of security action this is so
507                                 // we must do it the hard way - and it also means that we can skip calling
508                                 // Attribute (which is another an icall)
509                                 SecurityManager.ReflectedLinkDemandInvoke (this);
510                         }
511 #endif
512
513                         if (obj == null && DeclaringType.ContainsGenericParameters)
514                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
515
516                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
517                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
518                         }
519
520                         Exception exc = null;
521                         object o = null;
522
523                         try {
524                                 o = InternalInvoke (obj, parameters, out exc);
525 #if NET_2_1
526                         } catch (MethodAccessException) {
527                                 throw;
528 #endif
529                         } catch (Exception e) {
530                                 throw new TargetInvocationException (e);
531                         }
532
533                         if (exc != null)
534                                 throw exc;
535                         return (obj == null) ? o : null;
536                 }
537
538                 [DebuggerHidden]
539                 [DebuggerStepThrough]
540                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
541                 {
542                         return Invoke (null, invokeAttr, binder, parameters, culture);
543                 }
544
545                 public override RuntimeMethodHandle MethodHandle { 
546                         get {
547                                 return new RuntimeMethodHandle (mhandle);
548                         } 
549                 }
550                 
551                 public override MethodAttributes Attributes { 
552                         get {
553                                 return MonoMethodInfo.GetAttributes (mhandle);
554                         } 
555                 }
556
557                 public override CallingConventions CallingConvention { 
558                         get {
559                                 return MonoMethodInfo.GetCallingConvention (mhandle);
560                         }
561                 }
562                 
563                 public override Type ReflectedType {
564                         get {
565                                 return reftype;
566                         }
567                 }
568                 public override Type DeclaringType {
569                         get {
570                                 return MonoMethodInfo.GetDeclaringType (mhandle);
571                         }
572                 }
573                 public override string Name {
574                         get {
575                                 if (name != null)
576                                         return name;
577                                 return MonoMethod.get_name (this);
578                         }
579                 }
580
581                 public override bool IsDefined (Type attributeType, bool inherit) {
582                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
583                 }
584
585                 public override object[] GetCustomAttributes( bool inherit) {
586                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
587                 }
588
589                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
590                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
591                 }
592
593                 public override MethodBody GetMethodBody () {
594                         return GetMethodBody (mhandle);
595                 }
596
597                 public override string ToString () {
598                         StringBuilder sb = new StringBuilder ();
599                         sb.Append ("Void ");
600                         sb.Append (Name);
601                         sb.Append ("(");
602                         ParameterInfo[] p = GetParameters ();
603                         for (int i = 0; i < p.Length; ++i) {
604                                 if (i > 0)
605                                         sb.Append (", ");
606                                 sb.Append (p[i].ParameterType.Name);
607                         }
608                         if (CallingConvention == CallingConventions.Any)
609                                 sb.Append (", ...");
610                         sb.Append (")");
611                         return sb.ToString ();
612                 }
613
614                 // ISerializable
615                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
616                 {
617                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
618                 }
619
620 #if NET_4_0
621                 public override IList<CustomAttributeData> GetCustomAttributesData () {
622                         return CustomAttributeData.GetCustomAttributes (this);
623                 }
624 #endif
625         }
626 }