X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdelegate.cs;h=622244d1b5214bfd19f9636464c6713e74fe8d86;hb=f8be5461467b13a0423adc77b4f0ad897537d532;hp=3a9f52e99348d070f7bf910ac962cf2b600db64a;hpb=9e9d8511a8b0ffdf0e49fa6a8f8edc952a8ea917;p=mono.git diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index 3a9f52e9934..622244d1b52 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -6,10 +6,10 @@ // Miguel de Icaza (miguel@ximian.com) // Marek Safar (marek.safar@gmail.com) // -// Licensed under the terms of the GNU GPL -// -// (C) 2001 Ximian, Inc (http://www.ximian.com) +// 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) // using System; @@ -23,9 +23,10 @@ namespace Mono.CSharp { /// /// Holds Delegates /// - public class Delegate : DeclSpace { - public Expression ReturnType; - public Parameters Parameters; + public class Delegate : DeclSpace, IMemberContainer + { + FullNamedExpression ReturnType; + public ParametersCompiled Parameters; public ConstructorBuilder ConstructorBuilder; public MethodBuilder InvokeBuilder; @@ -39,7 +40,12 @@ namespace Mono.CSharp { Expression instance_expr; MethodBase delegate_method; ReturnParameter return_attributes; - + + MemberCache member_cache; + + const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | + MethodAttributes.Virtual | MethodAttributes.NewSlot; + const int AllowedModifiers = Modifiers.NEW | Modifiers.PUBLIC | @@ -48,8 +54,8 @@ namespace Mono.CSharp { Modifiers.UNSAFE | Modifiers.PRIVATE; - public Delegate (NamespaceEntry ns, DeclSpace parent, Expression type, - int mod_flags, MemberName name, Parameters param_list, + public Delegate (NamespaceEntry ns, DeclSpace parent, FullNamedExpression type, + int mod_flags, MemberName name, ParametersCompiled param_list, Attributes attrs) : base (ns, parent, name, attrs) @@ -61,17 +67,17 @@ namespace Mono.CSharp { Parameters = param_list; } - public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb) + public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa) { if (a.Target == AttributeTargets.ReturnValue) { if (return_attributes == null) return_attributes = new ReturnParameter (InvokeBuilder, Location); - return_attributes.ApplyAttributeBuilder (a, cb); + return_attributes.ApplyAttributeBuilder (a, cb, pa); return; } - base.ApplyAttributeBuilder (a, cb); + base.ApplyAttributeBuilder (a, cb, pa); } public override TypeBuilder DefineType () @@ -79,23 +85,11 @@ namespace Mono.CSharp { if (TypeBuilder != null) return TypeBuilder; - if (TypeManager.multicast_delegate_type == null && !RootContext.StdLib) { - Namespace system = RootNamespace.Global.GetNamespace ("System", true); - TypeExpr expr = system.Lookup (this, "MulticastDelegate", Location) as TypeExpr; - TypeManager.multicast_delegate_type = expr.Type; - } - - if (TypeManager.multicast_delegate_type == null) - Report.Error (-100, Location, "Internal error: delegate used before " + - "System.MulticastDelegate is resolved. This can only " + - "happen during corlib compilation, when using a delegate " + - "in any of the `core' classes. See bug #72015 for details."); - if (IsTopLevel) { if (TypeManager.NamespaceClash (Name, Location)) return null; - ModuleBuilder builder = CodeGen.Module.Builder; + ModuleBuilder builder = Module.Builder; TypeBuilder = builder.DefineType ( Name, TypeAttr, TypeManager.multicast_delegate_type); @@ -142,7 +136,6 @@ namespace Mono.CSharp { public override bool Define () { -#if GMCS_SOURCE if (IsGeneric) { foreach (TypeParameter type_param in TypeParameters) { if (!type_param.Resolve (this)) @@ -153,13 +146,9 @@ namespace Mono.CSharp { if (!type_param.DefineType (this)) return false; } - - foreach (TypeParameter type_param in TypeParameters) { - if (!type_param.CheckDependencies ()) - return false; - } } -#endif + + member_cache = new MemberCache (TypeManager.multicast_delegate_type, this); // FIXME: POSSIBLY make this static, as it is always constant // @@ -179,16 +168,17 @@ namespace Mono.CSharp { // // HACK because System.Reflection.Emit is lame // - Parameter [] fixed_pars = new Parameter [2]; - fixed_pars [0] = new Parameter (TypeManager.object_type, "object", - Parameter.Modifier.NONE, null, Location); - fixed_pars [1] = new Parameter (TypeManager.intptr_type, "method", - Parameter.Modifier.NONE, null, Location); - Parameters const_parameters = new Parameters (fixed_pars); - const_parameters.Resolve (null); + 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); @@ -207,11 +197,12 @@ namespace Mono.CSharp { // Check accessibility foreach (Type partype in Parameters.Types){ - if (!Parent.AsAccessible (partype, ModFlags)) { + if (!IsAccessibleAs (partype)) { + Report.SymbolRelatedToPreviousError (partype); Report.Error (59, Location, - "Inconsistent accessibility: parameter type `" + - TypeManager.CSharpName (partype) + "' is less " + - "accessible than delegate `" + Name + "'"); + "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", + TypeManager.CSharpName (partype), + GetSignatureForError ()); return false; } } @@ -222,19 +213,24 @@ namespace Mono.CSharp { ret_type = ReturnType.Type; - if (!Parent.AsAccessible (ret_type, ModFlags)) { + 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 `" + Name + "'"); + "accessible than delegate `" + GetSignatureForError () + "'"); return false; } - if (RootContext.StdLib && (ret_type == TypeManager.arg_iterator_type || ret_type == TypeManager.typed_reference_type)) { + CheckProtectedModifier (); + + if (RootContext.StdLib && TypeManager.IsSpecialType (ret_type)) { Method.Error1599 (Location, ret_type); return false; } + TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); + // // We don't have to check any others because they are all // guaranteed to be accessible - they are standard types. @@ -242,31 +238,46 @@ namespace Mono.CSharp { CallingConventions cc = Parameters.CallingConvention; - const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot; - InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", mattr, cc, ret_type, - Parameters.Types); + 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); + } + return true; + } + + void DefineAsyncMethods (CallingConventions cc) + { // // BeginInvoke // - - Parameters async_parameters = Parameters.MergeGenerated (Parameters, - new Parameter (TypeManager.asynccallback_type, "callback", Parameter.Modifier.NONE, null, Location), - new Parameter (TypeManager.object_type, "object", Parameter.Modifier.NONE, null, Location)); - + 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) + }, + new Type [] { + TypeManager.asynccallback_type, + TypeManager.object_type + } + ); + BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke", - mattr, cc, TypeManager.iasyncresult_type, async_parameters.Types); + mattr, cc, TypeManager.iasyncresult_type, async_parameters.GetEmitTypes ()); BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters); + member_cache.AddMember (BeginInvokeBuilder, this); // // EndInvoke is a bit more interesting, all the parameters labeled as @@ -276,7 +287,7 @@ namespace Mono.CSharp { // // Define parameters, and count out/ref parameters // - Parameters end_parameters; + ParametersCompiled end_parameters; int out_params = 0; foreach (Parameter p in Parameters.FixedParameters) { @@ -286,45 +297,45 @@ namespace Mono.CSharp { if (out_params > 0) { Type [] end_param_types = new Type [out_params]; - Parameter [] end_params = new Parameter [out_params ]; + Parameter[] end_params = new Parameter [out_params]; - int param = 0; + int param = 0; for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { - Parameter p = Parameters.FixedParameters [i]; + Parameter p = Parameters [i]; if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) continue; - end_param_types [param] = p.ExternalType(); + end_param_types [param] = Parameters.Types [i]; end_params [param] = p; ++param; } - end_parameters = Parameters.CreateFullyResolved (end_params, end_param_types); - } - else { - end_parameters = Parameters.EmptyReadOnlyParameters; + end_parameters = ParametersCompiled.CreateFullyResolved (end_params, end_param_types); + } else { + end_parameters = ParametersCompiled.EmptyReadOnlyParameters; } - end_parameters = Parameters.MergeGenerated (end_parameters, - new Parameter (TypeManager.iasyncresult_type, "result", Parameter.Modifier.NONE, null, Location)); - + end_parameters = ParametersCompiled.MergeGenerated (end_parameters, false, + new Parameter (null, "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.Types); + EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.GetEmitTypes ()); EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); end_parameters.ApplyAttributes (EndInvokeBuilder); TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters); - - return true; + member_cache.AddMember (EndInvokeBuilder, this); } public override void Emit () { Parameters.ApplyAttributes (InvokeBuilder); - Parameters p = (Parameters)TypeManager.GetParameterData (BeginInvokeBuilder); - p.ApplyAttributes (BeginInvokeBuilder); + if (BeginInvokeBuilder != null) { + ParametersCompiled p = (ParametersCompiled) TypeManager.GetParameterData (BeginInvokeBuilder); + p.ApplyAttributes (BeginInvokeBuilder); + } if (OptAttributes != null) { OptAttributes.Emit (); @@ -357,24 +368,23 @@ namespace Mono.CSharp { Parameters.VerifyClsCompliance (); if (!AttributeTester.IsClsCompliant (ReturnType.Type)) { - Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ()); + Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", + GetSignatureForError ()); } return true; } - public static ConstructorInfo GetConstructor (Type containerType, Type delegateType) + public static ConstructorInfo GetConstructor (Type container_type, Type delegate_type) { - Type dt = delegateType; -#if GMCS_SOURCE + Type dt = delegate_type; Type[] g_args = null; - if (delegateType.IsGenericType) { - g_args = delegateType.GetGenericArguments (); - delegateType = delegateType.GetGenericTypeDefinition (); + if (TypeManager.IsGenericType (delegate_type)) { + g_args = TypeManager.GetTypeArguments (delegate_type); + delegate_type = TypeManager.DropGenericTypeArguments (delegate_type); } -#endif - Delegate d = TypeManager.LookupDelegate (delegateType); + Delegate d = TypeManager.LookupDelegate (delegate_type); if (d != null) { #if GMCS_SOURCE if (g_args != null) @@ -383,7 +393,7 @@ namespace Mono.CSharp { return d.ConstructorBuilder; } - Expression ml = Expression.MemberLookup (containerType, + Expression ml = Expression.MemberLookup (container_type, null, dt, ConstructorInfo.ConstructorName, MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location.Null); @@ -404,20 +414,21 @@ namespace Mono.CSharp { public static MethodInfo GetInvokeMethod (Type container_type, Type delegate_type) { 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 (); + if (TypeManager.IsGenericType (delegate_type)) { + g_args = TypeManager.GetTypeArguments (delegate_type); + delegate_type = TypeManager.DropGenericTypeArguments (delegate_type); } -#endif + Delegate d = TypeManager.LookupDelegate (delegate_type); + MethodInfo invoke; if (d != null) { #if GMCS_SOURCE if (g_args != null) { - MethodInfo invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder); + invoke = TypeBuilder.GetMethod (dt, d.InvokeBuilder); #if MS_COMPATIBLE - Parameters p = (Parameters) d.Parameters.InflateTypes (g_args, g_args); + ParametersCompiled p = (ParametersCompiled) d.Parameters.InflateTypes (g_args, g_args); TypeManager.RegisterMethod (invoke, p); #endif return invoke; @@ -436,7 +447,36 @@ namespace Mono.CSharp { return null; } - return (MethodInfo) mg.Methods[0]; + 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 invoke; + } + + // + // 15.2 Delegate compatibility + // + public static bool IsTypeCovariant (Expression a, Type b) + { + // + // For each value parameter (a parameter with no ref or out modifier), an + // identity conversion or implicit reference conversion exists from the + // parameter type in D to the corresponding parameter type in M + // + if (a.Type == b) + return true; + + if (RootContext.Version == LanguageVersion.ISO_1) + return false; + + return Convert.ImplicitReferenceConversionExists (a, b); } /// @@ -444,19 +484,25 @@ namespace Mono.CSharp { /// 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, - Location loc) + MethodGroupExpr old_mg, MethodBase mb) { + bool is_method_definition = TypeManager.IsGenericMethodDefinition (mb); + MethodInfo invoke_mb = GetInvokeMethod (container_type, delegate_type); - ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb); + 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 (!old_mg.HasTypeArguments && + if (!is_method_definition && old_mg.type_arguments == null && !TypeManager.InferTypeArguments (invoke_pd, ref mb)) return null; #endif - - ParameterData pd = TypeManager.GetParameterData (mb); + AParametersCollection pd = TypeManager.GetParameterData (mb); if (invoke_pd.Count != pd.Count) return null; @@ -464,10 +510,10 @@ namespace Mono.CSharp { for (int i = pd.Count; i > 0; ) { i--; - Type invoke_pd_type = invoke_pd.ParameterType (i); - Type pd_type = pd.ParameterType (i); - Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i); - Parameter.Modifier pd_type_mod = pd.ParameterModifier (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; @@ -475,23 +521,22 @@ namespace Mono.CSharp { if (invoke_pd_type_mod != pd_type_mod) return null; - if (invoke_pd_type == pd_type) + if (TypeManager.IsEqual (invoke_pd_type, pd_type)) continue; - if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (invoke_pd_type), pd_type)) - return null; + if (IsTypeCovariant (new EmptyExpression (invoke_pd_type), pd_type)) + continue; - if (RootContext.Version == LanguageVersion.ISO_1) - return null; + return null; } Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType; Type mb_retval = ((MethodInfo) mb).ReturnType; - if (invoke_mb_retval == mb_retval) + if (TypeManager.TypeToCoreType (invoke_mb_retval) == TypeManager.TypeToCoreType (mb_retval)) return mb; - if (!Convert.ImplicitReferenceConversionExists (new EmptyExpression (mb_retval), invoke_mb_retval)) - return null; + //if (!IsTypeCovariant (mb_retval, invoke_mb_retval)) + // return null; if (RootContext.Version == LanguageVersion.ISO_1) return null; @@ -504,7 +549,7 @@ namespace Mono.CSharp { // delegate's target method // public static bool VerifyApplicability (EmitContext ec, Type delegate_type, - ArrayList args, Location loc) + ref ArrayList args, Location loc) { int arg_count; @@ -513,27 +558,18 @@ namespace Mono.CSharp { else arg_count = args.Count; - Expression ml = Expression.MemberLookup ( - ec.ContainerType, delegate_type, "Invoke", loc); - - MethodGroupExpr me = ml as MethodGroupExpr; - if (me == null) { - Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type); - return false; - } - MethodBase mb = GetInvokeMethod (ec.ContainerType, delegate_type); - ParameterData pd = TypeManager.GetParameterData (mb); + 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 = Invocation.IsApplicable (ec, me, args, arg_count, ref mb); - - if (!is_applicable && params_method && - Invocation.IsParamsMethodApplicable (ec, me, args, arg_count, ref mb)) - is_applicable = is_params_applicable = true; + bool is_applicable = me.IsApplicable (ec, ref args, arg_count, ref mb, ref is_params_applicable) == 0; + if (args != null) + arg_count = args.Count; if (!is_applicable && !params_method && arg_count != pd_count) { Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", @@ -541,98 +577,20 @@ namespace Mono.CSharp { return false; } - return Invocation.VerifyArgumentsCompat ( - ec, args, arg_count, mb, + return me.VerifyArgumentsCompat ( + ec, ref args, arg_count, mb, is_params_applicable || (!is_applicable && params_method), - delegate_type, false, loc); + false, loc); } - /// - /// Verifies whether the delegate in question is compatible with this one in - /// order to determine if instantiation from the same is possible. - /// - public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Location loc) + public static string FullDelegateDesc (MethodBase invoke_method) { - Expression ml = Expression.MemberLookup ( - ec.ContainerType, delegate_type, "Invoke", loc); - - if (!(ml is MethodGroupExpr)) { - Report.Error (-100, loc, "Internal error: could not find Invoke method!"); - return false; - } - - MethodBase mb = ((MethodGroupExpr) ml).Methods [0]; - ParameterData pd = TypeManager.GetParameterData (mb); - - Expression probe_ml = Expression.MemberLookup ( - ec.ContainerType, delegate_type, "Invoke", loc); - - if (!(probe_ml is MethodGroupExpr)) { - Report.Error (-100, loc, "Internal error: could not find Invoke method!"); - return false; - } - - MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0]; - ParameterData probe_pd = TypeManager.GetParameterData (probe_mb); - - if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType) - return false; - - if (pd.Count != probe_pd.Count) - return false; - - for (int i = pd.Count; i > 0; ) { - i--; - - if (pd.ParameterType (i) != probe_pd.ParameterType (i) || - pd.ParameterModifier (i) != probe_pd.ParameterModifier (i)) - return false; - } - - return true; + return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", ""); } - public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd) - { - StringBuilder sb = new StringBuilder (); - sb.Append (TypeManager.CSharpName (((MethodInfo) mb).ReturnType)); - sb.Append (" "); - sb.Append (TypeManager.CSharpName (del_type)); - sb.Append (pd.GetSignatureForError ()); - return sb.ToString (); - } - - // Hack around System.Reflection as found everywhere else - public override MemberList FindMembers (MemberTypes mt, BindingFlags bf, - MemberFilter filter, object criteria) - { - ArrayList members = new ArrayList (2); - - if ((mt & MemberTypes.Constructor) != 0) { - if (ConstructorBuilder != null && filter (ConstructorBuilder, criteria)) - members.Add (ConstructorBuilder); - } - - if ((mt & MemberTypes.Method) != 0) { - if (InvokeBuilder != null) - if (filter (InvokeBuilder, criteria)) - members.Add (InvokeBuilder); - - if (BeginInvokeBuilder != null) - if (filter (BeginInvokeBuilder, criteria)) - members.Add (BeginInvokeBuilder); - - if (EndInvokeBuilder != null) - if (filter (EndInvokeBuilder, criteria)) - members.Add (EndInvokeBuilder); - } - - return new MemberList (members); - } - public override MemberCache MemberCache { get { - return null; + return member_cache; } } @@ -672,190 +630,282 @@ namespace Mono.CSharp { 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 } // // Base class for `NewDelegate' and `ImplicitDelegateCreation' // - public abstract class DelegateCreation : Expression { + public abstract class DelegateCreation : Expression, MethodGroupExpr.IErrorHandler + { protected ConstructorInfo constructor_method; - protected MethodBase delegate_method; + protected MethodInfo delegate_method; // We keep this to handle IsBase only protected MethodGroupExpr method_group; protected Expression delegate_instance_expression; - protected DelegateCreation () {} + public static ArrayList CreateDelegateMethodArguments (MethodInfo invoke_method, Location loc) + { + AParametersCollection pd = TypeManager.GetParameterData (invoke_method); + ArrayList delegate_arguments = new ArrayList (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; + break; + } + delegate_arguments.Add (new Argument (new TypeExpression (atype, loc), atype_modifier)); + } + return delegate_arguments; + } - static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc) + public override Expression CreateExpressionTree (EmitContext ec) { - string method_desc; - MethodBase found_method = mg.Methods [0]; + MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc); + + ArrayList args = new ArrayList (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))); + Expression e = new Invocation (ma, args).Resolve (ec); + if (e == null) + return null; - if (mg.Methods.Length > 1) - method_desc = found_method.Name; - else - method_desc = Invocation.FullMethodDesc (found_method); + e = Convert.ExplicitConversion (ec, e, type, loc); + if (e == null) + return null; - MethodInfo method = Delegate.GetInvokeMethod (ec.ContainerType, type); - ParameterData param = TypeManager.GetParameterData (method); + return e.CreateExpressionTree (ec); + } - string delegate_desc = Delegate.FullDelegateDesc (type, method, param); + public override Expression DoResolve (EmitContext ec) + { + constructor_method = Delegate.GetConstructor (ec.ContainerType, type); -#if GMCS_SOURCE - if (!mg.HasTypeArguments && - !TypeManager.InferTypeArguments (param, ref found_method)) { - Report.Error (411, loc, "The type arguments for " + - "method `{0}' cannot be inferred from " + - "the usage. Try specifying the type " + - "arguments explicitly.", method_desc); - return; + MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type); + method_group.DelegateType = type; + method_group.CustomErrorHandler = this; + + ArrayList arguments = CreateDelegateMethodArguments (invoke_method, loc); + method_group = method_group.OverloadResolve (ec, ref arguments, false, loc); + if (method_group == null) + return null; + + delegate_method = (MethodInfo) method_group; + + 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)); + return null; + } + + Invocation.IsSpecialMethodInvocation (delegate_method, loc); + + ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; + if (emg != null) { + delegate_instance_expression = emg.ExtensionExpression; + Type e_type = delegate_instance_expression.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)); + } } -#endif - Report.SymbolRelatedToPreviousError (found_method); - if (RootContext.Version == LanguageVersion.ISO_1) { - Report.Error (410, loc, "The method `{0}' parameters and return type must be same as delegate `{1}' parameters and return type", - method_desc, delegate_desc); - return; + Type rt = TypeManager.TypeToCoreType (delegate_method.ReturnType); + Expression ret_expr = new TypeExpression (rt, loc); + if (!Delegate.IsTypeCovariant (ret_expr, (TypeManager.TypeToCoreType (invoke_method.ReturnType)))) { + Error_ConversionFailed (ec, delegate_method, ret_expr); } - Type delegateType = method.ReturnType; - Type methodType = ((MethodInfo) found_method).ReturnType; - if (delegateType != methodType && - !Convert.ImplicitReferenceConversionExists (new EmptyExpression (methodType), delegateType)) { - Report.Error (407, loc, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc, delegate_desc); - } else { - Report.Error (123, loc, "The method `{0}' parameters do not match delegate `{1}' parameters", - TypeManager.CSharpSignature (found_method), delegate_desc); + if (Invocation.IsMethodExcluded (delegate_method, loc)) { + Report.SymbolRelatedToPreviousError (delegate_method); + MethodOrOperator m = TypeManager.GetMethod (delegate_method) as MethodOrOperator; + if (m != null && m.IsPartialDefinition) { + Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", + TypeManager.CSharpSignature (delegate_method)); + } else { + Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", + TypeManager.CSharpSignature (delegate_method)); + } + } + + DoResolveInstanceExpression (ec); + 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 || delegate_method.IsStatic) + if (delegate_instance_expression == null) ec.ig.Emit (OpCodes.Ldnull); else delegate_instance_expression.Emit (ec); - if (delegate_method.IsVirtual && !method_group.IsBase) { + if (!delegate_method.DeclaringType.IsSealed && delegate_method.IsVirtual && !method_group.IsBase) { ec.ig.Emit (OpCodes.Dup); - ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method); - } else - ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method); + ec.ig.Emit (OpCodes.Ldvirtftn, delegate_method); + } else { + ec.ig.Emit (OpCodes.Ldftn, delegate_method); + } + ec.ig.Emit (OpCodes.Newobj, constructor_method); } - protected bool ResolveConstructorMethod (EmitContext ec) + void Error_ConversionFailed (EmitContext ec, MethodBase method, Expression return_type) { - constructor_method = Delegate.GetConstructor (ec.ContainerType, type); - return true; + MethodInfo invoke_method = Delegate.GetInvokeMethod (ec.ContainerType, type); + string member_name = delegate_instance_expression != null ? + Delegate.FullDelegateDesc (method) : + TypeManager.GetFullNameSignature (method); + + Report.SymbolRelatedToPreviousError (type); + 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, + 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", + 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", + return_type.GetSignatureForError (), member_name, + TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); } - public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type targetType) + public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type 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, targetType, mg, mi, Location.Null); + MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, target_type, mg, mi); if (mb != null) return mb; } return null; } - protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg) + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) { - delegate_method = ImplicitStandardConversionExists (mg, type); + if (delegate_instance_expression != null) + delegate_instance_expression.MutateHoistedGenericType (storey); - if (delegate_method == null) { - Error_NoMatchingMethodForDelegate (ec, mg, type, loc); - return null; - } - - // - // Check safe/unsafe of the delegate - // - if (!ec.InUnsafe){ - ParameterData param = TypeManager.GetParameterData (delegate_method); - int count = param.Count; - - for (int i = 0; i < count; i++){ - if (param.ParameterType (i).IsPointer){ - Expression.UnsafeError (loc); - return null; - } - } - } - - //TODO: implement caching when performance will be low - IMethodData md = TypeManager.GetMethod ( - TypeManager.DropGenericMethodArguments (delegate_method)); - if (md == null) { - if (System.Attribute.GetCustomAttribute (delegate_method, TypeManager.conditional_attribute_type) != null) { - Report.SymbolRelatedToPreviousError (delegate_method); - Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); - return null; - } - } else { - md.SetMemberIsUsed (); - if (md.OptAttributes != null && md.OptAttributes.Search (TypeManager.conditional_attribute_type) != null) { - Report.SymbolRelatedToPreviousError (delegate_method); - Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); - return null; - } - } - - if (mg.InstanceExpression != null) - delegate_instance_expression = mg.InstanceExpression.Resolve (ec); - else if (ec.IsStatic) { - if (!delegate_method.IsStatic) { - Report.Error (120, loc, "`{0}': An object reference is required for the nonstatic field, method or property", - TypeManager.CSharpSignature (delegate_method)); - return null; - } - delegate_instance_expression = null; - } else - delegate_instance_expression = ec.GetThis (loc); + delegate_method = storey.MutateGenericMethod (delegate_method); + constructor_method = storey.MutateConstructor (constructor_method); + } - if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType) - delegate_instance_expression = new BoxedCast ( - delegate_instance_expression, TypeManager.object_type); + #region IErrorHandler Members - method_group = mg; - eclass = ExprClass.Value; - return this; + public bool NoExactMatch (EmitContext ec, MethodBase method) + { + if (TypeManager.IsGenericMethod (method)) + return false; + + Error_ConversionFailed (ec, method, null); + return true; + } + + public bool AmbiguousCall (MethodBase ambiguous) + { + return false; } + + #endregion } // // Created from the conversion code // - public class ImplicitDelegateCreation : DelegateCreation { - - ImplicitDelegateCreation (Type t, Location l) + public class ImplicitDelegateCreation : DelegateCreation + { + ImplicitDelegateCreation (Type t, MethodGroupExpr mg, Location l) { type = t; + this.method_group = mg; loc = l; } - public override Expression DoResolve (EmitContext ec) - { - return this; - } - static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc) { - ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc); - if (!d.ResolveConstructorMethod (ec)) - return null; - - return d.ResolveMethodGroupExpr (ec, mge); + ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc); + return d.DoResolve (ec); } } // // A delegate-creation-expression, invoked from the `New' class // - public class NewDelegate : DelegateCreation { + public class NewDelegate : DelegateCreation + { public ArrayList Arguments; // @@ -870,63 +920,55 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - if (Arguments == null) { - Invocation.Error_WrongNumArguments (loc, GetSignatureForError (), 0); + if (Arguments == null || Arguments.Count != 1) { + Error_InvalidDelegateArgument (); return null; } - if (!ResolveConstructorMethod (ec)) - return null; - Argument a = (Argument) Arguments [0]; - if (!a.ResolveMethodGroup (ec)) return null; - - Expression e = a.Expr; - if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1) - return ((AnonymousMethodExpression) e).Compatible (ec, type).Resolve (ec); + Expression e = a.Expr; - MethodGroupExpr mg = e as MethodGroupExpr; - if (mg != null) { - if (TypeManager.IsNullableType (mg.DeclaringType)) { - Report.Error (1728, loc, "Cannot use method `{0}' as delegate creation expression because it is member of Nullable type", - mg.GetSignatureForError ()); + AnonymousMethodExpression ame = e as AnonymousMethodExpression; + if (ame != null && RootContext.Version != LanguageVersion.ISO_1) { + e = ame.Compatible (ec, type); + if (e == null) return null; - } - return ResolveMethodGroupExpr (ec, mg); + return e.Resolve (ec); } - if (!TypeManager.IsDelegateType (e.Type)) { - Report.Error (149, loc, "Method name expected"); - return null; - } + method_group = e as MethodGroupExpr; + if (method_group == null) { + if (!TypeManager.IsDelegateType (e.Type)) { + e.Error_UnexpectedKind (ResolveFlags.MethodGroup | ResolveFlags.Type, loc); + return null; + } - // This is what MS' compiler reports. We could always choose - // to be more verbose and actually give delegate-level specifics - if (!Delegate.VerifyDelegate (ec, type, loc)) { - Report.Error (29, loc, "Cannot implicitly convert type '" + e.Type + "' " + - "to type '" + type + "'"); - 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); } - - delegate_instance_expression = e; - delegate_method = Delegate.GetInvokeMethod (ec.ContainerType, type); - method_group = new MethodGroupExpr (new MemberInfo[] { delegate_method }, type, loc); - eclass = ExprClass.Value; - return this; + return base.DoResolve (ec); + } + + void Error_InvalidDelegateArgument () + { + Report.Error (149, loc, "Method name expected"); } } public class DelegateInvocation : ExpressionStatement { readonly Expression InstanceExpr; - readonly ArrayList Arguments; - - MethodBase method; + ArrayList Arguments; + MethodInfo method; public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc) { @@ -934,34 +976,31 @@ namespace Mono.CSharp { this.Arguments = args; this.loc = loc; } + + public override Expression CreateExpressionTree (EmitContext 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))); + } + + return CreateExpressionFactoryCall ("Invoke", args); + } public override Expression DoResolve (EmitContext ec) { if (InstanceExpr is EventExpr) { - - EventInfo ei = ((EventExpr) InstanceExpr).EventInfo; - - Expression ml = MemberLookup ( - ec.ContainerType, ec.ContainerType, ei.Name, - MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc); - - if (ml == null) { - // - // If this is the case, then the Event does not belong - // to this Type and so, according to the spec - // cannot be accessed directly - // - // Note that target will not appear as an EventExpr - // in the case it is being referenced within the same type container; - // it will appear as a FieldExpr in that case. - // - - Assign.error70 (ei, loc); - return null; - } + ((EventExpr) InstanceExpr).Error_CannotAssign (); + return null; } - Type del_type = InstanceExpr.Type; if (del_type == null) return null; @@ -973,11 +1012,11 @@ namespace Mono.CSharp { } } - if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc)) + if (!Delegate.VerifyApplicability (ec, del_type, ref Arguments, loc)) return null; method = Delegate.GetInvokeMethod (ec.ContainerType, del_type); - type = ((MethodInfo) method).ReturnType; + type = TypeManager.TypeToCoreType (method.ReturnType); eclass = ExprClass.Value; return this; @@ -998,12 +1037,22 @@ namespace Mono.CSharp { // // Pop the return value if there is one // - if (method is MethodInfo){ - Type ret = ((MethodInfo)method).ReturnType; - if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type) - ec.ig.Emit (OpCodes.Pop); - } + if (type != TypeManager.void_type) + ec.ig.Emit (OpCodes.Pop); } + public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + { + method = storey.MutateGenericMethod (method); + type = storey.MutateType (type); + + if (Arguments != null) { + foreach (Argument a in Arguments) { + a.Expr.MutateHoistedGenericType (storey); + } + } + + InstanceExpr.MutateHoistedGenericType (storey); + } } }