X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdelegate.cs;h=2729fcfe2c9c7ea99bec7a2e173904f4df71bfc0;hb=81dfccbd14f683f1fe46f570e76c1e99a14c5a81;hp=0cc8b404aed9838154788499f3c0b036b0b63d90;hpb=a8b8e5b2530e8a0549b58d787da3e8aa63758ba7;p=mono.git diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 0cc8b404aed..2729fcfe2c9 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -9,187 +9,105 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2001 Ximian, Inc (http://www.ximian.com) -// Copyright 2003-2008 Novell, Inc (http://www.ximian.com) +// Copyright 2003-2009 Novell, Inc (http://www.novell.com) // using System; -using System.Collections; using System.Reflection; using System.Reflection.Emit; -using System.Text; +using System.Collections.Generic; namespace Mono.CSharp { - /// - /// Holds Delegates - /// - public class Delegate : DeclSpace, IMemberContainer + // + // Delegate container implementation + // + public class Delegate : TypeContainer { FullNamedExpression ReturnType; - public ParametersCompiled Parameters; + public readonly ParametersCompiled Parameters; - public ConstructorBuilder ConstructorBuilder; - public MethodBuilder InvokeBuilder; - public MethodBuilder BeginInvokeBuilder; - public MethodBuilder EndInvokeBuilder; - - Type ret_type; + Constructor Constructor; + Method InvokeBuilder; + Method BeginInvokeBuilder; + Method EndInvokeBuilder; + + static readonly string[] attribute_targets = new string [] { "type", "return" }; - static string[] attribute_targets = new string [] { "type", "return" }; + public static readonly string InvokeMethodName = "Invoke"; Expression instance_expr; - MethodBase delegate_method; ReturnParameter return_attributes; - MemberCache member_cache; + const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL; - const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | - MethodAttributes.Virtual | MethodAttributes.NewSlot; - - const int AllowedModifiers = + const Modifiers AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | - Modifiers.UNSAFE | + Modifiers.UNSAFE | Modifiers.PRIVATE; public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type, - int mod_flags, MemberName name, ParametersCompiled param_list, + Modifiers mod_flags, MemberName name, ParametersCompiled param_list, Attributes attrs) - : base (ns, parent, name, attrs) + : base (ns, parent, name, attrs, MemberKind.Delegate) { this.ReturnType = type; - ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, + ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, IsTopLevel ? Modifiers.INTERNAL : - Modifiers.PRIVATE, name.Location); + Modifiers.PRIVATE, name.Location, Report); Parameters = param_list; + spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED); } - public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb) + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) { if (a.Target == AttributeTargets.ReturnValue) { if (return_attributes == null) - return_attributes = new ReturnParameter (InvokeBuilder, Location); + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); - return_attributes.ApplyAttributeBuilder (a, cb); + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); return; } - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, ctor, cdata, pa); } - public override TypeBuilder DefineType () - { - if (TypeBuilder != null) - return TypeBuilder; - - if (IsTopLevel) { - if (TypeManager.NamespaceClash (Name, Location)) - return null; - - ModuleBuilder builder = CodeGen.Module.Builder; - - TypeBuilder = builder.DefineType ( - Name, TypeAttr, TypeManager.multicast_delegate_type); - } else { - TypeBuilder builder = Parent.TypeBuilder; - - string name = Name.Substring (1 + Name.LastIndexOf ('.')); - TypeBuilder = builder.DefineNestedType ( - name, TypeAttr, TypeManager.multicast_delegate_type); - } - - TypeManager.AddUserType (this); - -#if GMCS_SOURCE - if (IsGeneric) { - string[] param_names = new string [TypeParameters.Length]; - for (int i = 0; i < TypeParameters.Length; i++) - param_names [i] = TypeParameters [i].Name; - - GenericTypeParameterBuilder[] gen_params; - gen_params = TypeBuilder.DefineGenericParameters (param_names); - - int offset = CountTypeParameters - CurrentTypeParameters.Length; - for (int i = offset; i < gen_params.Length; i++) - CurrentTypeParameters [i - offset].Define (gen_params [i]); - - foreach (TypeParameter type_param in CurrentTypeParameters) { - if (!type_param.Resolve (this)) - return null; - } - - Expression current = new SimpleName ( - MemberName.Basename, TypeParameters, Location); - current = current.ResolveAsTypeTerminal (this, false); - if (current == null) - return null; - - CurrentType = current.Type; + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Delegate; } -#endif - - return TypeBuilder; } - public override bool Define () + protected override bool DoDefineMembers () { -#if GMCS_SOURCE - if (IsGeneric) { - foreach (TypeParameter type_param in TypeParameters) { - if (!type_param.Resolve (this)) - return false; - } - - foreach (TypeParameter type_param in TypeParameters) { - if (!type_param.DefineType (this)) - return false; + var ctor_parameters = ParametersCompiled.CreateFullyResolved ( + new [] { + new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (TypeManager.intptr_type, Location), "method", Parameter.Modifier.NONE, null, Location) + }, + new [] { + TypeManager.object_type, + TypeManager.intptr_type } - } -#endif - member_cache = new MemberCache (TypeManager.multicast_delegate_type, this); - - // FIXME: POSSIBLY make this static, as it is always constant - // - Type [] const_arg_types = new Type [2]; - const_arg_types [0] = TypeManager.object_type; - const_arg_types [1] = TypeManager.intptr_type; - - const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | - MethodAttributes.HideBySig | MethodAttributes.Public; - - ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr, - CallingConventions.Standard, - const_arg_types); + ); - ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object"); - ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method"); - // - // HACK because System.Reflection.Emit is lame - // - IParameterData [] fixed_pars = new IParameterData [] { - new ParameterData ("object", Parameter.Modifier.NONE), - new ParameterData ("method", Parameter.Modifier.NONE) - }; - - AParametersCollection const_parameters = new ParametersImported ( - fixed_pars, - new Type[] { TypeManager.object_type, TypeManager.intptr_type }); - - TypeManager.RegisterMethod (ConstructorBuilder, const_parameters); - member_cache.AddMember (ConstructorBuilder, this); - - ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + Constructor = new Constructor (this, System.Reflection.ConstructorInfo.ConstructorName, + Modifiers.PUBLIC, null, ctor_parameters, null, Location); + Constructor.Define (); // // Here the various methods like Invoke, BeginInvoke etc are defined // // First, call the `out of band' special method for // defining recursively any types we need: - - if (!Parameters.Resolve (this)) + // + var p = Parameters; + + if (!p.Resolve (this)) return false; // @@ -197,66 +115,51 @@ namespace Mono.CSharp { // // Check accessibility - foreach (Type partype in Parameters.Types){ + foreach (var partype in p.Types) { if (!IsAccessibleAs (partype)) { Report.SymbolRelatedToPreviousError (partype); Report.Error (59, Location, - "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", - TypeManager.CSharpName (partype), - GetSignatureForError ()); - return false; + "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", + TypeManager.CSharpName (partype), GetSignatureForError ()); } } - + ReturnType = ReturnType.ResolveAsTypeTerminal (this, false); if (ReturnType == null) return false; - ret_type = ReturnType.Type; - + var ret_type = ReturnType.Type; + + // + // We don't have to check any others because they are all + // guaranteed to be accessible - they are standard types. + // if (!IsAccessibleAs (ret_type)) { Report.SymbolRelatedToPreviousError (ret_type); Report.Error (58, Location, - "Inconsistent accessibility: return type `" + - TypeManager.CSharpName (ret_type) + "' is less " + - "accessible than delegate `" + GetSignatureForError () + "'"); + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (ret_type) + "' is less " + + "accessible than delegate `" + GetSignatureForError () + "'"); return false; } CheckProtectedModifier (); if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) { - Method.Error1599 (Location, ret_type); + Method.Error1599 (Location, ret_type, Report); return false; } -#if GMCS_SOURCE - if (ret_type.IsGenericParameter && (ret_type.GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) { - Report.Error (-33, Location, "Contravariant type parameters can only be used in input positions"); - return false; - } -#endif + TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); + + InvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName (InvokeMethodName), p, null); + InvokeBuilder.Define (); // - // We don't have to check any others because they are all - // guaranteed to be accessible - they are standard types. + // Don't emit async method for compiler generated delegates (e.g. dynamic site containers) // - - CallingConventions cc = Parameters.CallingConvention; - - InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", - mattr, - cc, - ret_type, - Parameters.GetEmitTypes ()); - - InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); - - TypeManager.RegisterMethod (InvokeBuilder, Parameters); - member_cache.AddMember (InvokeBuilder, this); - - if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null) { - DefineAsyncMethods (cc); + if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) { + DefineAsyncMethods (Parameters.CallingConvention); } return true; @@ -267,23 +170,30 @@ namespace Mono.CSharp { // // BeginInvoke // - ParametersCompiled async_parameters = ParametersCompiled.MergeGenerated (Parameters, false, - new Parameter [] { - new Parameter (null, "callback", Parameter.Modifier.NONE, null, Location), - new Parameter (null, "object", Parameter.Modifier.NONE, null, Location) + Parameter[] compiled = new Parameter[Parameters.Count]; + for (int i = 0; i < compiled.Length; ++i) + compiled[i] = new Parameter (new TypeExpression (Parameters.Types[i], Location), + Parameters.FixedParameters[i].Name, + Parameters.FixedParameters[i].ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + null, Location); + + ParametersCompiled async_parameters = new ParametersCompiled (Compiler, compiled); + + async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false, + new Parameter[] { + new Parameter (new TypeExpression (TypeManager.asynccallback_type, Location), "callback", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (TypeManager.object_type, Location), "object", Parameter.Modifier.NONE, null, Location) }, - new Type [] { + new [] { TypeManager.asynccallback_type, TypeManager.object_type } ); - BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke", - mattr, cc, TypeManager.iasyncresult_type, async_parameters.GetEmitTypes ()); - - BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); - TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters); - member_cache.AddMember (BeginInvokeBuilder, this); + BeginInvokeBuilder = new Method (this, null, + new TypeExpression (TypeManager.iasyncresult_type, Location), MethodModifiers, + new MemberName ("BeginInvoke"), async_parameters, null); + BeginInvokeBuilder.Define (); // // EndInvoke is a bit more interesting, all the parameters labeled as @@ -302,8 +212,8 @@ namespace Mono.CSharp { } if (out_params > 0) { - Type [] end_param_types = new Type [out_params]; - Parameter[] end_params = new Parameter [out_params]; + var end_param_types = new TypeSpec [out_params]; + Parameter[] end_params = new Parameter[out_params]; int param = 0; for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { @@ -311,8 +221,8 @@ namespace Mono.CSharp { if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) continue; - end_param_types [param] = Parameters.Types [i]; - end_params [param] = p; + end_param_types[param] = Parameters.Types[i]; + end_params[param] = p; ++param; } end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types); @@ -320,27 +230,54 @@ namespace Mono.CSharp { end_parameters = ParametersCompiled.EmptyReadOnlyParameters; } - end_parameters = ParametersCompiled.MergeGenerated (end_parameters, false, - new Parameter (null, "result", Parameter.Modifier.NONE, null, Location), TypeManager.iasyncresult_type); + end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false, + new Parameter ( + new TypeExpression (TypeManager.iasyncresult_type, Location), + "result", Parameter.Modifier.NONE, null, Location), + TypeManager.iasyncresult_type); // // Create method, define parameters, register parameters with type system // - EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.GetEmitTypes ()); - EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null); + EndInvokeBuilder.Define (); + } - end_parameters.ApplyAttributes (EndInvokeBuilder); - TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters); - member_cache.AddMember (EndInvokeBuilder, this); + public override void DefineConstants () + { + if (!Parameters.IsEmpty && Parameters[Parameters.Count - 1].HasDefaultValue) { + var rc = new ResolveContext (this); + Parameters.ResolveDefaultValues (rc); + } } - public override void Emit () + public override void EmitType () { - Parameters.ApplyAttributes (InvokeBuilder); + if (ReturnType.Type == InternalType.Dynamic) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder); + } else { + var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType.Type); + if (trans_flags != null) { + var pa = PredefinedAttributes.Get.DynamicTransform; + if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + return_attributes.Builder.SetCustomAttribute ( + new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags })); + } + } + } + + Parameters.ApplyAttributes (InvokeBuilder.MethodBuilder); + + Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); if (BeginInvokeBuilder != null) { - ParametersCompiled p = (ParametersCompiled) TypeManager.GetParameterData (BeginInvokeBuilder); - p.ApplyAttributes (BeginInvokeBuilder); + BeginInvokeBuilder.ParameterInfo.ApplyAttributes (BeginInvokeBuilder.MethodBuilder); + + BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); } if (OptAttributes != null) { @@ -350,9 +287,16 @@ namespace Mono.CSharp { base.Emit (); } + protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class) + { + base_type = TypeManager.multicast_delegate_type; + base_class = null; + return null; + } + protected override TypeAttributes TypeAttr { get { - return Modifiers.TypeAttr (ModFlags, IsTopLevel) | + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr; } @@ -371,9 +315,9 @@ namespace Mono.CSharp { return false; } - Parameters.VerifyClsCompliance (); + Parameters.VerifyClsCompliance (this); - if (!AttributeTester.IsClsCompliant (ReturnType.Type)) { + if (!ReturnType.Type.IsCLSCompliant ()) { Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ()); } @@ -381,97 +325,34 @@ namespace Mono.CSharp { } - public static ConstructorInfo GetConstructor (Type container_type, Type delegate_type) + public static MethodSpec GetConstructor (CompilerContext ctx, TypeSpec container_type, TypeSpec delType) { - Type dt = delegate_type; -#if GMCS_SOURCE - Type[] g_args = null; - if (delegate_type.IsGenericType) { - g_args = delegate_type.GetGenericArguments (); - delegate_type = delegate_type.GetGenericTypeDefinition (); - } -#endif - - Delegate d = TypeManager.LookupDelegate (delegate_type); - if (d != null) { -#if GMCS_SOURCE - if (g_args != null) - return TypeBuilder.GetConstructor (dt, d.ConstructorBuilder); -#endif - return d.ConstructorBuilder; - } - - Expression ml = Expression.MemberLookup (container_type, - null, dt, ConstructorInfo.ConstructorName, MemberTypes.Constructor, - BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location.Null); - - MethodGroupExpr mg = ml as MethodGroupExpr; - if (mg == null) { - Report.Error (-100, Location.Null, "Internal error: could not find delegate constructor!"); - // FIXME: null will cause a crash later - return null; - } - - return (ConstructorInfo) mg.Methods[0]; + var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly); + return (MethodSpec) ctor; } // - // Returns the MethodBase for "Invoke" from a delegate type, this is used - // to extract the signature of a delegate. + // Returns the "Invoke" from a delegate type // - public static MethodInfo GetInvokeMethod (Type container_type, Type delegate_type) + public static MethodSpec GetInvokeMethod (CompilerContext ctx, TypeSpec delType) { - Type dt = delegate_type; -#if GMCS_SOURCE - Type[] g_args = null; - if (delegate_type.IsGenericType) { - g_args = delegate_type.GetGenericArguments (); - delegate_type = delegate_type.GetGenericTypeDefinition (); - } -#endif - Delegate d = TypeManager.LookupDelegate (delegate_type); - MethodInfo invoke; - if (d != null) { -#if GMCS_SOURCE - if (g_args != null) { - invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder); -#if MS_COMPATIBLE - ParametersCompiled p = (ParametersCompiled) d.Parameters.InflateTypes (g_args, g_args); - TypeManager.RegisterMethod (invoke, p); -#endif - return invoke; - } -#endif - return d.InvokeBuilder; - } - - Expression ml = Expression.MemberLookup (container_type, null, dt, - "Invoke", Location.Null); - - MethodGroupExpr mg = ml as MethodGroupExpr; - if (mg == null) { - Report.Error (-100, Location.Null, "Internal error: could not find Invoke method!"); - // FIXME: null will cause a crash later - return null; - } + var invoke = MemberCache.FindMember (delType, + MemberFilter.Method (InvokeMethodName, 0, null, null), + BindingRestriction.DeclaredOnly); - invoke = (MethodInfo) mg.Methods[0]; -#if MS_COMPATIBLE - if (g_args != null) { - AParametersCollection p = TypeManager.GetParameterData (invoke); - p = p.InflateTypes (g_args, g_args); - TypeManager.RegisterMethod (invoke, p); - return invoke; - } -#endif + return (MethodSpec) invoke; + } - return invoke; + public static AParametersCollection GetParameters (CompilerContext ctx, TypeSpec delType) + { + var invoke_mb = GetInvokeMethod (ctx, delType); + return invoke_mb.Parameters; } // // 15.2 Delegate compatibility // - public static bool IsTypeCovariant (Expression a, Type b) + public static bool IsTypeCovariant (Expression a, TypeSpec b) { // // For each value parameter (a parameter with no ref or out modifier), an @@ -486,120 +367,12 @@ namespace Mono.CSharp { return Convert.ImplicitReferenceConversionExists (a, b); } - - /// - /// Verifies whether the method in question is compatible with the delegate - /// Returns the method itself if okay and null if not. - /// - public static MethodBase VerifyMethod (Type container_type, Type delegate_type, - MethodGroupExpr old_mg, MethodBase mb) - { - bool is_method_definition = TypeManager.IsGenericMethodDefinition (mb); - - MethodInfo invoke_mb = GetInvokeMethod (container_type, delegate_type); - if (invoke_mb == null) - return null; - - if (is_method_definition) - invoke_mb = (MethodInfo) TypeManager.DropGenericMethodArguments (invoke_mb); - - AParametersCollection invoke_pd = TypeManager.GetParameterData (invoke_mb); - -#if GMCS_SOURCE - if (!is_method_definition && old_mg.type_arguments == null && - !TypeManager.InferTypeArguments (invoke_pd, ref mb)) - return null; -#endif - AParametersCollection pd = TypeManager.GetParameterData (mb); - - if (invoke_pd.Count != pd.Count) - return null; - - for (int i = pd.Count; i > 0; ) { - i--; - - Type invoke_pd_type = invoke_pd.Types [i]; - Type pd_type = pd.Types [i]; - Parameter.Modifier invoke_pd_type_mod = invoke_pd.FixedParameters [i].ModFlags; - Parameter.Modifier pd_type_mod = pd.FixedParameters [i].ModFlags; - - invoke_pd_type_mod &= ~Parameter.Modifier.PARAMS; - pd_type_mod &= ~Parameter.Modifier.PARAMS; - - if (invoke_pd_type_mod != pd_type_mod) - return null; - - if (TypeManager.IsEqual (invoke_pd_type, pd_type)) - continue; - - if (IsTypeCovariant (new EmptyExpression (invoke_pd_type), pd_type)) - continue; - - return null; - } - - Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType; - Type mb_retval = ((MethodInfo) mb).ReturnType; - if (TypeManager.TypeToCoreType (invoke_mb_retval) == TypeManager.TypeToCoreType (mb_retval)) - return mb; - - //if (!IsTypeCovariant (mb_retval, invoke_mb_retval)) - // return null; - - if (RootContext.Version == LanguageVersion.ISO_1) - return null; - return mb; - } - - // - // Verifies whether the invocation arguments are compatible with the - // delegate's target method - // - public static bool VerifyApplicability (EmitContext ec, Type delegate_type, - ArrayList args, Location loc) - { - int arg_count; - - if (args == null) - arg_count = 0; - else - arg_count = args.Count; - - MethodBase mb = GetInvokeMethod (ec.ContainerType, delegate_type); - MethodGroupExpr me = new MethodGroupExpr (new MemberInfo [] { mb }, delegate_type, loc); - - AParametersCollection pd = TypeManager.GetParameterData (mb); - - int pd_count = pd.Count; - - bool params_method = pd.HasParams; - bool is_params_applicable = false; - bool is_applicable = me.IsApplicable (ec, args, arg_count, ref mb, ref is_params_applicable) == 0; - - if (!is_applicable && !params_method && arg_count != pd_count) { - Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", - TypeManager.CSharpName (delegate_type), arg_count.ToString ()); - return false; - } - - return me.VerifyArgumentsCompat ( - ec, ref args, arg_count, mb, - is_params_applicable || (!is_applicable && params_method), - false, loc); - } - - public static string FullDelegateDesc (MethodBase invoke_method) + public static string FullDelegateDesc (MethodSpec invoke_method) { return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", ""); } - public override MemberCache MemberCache { - get { - return member_cache; - } - } - public Expression InstanceExpression { get { return instance_expr; @@ -608,64 +381,6 @@ namespace Mono.CSharp { instance_expr = value; } } - - public MethodBase TargetMethod { - get { - return delegate_method; - } - set { - delegate_method = value; - } - } - - public Type TargetReturnType { - get { - return ret_type; - } - } - - public override AttributeTargets AttributeTargets { - get { - return AttributeTargets.Delegate; - } - } - - // - // Represents header string for documentation comment. - // - public override string DocCommentHeader { - get { return "T:"; } - } - - #region IMemberContainer Members - - string IMemberContainer.Name - { - get { throw new NotImplementedException (); } - } - - Type IMemberContainer.Type - { - get { throw new NotImplementedException (); } - } - - MemberCache IMemberContainer.BaseCache - { - get { throw new NotImplementedException (); } - } - - bool IMemberContainer.IsInterface { - get { - return false; - } - } - - MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf) - { - throw new NotImplementedException (); - } - - #endregion } // @@ -673,48 +388,40 @@ namespace Mono.CSharp { // public abstract class DelegateCreation : Expression, MethodGroupExpr.IErrorHandler { - protected ConstructorInfo constructor_method; - protected MethodInfo delegate_method; - // We keep this to handle IsBase only + protected MethodSpec constructor_method; protected MethodGroupExpr method_group; - protected Expression delegate_instance_expression; - public static ArrayList CreateDelegateMethodArguments (MethodInfo invoke_method, Location loc) + public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc) { - AParametersCollection pd = TypeManager.GetParameterData (invoke_method); - ArrayList delegate_arguments = new ArrayList (pd.Count); + Arguments delegate_arguments = new Arguments (pd.Count); for (int i = 0; i < pd.Count; ++i) { Argument.AType atype_modifier; - Type atype = pd.Types [i]; switch (pd.FixedParameters [i].ModFlags) { case Parameter.Modifier.REF: atype_modifier = Argument.AType.Ref; - //atype = atype.GetElementType (); break; case Parameter.Modifier.OUT: atype_modifier = Argument.AType.Out; - //atype = atype.GetElementType (); break; - case Parameter.Modifier.ARGLIST: - // __arglist is not valid - throw new InternalErrorException ("__arglist modifier"); default: - atype_modifier = Argument.AType.Expression; + atype_modifier = 0; break; } - delegate_arguments.Add (new Argument (new TypeExpression (atype, loc), atype_modifier)); + + delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier)); } + return delegate_arguments; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc); - ArrayList args = new ArrayList (3); + Arguments args = new Arguments (3); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); args.Add (new Argument (new NullLiteral (loc))); - args.Add (new Argument (new TypeOfMethodInfo (delegate_method, loc))); + args.Add (new Argument (method_group.CreateExpressionTree (ec))); Expression e = new Invocation (ma, args).Resolve (ec); if (e == null) return null; @@ -726,160 +433,135 @@ namespace Mono.CSharp { return e.CreateExpressionTree (ec); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - constructor_method = Delegate.GetConstructor (ec.ContainerType, type); + constructor_method = Delegate.GetConstructor (ec.Compiler, ec.CurrentType, type); - MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type); + var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, type); method_group.DelegateType = type; method_group.CustomErrorHandler = this; - ArrayList arguments = CreateDelegateMethodArguments (invoke_method, loc); + Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc); method_group = method_group.OverloadResolve (ec, ref arguments, false, loc); if (method_group == null) return null; - delegate_method = (MethodInfo) method_group; + var delegate_method = method_group.BestCandidate; if (TypeManager.IsNullableType (delegate_method.DeclaringType)) { - Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable type", - TypeManager.GetFullNameSignature (delegate_method)); + ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable type", + delegate_method.GetSignatureForError ()); return null; } - Invocation.IsSpecialMethodInvocation (delegate_method, loc); + Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; if (emg != null) { - delegate_instance_expression = emg.ExtensionExpression; - Type e_type = delegate_instance_expression.Type; + method_group.InstanceExpression = emg.ExtensionExpression; + TypeSpec e_type = emg.ExtensionExpression.Type; if (TypeManager.IsValueType (e_type)) { - Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", - TypeManager.CSharpSignature (delegate_method), TypeManager.CSharpName (e_type)); + ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", + delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type)); } } - Type rt = TypeManager.TypeToCoreType (delegate_method.ReturnType); + TypeSpec rt = delegate_method.ReturnType; Expression ret_expr = new TypeExpression (rt, loc); - if (!Delegate.IsTypeCovariant (ret_expr, (TypeManager.TypeToCoreType (invoke_method.ReturnType)))) { + if (!Delegate.IsTypeCovariant (ret_expr, invoke_method.ReturnType)) { Error_ConversionFailed (ec, delegate_method, ret_expr); } - if (Invocation.IsMethodExcluded (delegate_method, loc)) { - Report.SymbolRelatedToPreviousError (delegate_method); - MethodOrOperator m = TypeManager.GetMethod (delegate_method) as MethodOrOperator; + if (delegate_method.IsConditionallyExcluded (loc)) { + ec.Report.SymbolRelatedToPreviousError (delegate_method); + MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; if (m != null && m.IsPartialDefinition) { - Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", - TypeManager.CSharpSignature (delegate_method)); + ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", + delegate_method.GetSignatureForError ()); } else { - Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", + ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); } } - DoResolveInstanceExpression (ec); + var expr = method_group.InstanceExpression; + if (expr != null && (expr.Type.IsGenericParameter || !TypeManager.IsReferenceType (expr.Type))) + method_group.InstanceExpression = new BoxedCast (expr, TypeManager.object_type); + eclass = ExprClass.Value; return this; } - - void DoResolveInstanceExpression (EmitContext ec) - { - // - // Argument is another delegate - // - if (delegate_instance_expression != null) - return; - - Expression instance = method_group.InstanceExpression; - if (instance != null && instance != EmptyExpression.Null) { - delegate_instance_expression = instance; - Type instance_type = delegate_instance_expression.Type; - if (TypeManager.IsValueType (instance_type) || TypeManager.IsGenericParameter (instance_type)) { - delegate_instance_expression = new BoxedCast ( - delegate_instance_expression, TypeManager.object_type); - } - } else if (!delegate_method.IsStatic && !ec.IsStatic) { - delegate_instance_expression = ec.GetThis (loc); - } - } public override void Emit (EmitContext ec) { - if (delegate_instance_expression == null) - ec.ig.Emit (OpCodes.Ldnull); + if (method_group.InstanceExpression == null) + ec.Emit (OpCodes.Ldnull); else - delegate_instance_expression.Emit (ec); + method_group.InstanceExpression.Emit (ec); + + var delegate_method = method_group.BestCandidate; - if (!delegate_method.DeclaringType.IsSealed && delegate_method.IsVirtual && !method_group.IsBase) { - ec.ig.Emit (OpCodes.Dup); - ec.ig.Emit (OpCodes.Ldvirtftn, delegate_method); + // Any delegate must be sealed + if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) { + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldvirtftn, delegate_method); } else { - ec.ig.Emit (OpCodes.Ldftn, delegate_method); + ec.Emit (OpCodes.Ldftn, delegate_method); } - ec.ig.Emit (OpCodes.Newobj, constructor_method); + ec.Emit (OpCodes.Newobj, constructor_method); } - void Error_ConversionFailed (EmitContext ec, MethodBase method, Expression return_type) + void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type) { - MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type); - string member_name = delegate_instance_expression != null ? + var invoke_method = Delegate.GetInvokeMethod (ec.Compiler, type); + string member_name = method_group.InstanceExpression != null ? Delegate.FullDelegateDesc (method) : TypeManager.GetFullNameSignature (method); - Report.SymbolRelatedToPreviousError (type); - Report.SymbolRelatedToPreviousError (method); + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.SymbolRelatedToPreviousError (method); if (RootContext.Version == LanguageVersion.ISO_1) { - Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type", - TypeManager.CSharpName (((MethodInfo) method).ReturnType), member_name, + ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type", + TypeManager.CSharpName (method.ReturnType), member_name, TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); return; } if (return_type == null) { - Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters", + ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters", member_name, Delegate.FullDelegateDesc (invoke_method)); return; } - Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type", + ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type", return_type.GetSignatureForError (), member_name, TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); } - public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type target_type) + public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type) { if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type) - return null; - - foreach (MethodInfo mi in mg.Methods){ - MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, target_type, mg, mi); - if (mb != null) - return mb; - } - return null; - } + return false; - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - if (delegate_instance_expression != null) - delegate_instance_expression.MutateHoistedGenericType (storey); + mg.DelegateType = target_type; + var invoke = Delegate.GetInvokeMethod (ec.Compiler, target_type); - delegate_method = storey.MutateGenericMethod (delegate_method); - constructor_method = storey.MutateConstructor (constructor_method); + Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location); + return mg.OverloadResolve (ec, ref arguments, true, mg.Location) != null; } #region IErrorHandler Members - public bool NoExactMatch (EmitContext ec, MethodBase method) + public bool NoExactMatch (ResolveContext ec, MethodSpec method) { - if (TypeManager.IsGenericMethod (method)) + if (method.IsGeneric) return false; Error_ConversionFailed (ec, method, null); return true; } - public bool AmbiguousCall (MethodBase ambiguous) + public bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous) { return false; } @@ -892,15 +574,15 @@ namespace Mono.CSharp { // public class ImplicitDelegateCreation : DelegateCreation { - ImplicitDelegateCreation (Type t, MethodGroupExpr mg, Location l) + ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l) { type = t; this.method_group = mg; loc = l; } - static public Expression Create (EmitContext ec, MethodGroupExpr mge, - Type target_type, Location loc) + static public Expression Create (ResolveContext ec, MethodGroupExpr mge, + TypeSpec target_type, Location loc) { ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc); return d.DoResolve (ec); @@ -912,26 +594,26 @@ namespace Mono.CSharp { // public class NewDelegate : DelegateCreation { - public ArrayList Arguments; + public Arguments Arguments; // // This constructor is invoked from the `New' expression // - public NewDelegate (Type type, ArrayList Arguments, Location loc) + public NewDelegate (TypeSpec type, Arguments Arguments, Location loc) { this.type = type; this.Arguments = Arguments; this.loc = loc; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { if (Arguments == null || Arguments.Count != 1) { - Error_InvalidDelegateArgument (); + ec.Report.Error (149, loc, "Method name expected"); return null; } - Argument a = (Argument) Arguments [0]; + Argument a = Arguments [0]; if (!a.ResolveMethodGroup (ec)) return null; @@ -948,84 +630,85 @@ namespace Mono.CSharp { method_group = e as MethodGroupExpr; if (method_group == null) { - if (!TypeManager.IsDelegateType (e.Type)) { - e.Error_UnexpectedKind (ResolveFlags.MethodGroup | ResolveFlags.Type, loc); + if (e.Type == InternalType.Dynamic) { + e = Convert.ImplicitConversionRequired (ec, e, type, loc); + } else if (!e.Type.IsDelegate) { + e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc); return null; } // // An argument is not a method but another delegate // - delegate_instance_expression = e; - method_group = new MethodGroupExpr (new MemberInfo [] { - Delegate.GetInvokeMethod (ec.ContainerType, e.Type) }, e.Type, loc); + method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (ec.Compiler, e.Type), e.Type, loc); + method_group.InstanceExpression = e; } return base.DoResolve (ec); } - - void Error_InvalidDelegateArgument () - { - Report.Error (149, loc, "Method name expected"); - } } - public class DelegateInvocation : ExpressionStatement { - + // + // Invocation converted to delegate Invoke call + // + class DelegateInvocation : ExpressionStatement + { readonly Expression InstanceExpr; - readonly ArrayList Arguments; - - MethodInfo method; + Arguments arguments; + MethodSpec method; - public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc) + public DelegateInvocation (Expression instance_expr, Arguments args, Location loc) { this.InstanceExpr = instance_expr; - this.Arguments = args; + this.arguments = args; this.loc = loc; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { - ArrayList args; - if (Arguments == null) - args = new ArrayList (1); - else - args = new ArrayList (Arguments.Count + 1); - - args.Add (new Argument (InstanceExpr.CreateExpressionTree (ec))); - if (Arguments != null) { - foreach (Argument a in Arguments) - args.Add (new Argument (a.Expr.CreateExpressionTree (ec))); - } + Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments, + InstanceExpr.CreateExpressionTree (ec)); - return CreateExpressionFactoryCall ("Invoke", args); + return CreateExpressionFactoryCall (ec, "Invoke", args); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { if (InstanceExpr is EventExpr) { - ((EventExpr) InstanceExpr).Error_CannotAssign (); + ((EventExpr) InstanceExpr).Error_CannotAssign (ec); return null; } - Type del_type = InstanceExpr.Type; + TypeSpec del_type = InstanceExpr.Type; if (del_type == null) return null; - if (Arguments != null){ - foreach (Argument a in Arguments){ - if (!a.Resolve (ec, loc)) - return null; - } + method = Delegate.GetInvokeMethod (ec.Compiler, del_type); + var mb = method; + var me = new MethodGroupExpr (mb, del_type, loc); + me.InstanceExpression = InstanceExpr; + + AParametersCollection pd = mb.Parameters; + int pd_count = pd.Count; + + int arg_count = arguments == null ? 0 : arguments.Count; + + bool params_method = pd.HasParams; + bool is_params_applicable = false; + bool is_applicable = me.IsApplicable (ec, ref arguments, arg_count, ref mb, ref is_params_applicable) == 0; + if (arguments != null) + arg_count = arguments.Count; + + if (!is_applicable && !params_method && arg_count != pd_count) { + ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + TypeManager.CSharpName (del_type), arg_count.ToString ()); + } else if (arguments == null || !arguments.HasDynamic) { + me.VerifyArgumentsCompat (ec, ref arguments, arg_count, mb, + is_params_applicable || (!is_applicable && params_method), false, loc); } - - if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc)) - return null; - method = Delegate.GetInvokeMethod (ec.ContainerType, del_type); - type = TypeManager.TypeToCoreType (method.ReturnType); + type = method.ReturnType; eclass = ExprClass.Value; - return this; } @@ -1035,7 +718,7 @@ namespace Mono.CSharp { // Invocation on delegates call the virtual Invoke member // so we are always `instance' calls // - Invocation.EmitCall (ec, false, InstanceExpr, method, Arguments, loc); + Invocation.EmitCall (ec, false, InstanceExpr, method, arguments, loc); } public override void EmitStatement (EmitContext ec) @@ -1045,21 +728,12 @@ namespace Mono.CSharp { // Pop the return value if there is one // if (type != TypeManager.void_type) - ec.ig.Emit (OpCodes.Pop); + ec.Emit (OpCodes.Pop); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) { - method = storey.MutateGenericMethod (method); - type = storey.MutateType (type); - - if (Arguments != null) { - foreach (Argument a in Arguments) { - a.Expr.MutateHoistedGenericType (storey); - } - } - - InstanceExpr.MutateHoistedGenericType (storey); + return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments); } } }