2007-09-14 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodBuilder.cs
index 38e7bb1ef71e4d1997959f2a4bf0e75498428c54..14216acd88428dfdd2165ef1c1e3b645c9b5f529 100644 (file)
@@ -40,13 +40,15 @@ using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Diagnostics.SymbolStore;
 
-namespace System.Reflection.Emit {
+namespace System.Reflection.Emit
+{
 #if NET_2_0
        [ComVisible (true)]
-       [ClassInterfaceAttribute (ClassInterfaceType.None)]
-       [ComDefaultInterfaceAttribute (typeof (_MethodBuilder))]
+       [ComDefaultInterface (typeof (_MethodBuilder))]
 #endif
-       public sealed class MethodBuilder : MethodInfo {
+       [ClassInterface (ClassInterfaceType.None)]
+       public sealed class MethodBuilder : MethodInfo, _MethodBuilder
+       {
                private RuntimeMethodHandle mhandle;
                private Type rtype;
                private Type[] parameters;
@@ -69,7 +71,7 @@ namespace System.Reflection.Emit {
                private bool init_locals = true;
                private IntPtr generic_container;
 #if NET_2_0 || BOOTSTRAP_NET_2_0
-               private GenericTypeParameterBuilder[] generic_params;
+               private GenericTypeParameterBuilder[] generic_params;
 #else
                private Object generic_params; /* so offsets are the same */
 #endif
@@ -79,7 +81,8 @@ namespace System.Reflection.Emit {
                private Type[][] paramModOpt;
                private RefEmitPermissionSet[] permissions;
 
-               internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt) {
+               internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt)
+               {
                        this.name = name;
                        this.attrs = attributes;
                        this.call_conv = callingConvention;
@@ -102,13 +105,13 @@ namespace System.Reflection.Emit {
                        }
                        type = tb;
                        table_idx = get_next_table_index (this, 0x06, true);
-                       //Console.WriteLine ("index for "+name+" set to "+table_idx.ToString());
                }
 
                internal MethodBuilder (TypeBuilder tb, string name, MethodAttributes attributes, 
                                                                CallingConventions callingConvention, Type returnType, Type[] returnModReq, Type[] returnModOpt, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt, 
                        String dllName, String entryName, CallingConvention nativeCConv, CharSet nativeCharset) 
-                       : this (tb, name, attributes, callingConvention, returnType, returnModReq, returnModOpt, parameterTypes, paramModReq, paramModOpt) {
+                       : this (tb, name, attributes, callingConvention, returnType, returnModReq, returnModOpt, parameterTypes, paramModReq, paramModOpt)
+               {
                        pi_dll = dllName;
                        pi_entry = entryName;
                        native_cc = nativeCConv;
@@ -130,20 +133,35 @@ namespace System.Reflection.Emit {
                        }
                }
 
-               public override Type ReturnType {get {return rtype;}}
-               public override Type ReflectedType {get {return type;}}
-               public override Type DeclaringType {get {return type;}}
-               public override string Name {get {return name;}}
-               public override MethodAttributes Attributes {get {return attrs;}}
+               public override Type ReturnType {
+                       get { return rtype; }
+               }
+
+               public override Type ReflectedType {
+                       get { return type; }
+               }
+
+               public override Type DeclaringType {
+                       get { return type; }
+               }
+
+               public override string Name {
+                       get { return name; }
+               }
+
+               public override MethodAttributes Attributes {
+                       get { return attrs; }
+               }
+
                public override ICustomAttributeProvider ReturnTypeCustomAttributes {
-                       get {return null;}
+                       get { return null; }
                }
 
-               public override CallingConventions CallingConvention { 
+               public override CallingConventions CallingConvention {
                        get { return call_conv; }
                }
 
-               [MonoTODO]
+               [MonoTODO("Not implemented")]
                public string Signature {
                        get {
                                throw new NotImplementedException ();
@@ -153,42 +171,48 @@ namespace System.Reflection.Emit {
                /* Used by mcs */
                internal bool BestFitMapping {
                        set {
-                               extra_flags = (uint) ((extra_flags & ~0x30) | (value ? 0x10 : 0x20));
+                               extra_flags = (uint) ((extra_flags & ~0x30) | (uint)(value ? 0x10 : 0x20));
                        }
                }
 
                /* Used by mcs */
                internal bool ThrowOnUnmappableChar {
                        set {
-                               extra_flags = (uint) ((extra_flags & ~0x3000) | (value ? 0x1000 : 0x2000));
+                               extra_flags = (uint) ((extra_flags & ~0x3000) | (uint)(value ? 0x1000 : 0x2000));
                        }
                }
 
                /* Used by mcs */
                internal bool ExactSpelling {
                        set {
-                               extra_flags = (uint) ((extra_flags & ~0x01) | (value ? 0x01 : 0x00));
+                               extra_flags = (uint) ((extra_flags & ~0x01) | (uint)(value ? 0x01 : 0x00));
                        }
                }
 
                /* Used by mcs */
                internal bool SetLastError {
                        set {
-                               extra_flags = (uint) ((extra_flags & ~0x40) | (value ? 0x40 : 0x00));
+                               extra_flags = (uint) ((extra_flags & ~0x40) | (uint)(value ? 0x40 : 0x00));
                        }
                }
 
-               public MethodToken GetToken() {
+               public MethodToken GetToken()
+               {
                        return new MethodToken(0x06000000 | table_idx);
                }
                
-               public override MethodInfo GetBaseDefinition() {
+               public override MethodInfo GetBaseDefinition()
+               {
                        return this;
                }
-               public override MethodImplAttributes GetMethodImplementationFlags() {
+
+               public override MethodImplAttributes GetMethodImplementationFlags()
+               {
                        return iattrs;
                }
-               public override ParameterInfo[] GetParameters() {
+
+               public override ParameterInfo[] GetParameters()
+               {
                        if (!type.is_created)
                                throw NotSupported ();
                        if (parameters == null)
@@ -209,13 +233,15 @@ namespace System.Reflection.Emit {
                        return parameters.Length;
                }
 
-               public Module GetModule () {
+               public Module GetModule ()
+               {
                        return type.Module;
                }
 
-               public void CreateMethodBody( byte[] il, int count) {
+               public void CreateMethodBody (byte[] il, int count)
+               {
                        if ((il != null) && ((count < 0) || (count > il.Length)))
-                               throw new ArgumentException ("Index was out of range.  Must be non-negative and less than the size of the collection.");
+                               throw new ArgumentOutOfRangeException ("Index was out of range.  Must be non-negative and less than the size of the collection.");
 
                        if ((code != null) || type.is_created)
                                throw new InvalidOperationException ("Type definition of the method is complete.");
@@ -228,23 +254,44 @@ namespace System.Reflection.Emit {
                        }
                }
 
-               public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
+               public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+               {
                        throw NotSupported ();
                }
-               public override bool IsDefined (Type attribute_type, bool inherit) {
+
+               public override bool IsDefined (Type attribute_type, bool inherit)
+               {
                        throw NotSupported ();
                }
-               public override object[] GetCustomAttributes( bool inherit) {
-                       throw NotSupported ();
+
+               public override object[] GetCustomAttributes (bool inherit)
+               {
+                       /*
+                        * On MS.NET, this always returns not_supported, but we can't do this
+                        * since there would be no way to obtain custom attributes of 
+                        * dynamically created ctors.
+                        */
+                       if (type.is_created)
+                               return MonoCustomAttrs.GetCustomAttributes (this, inherit);
+                       else
+                               throw NotSupported ();
                }
-               public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
-                       throw NotSupported ();
+
+               public override object[] GetCustomAttributes (Type attributeType, bool inherit)
+               {
+                       if (type.is_created)
+                               return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
+                       else
+                               throw NotSupported ();
                }
-               public ILGenerator GetILGenerator () {
+
+               public ILGenerator GetILGenerator ()
+               {
                        return GetILGenerator (64);
                }
 
-               public ILGenerator GetILGenerator (int size) {
+               public ILGenerator GetILGenerator (int size)
+               {
                        if (((iattrs & MethodImplAttributes.CodeTypeMask) != 
                                 MethodImplAttributes.IL) ||
                                ((iattrs & MethodImplAttributes.ManagedMask) != 
@@ -273,10 +320,18 @@ namespace System.Reflection.Emit {
                        return pb;
                }
 
-               internal void fixup () {
+               internal void fixup ()
+               {
                        if (((attrs & (MethodAttributes.Abstract | MethodAttributes.PinvokeImpl)) == 0) && ((iattrs & (MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall)) == 0)) {
+#if NET_2_0
+                               // do not allow zero length method body on MS.NET 2.0 (and higher)
+                               if (((ilgen == null) || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0)) && (code == null || code.Length == 0))
+#else
                                if (((ilgen == null) || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0)) && (code == null))
-                                       throw new InvalidOperationException ("Method '" + Name + "' does not have a method body.");
+#endif
+                                       throw new InvalidOperationException (
+                                                                            String.Format ("Method '{0}.{1}' does not have a method body.",
+                                                                                           DeclaringType.Name, Name));
                        }
                        if (ilgen != null)
                                ilgen.label_fixup ();
@@ -293,65 +348,83 @@ namespace System.Reflection.Emit {
                        }
                }
 
-               public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
+               public void SetCustomAttribute (CustomAttributeBuilder customBuilder)
+               {
                        if (customBuilder == null)
                                throw new ArgumentNullException ("customBuilder");
-                       string attrname = customBuilder.Ctor.ReflectedType.FullName;
-                       if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute") {
-                               byte[] data = customBuilder.Data;
-                               int impla; // the (stupid) ctor takes a short or an int ... 
-                               impla = (int)data [2];
-                               impla |= ((int)data [3]) << 8;
-                               SetImplementationFlags ((MethodImplAttributes)impla);
-                               return;
-                       }
-                       if (attrname == "System.Runtime.InteropServices.DllImportAttribute") {
-                               CustomAttributeBuilder.CustomAttributeInfo attr = CustomAttributeBuilder.decode_cattr (customBuilder);
-                               bool preserveSig = true;
-
-                               /*
-                                * It would be easier to construct a DllImportAttribute from
-                                * the custom attribute builder, but the DllImportAttribute 
-                                * does not contain all the information required here, ie.
-                                * - some parameters, like BestFitMapping has three values
-                                *   ("on", "off", "missing"), but DllImportAttribute only
-                                *   contains two (on/off).
-                                * - PreserveSig is true by default, while it is false by
-                                *   default in DllImportAttribute.
-                                */
-
-                               pi_dll = (string)attr.ctorArgs [0];
-                               native_cc = System.Runtime.InteropServices.CallingConvention.Winapi;
-
-                               for (int i = 0; i < attr.namedParamNames.Length; ++i) {
-                                       string name = attr.namedParamNames [i];
-                                       object value = attr.namedParamValues [i];
-
-                                       if (name == "CallingConvention")
-                                               native_cc = (CallingConvention)value;
-                                       else if (name == "CharSet")
-                                               charset = (CharSet)value;
-                                       else if (name == "EntryPoint")
-                                               pi_entry = (string)value;
-                                       else if (name == "ExactSpelling")
-                                               ExactSpelling = (bool)value;
-                                       else if (name == "SetLastError")
-                                               SetLastError = (bool)value;
-                                       else if (name == "PreserveSig")
-                                               preserveSig = (bool)value;
+
+                       switch (customBuilder.Ctor.ReflectedType.FullName) {
+                               case "System.Runtime.CompilerServices.MethodImplAttribute":
+                                       byte[] data = customBuilder.Data;
+                                       int impla; // the (stupid) ctor takes a short or an int ... 
+                                       impla = (int)data [2];
+                                       impla |= ((int)data [3]) << 8;
+                                       iattrs |= (MethodImplAttributes)impla;
+                                       return;
+
+                               case "System.Runtime.InteropServices.DllImportAttribute":
+                                       CustomAttributeBuilder.CustomAttributeInfo attr = CustomAttributeBuilder.decode_cattr (customBuilder);
+                                       bool preserveSig = true;
+
+                                       /*
+                                        * It would be easier to construct a DllImportAttribute from
+                                        * the custom attribute builder, but the DllImportAttribute 
+                                        * does not contain all the information required here, ie.
+                                        * - some parameters, like BestFitMapping has three values
+                                        *   ("on", "off", "missing"), but DllImportAttribute only
+                                        *   contains two (on/off).
+                                        * - PreserveSig is true by default, while it is false by
+                                        *   default in DllImportAttribute.
+                                        */
+
+                                       pi_dll = (string)attr.ctorArgs[0];
+                                       if (pi_dll == null || pi_dll.Length == 0)
+                                               throw new ArgumentException ("DllName cannot be empty");
+
+                                       native_cc = System.Runtime.InteropServices.CallingConvention.Winapi;
+
+                                       for (int i = 0; i < attr.namedParamNames.Length; ++i) {
+                                               string name = attr.namedParamNames [i];
+                                               object value = attr.namedParamValues [i];
+
+                                               if (name == "CallingConvention")
+                                                       native_cc = (CallingConvention)value;
+                                               else if (name == "CharSet")
+                                                       charset = (CharSet)value;
+                                               else if (name == "EntryPoint")
+                                                       pi_entry = (string)value;
+                                               else if (name == "ExactSpelling")
+                                                       ExactSpelling = (bool)value;
+                                               else if (name == "SetLastError")
+                                                       SetLastError = (bool)value;
+                                               else if (name == "PreserveSig")
+                                                       preserveSig = (bool)value;
 #if NET_1_1
                                        else if (name == "BestFitMapping")
                                                BestFitMapping = (bool)value;
                                        else if (name == "ThrowOnUnmappableChar")
                                                ThrowOnUnmappableChar = (bool)value;
 #endif
-                               }
+                                       }
 
-                               attrs |= MethodAttributes.PinvokeImpl;
-                               if (preserveSig)
+                                       attrs |= MethodAttributes.PinvokeImpl;
+                                       if (preserveSig)
+                                               iattrs |= MethodImplAttributes.PreserveSig;
+                                       return;
+
+                               case "System.Runtime.InteropServices.PreserveSigAttribute":
                                        iattrs |= MethodImplAttributes.PreserveSig;
-                               return;
+                                       return;
+#if NET_2_0
+                               case "System.Runtime.CompilerServices.SpecialNameAttribute":
+                                       attrs |= MethodAttributes.SpecialName;
+                                       return;
+#endif
+                               case "System.Security.SuppressUnmanagedCodeSecurityAttribute":
+                                       attrs |= MethodAttributes.HasSecurity;
+                                       break;
                        }
+
                        if (cattrs != null) {
                                CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
                                cattrs.CopyTo (new_array, 0);
@@ -366,25 +439,29 @@ namespace System.Reflection.Emit {
 #if NET_2_0
                [ComVisible (true)]
 #endif
-               public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
+               public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute)
+               {
                        if (con == null)
                                throw new ArgumentNullException ("con");
                        if (binaryAttribute == null)
                                throw new ArgumentNullException ("binaryAttribute");
                        SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
                }
-               public void SetImplementationFlags( MethodImplAttributes attributes) {
+
+               public void SetImplementationFlags (MethodImplAttributes attributes)
+               {
                        RejectIfCreated ();
                        iattrs = attributes;
                }
 
-               public void AddDeclarativeSecurity( SecurityAction action, PermissionSet pset) {
+               public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset)
+               {
                        if (pset == null)
                                throw new ArgumentNullException ("pset");
                        if ((action == SecurityAction.RequestMinimum) ||
                                (action == SecurityAction.RequestOptional) ||
                                (action == SecurityAction.RequestRefuse))
-                               throw new ArgumentException ("Request* values are not permitted", "action");
+                               throw new ArgumentOutOfRangeException ("Request* values are not permitted", "action");
 
                        RejectIfCreated ();
 
@@ -437,39 +514,51 @@ namespace System.Reflection.Emit {
                        return name.GetHashCode ();
                }
 
-               internal override int get_next_table_index (object obj, int table, bool inc) {
+               internal override int get_next_table_index (object obj, int table, bool inc)
+               {
                        return type.get_next_table_index (obj, table, inc);
                }
 
-               internal void set_override (MethodInfo mdecl) {
+               internal void set_override (MethodInfo mdecl)
+               {
                        override_method = mdecl;
                }
 
-               private void RejectIfCreated () {
+               private void RejectIfCreated ()
+               {
                        if (type.is_created)
                                throw new InvalidOperationException ("Type definition of the method is complete.");
                }
 
-               private Exception NotSupported () {
+               private Exception NotSupported ()
+               {
                        return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
                }
 
 #if NET_2_0 || BOOTSTRAP_NET_2_0
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               public override extern MethodInfo BindGenericParameters (Type [] types);
+               public override extern MethodInfo MakeGenericMethod (params Type [] types);
 
-               public override bool Mono_IsInflatedMethod {
+               public override bool IsGenericMethodDefinition {
                        get {
-                               return false;
+                               return generic_params != null;
                        }
                }
 
-               public override bool HasGenericParameters {
+               public override bool IsGenericMethod {
                        get {
                                return generic_params != null;
                        }
                }
 
+               public override MethodInfo GetGenericMethodDefinition ()
+               {
+                       if (!IsGenericMethodDefinition)
+                               throw new InvalidOperationException ();
+
+                       return this;
+               }
+
                public override Type[] GetGenericArguments ()
                {
                        if (generic_params == null)
@@ -484,6 +573,9 @@ namespace System.Reflection.Emit {
 
                public GenericTypeParameterBuilder[] DefineGenericParameters (params string[] names)
                {
+                       if (names == null)
+                               throw new ArgumentNullException ("names");
+
                        generic_params = new GenericTypeParameterBuilder [names.Length];
                        for (int i = 0; i < names.Length; i++)
                                generic_params [i] = new GenericTypeParameterBuilder (
@@ -499,13 +591,65 @@ namespace System.Reflection.Emit {
                        this.attrs = attributes;
                        this.call_conv = callingConvention;
                        if ((attributes & MethodAttributes.Static) == 0)
-                               this.call_conv |= CallingConventions.HasThis;
+                               this.call_conv |= CallingConventions.HasThis;
 
                        this.rtype = return_type;
                        this.parameters = new Type [parameter_types.Length];
                        System.Array.Copy (parameter_types, this.parameters, parameter_types.Length);
                }
+
+               public void SetReturnType (Type returnType)
+               {
+                       rtype = returnType;
+               }
+
+               public void SetParameters (params Type[] parameterTypes)
+               {
+                       if (parameterTypes != null) {
+                               for (int i = 0; i < parameterTypes.Length; ++i)
+                                       if (parameterTypes [i] == null)
+                                               throw new ArgumentException ("Elements of the parameterTypes array cannot be null", "parameterTypes");
+
+                               this.parameters = new Type [parameterTypes.Length];
+                               System.Array.Copy (parameterTypes, this.parameters, parameterTypes.Length);
+                       }
+               }
+
+               public void SetSignature (Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       SetReturnType (returnType);
+                       SetParameters (parameterTypes);
+                       this.returnModReq = returnTypeRequiredCustomModifiers;
+                       this.returnModOpt = returnTypeOptionalCustomModifiers;
+                       this.paramModReq = parameterTypeRequiredCustomModifiers;
+                       this.paramModOpt = parameterTypeOptionalCustomModifiers;
+               }
+
+               public override Module Module {
+                       get {
+                               return base.Module;
+                       }
+               }
 #endif
+
+               void _MethodBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _MethodBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _MethodBuilder.GetTypeInfoCount (out uint pcTInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _MethodBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+               {
+                       throw new NotImplementedException ();
+               }
        }
 }
-