X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdelegate.cs;h=608961acf168675766cdeae36db7f2564980dddb;hb=6aa6c6b2f57d04868ad3562dabe28a8222ae6d25;hp=f85632fd6bfea48c35b3a444f2f999d4da1aa349;hpb=0abc2e6270020edc4a5b4c66f93b4ae582815f20;p=mono.git diff --git a/mcs/mcs/delegate.cs b/mcs/mcs/delegate.cs index f85632fd6bf..608961acf16 100644 --- a/mcs/mcs/delegate.cs +++ b/mcs/mcs/delegate.cs @@ -31,7 +31,6 @@ namespace Mono.CSharp { public MethodBuilder BeginInvokeBuilder; public MethodBuilder EndInvokeBuilder; - Type [] param_types; Type ret_type; static string[] attribute_targets = new string [] { "type", "return" }; @@ -48,16 +47,16 @@ namespace Mono.CSharp { Modifiers.UNSAFE | Modifiers.PRIVATE; - public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type, + public Delegate (NamespaceEntry ns, DeclSpace parent, Expression type, int mod_flags, MemberName name, Parameters param_list, - Attributes attrs, Location l) - : base (ns, parent, name, attrs, l) + Attributes attrs) + : base (ns, parent, name, attrs) { this.ReturnType = type; ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, IsTopLevel ? Modifiers.INTERNAL : - Modifiers.PRIVATE, l); + Modifiers.PRIVATE, name.Location); Parameters = param_list; } @@ -79,10 +78,14 @@ namespace Mono.CSharp { if (TypeBuilder != null) return TypeBuilder; - ec = new EmitContext (this, this, Location, null, null, ModFlags, false); + 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; + } - TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) | - TypeAttributes.Class | TypeAttributes.Sealed; + if (TypeManager.multicast_delegate_type == null) + throw new InternalErrorException ("System.MulticastDelegate unresolved"); if (IsTopLevel) { if (TypeManager.NamespaceClash (Name, Location)) @@ -91,41 +94,32 @@ namespace Mono.CSharp { ModuleBuilder builder = CodeGen.Module.Builder; TypeBuilder = builder.DefineType ( - Name, attr, TypeManager.multicast_delegate_type); + Name, TypeAttr, TypeManager.multicast_delegate_type); } else { TypeBuilder builder = Parent.TypeBuilder; string name = Name.Substring (1 + Name.LastIndexOf ('.')); TypeBuilder = builder.DefineNestedType ( - name, attr, TypeManager.multicast_delegate_type); + name, TypeAttr, TypeManager.multicast_delegate_type); } - TypeManager.AddDelegateType (Name, TypeBuilder, this); + TypeManager.AddUserType (this); return TypeBuilder; } - public override bool DefineMembers (TypeContainer container) - { - return true; - } - public override bool Define () { - MethodAttributes mattr; - int i; - ec = new EmitContext (this, this, Location, null, null, ModFlags, false); - // 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; - mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | + const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; - ConstructorBuilder = TypeBuilder.DefineConstructor (mattr, + ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr, CallingConventions.Standard, const_arg_types); @@ -134,19 +128,15 @@ namespace Mono.CSharp { // // HACK because System.Reflection.Emit is lame // - // - // FIXME: POSSIBLY make these static, as they are always the same Parameter [] fixed_pars = new Parameter [2]; - fixed_pars [0] = new Parameter (TypeManager.system_object_expr, "object", - Parameter.Modifier.NONE, null); - fixed_pars [1] = new Parameter (TypeManager.system_intptr_expr, "method", - Parameter.Modifier.NONE, null); - Parameters const_parameters = new Parameters (fixed_pars, null, Location); - - TypeManager.RegisterMethod ( - ConstructorBuilder, - new InternalParameters (const_arg_types, const_parameters), - const_arg_types); + 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); + + TypeManager.RegisterMethod (ConstructorBuilder, const_parameters); ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); @@ -157,11 +147,7 @@ namespace Mono.CSharp { // First, call the `out of band' special method for // defining recursively any types we need: - if (!Parameters.ComputeAndDefineParameterTypes (ec)) - return false; - - param_types = Parameters.GetParameterInfo (ec); - if (param_types == null) + if (!Parameters.Resolve (this)) return false; // @@ -169,204 +155,139 @@ namespace Mono.CSharp { // // Check accessibility - foreach (Type partype in param_types){ + foreach (Type partype in Parameters.Types){ if (!Parent.AsAccessible (partype, ModFlags)) { Report.Error (59, Location, "Inconsistent accessibility: parameter type `" + - TypeManager.CSharpName (partype) + "` is less " + + TypeManager.CSharpName (partype) + "' is less " + "accessible than delegate `" + Name + "'"); return false; } - if (partype.IsPointer && !UnsafeOK (Parent)) - return false; } - ReturnType = ReturnType.ResolveAsTypeTerminal (ec, false); - if (ReturnType == null) - return false; - - ret_type = ReturnType.Type; - if (ret_type == null) + ReturnType = ReturnType.ResolveAsTypeTerminal (this, false); + if (ReturnType == null) return false; + ret_type = ReturnType.Type; + if (!Parent.AsAccessible (ret_type, ModFlags)) { Report.Error (58, Location, "Inconsistent accessibility: return type `" + - TypeManager.CSharpName (ret_type) + "` is less " + + TypeManager.CSharpName (ret_type) + "' is less " + "accessible than delegate `" + Name + "'"); return false; } - if (ret_type.IsPointer && !UnsafeOK (Parent)) + if (RootContext.StdLib && (ret_type == TypeManager.arg_iterator_type || ret_type == TypeManager.typed_reference_type)) { + Method.Error1599 (Location, ret_type); return false; + } // // We don't have to check any others because they are all // guaranteed to be accessible - they are standard types. // - CallingConventions cc = Parameters.GetCallingConvention (); + CallingConventions cc = Parameters.CallingConvention; - mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual; + const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot; InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", mattr, cc, ret_type, - param_types); - - // - // Define parameters, and count out/ref parameters - // - int out_params = 0; - i = 0; - if (Parameters.FixedParameters != null){ - int top = Parameters.FixedParameters.Length; - Parameter p; - - for (; i < top; i++) { - p = Parameters.FixedParameters [i]; - p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location); - - if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) - out_params++; - } - } - if (Parameters.ArrayParameter != null){ - Parameter p = Parameters.ArrayParameter; - p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location); - } + Parameters.Types); InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); - TypeManager.RegisterMethod (InvokeBuilder, - new InternalParameters (param_types, Parameters), - param_types); + TypeManager.RegisterMethod (InvokeBuilder, Parameters); // // BeginInvoke // - int params_num = param_types.Length; - Type [] async_param_types = new Type [params_num + 2]; - - param_types.CopyTo (async_param_types, 0); - - async_param_types [params_num] = TypeManager.asynccallback_type; - async_param_types [params_num + 1] = TypeManager.object_type; - - mattr = MethodAttributes.Public | MethodAttributes.HideBySig | - MethodAttributes.Virtual | MethodAttributes.NewSlot; + + 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)); BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke", - mattr, - cc, - TypeManager.iasyncresult_type, - async_param_types); - - i = 0; - if (Parameters.FixedParameters != null){ - int top = Parameters.FixedParameters.Length; - Parameter p; - - for (i = 0 ; i < top; i++) { - p = Parameters.FixedParameters [i]; + mattr, cc, TypeManager.iasyncresult_type, async_parameters.Types); - p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location); - } - } - if (Parameters.ArrayParameter != null){ - Parameter p = Parameters.ArrayParameter; - p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location); - - i++; - } - - BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback"); - BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object"); - BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); - - Parameter [] async_params = new Parameter [params_num + 2]; - int n = 0; - if (Parameters.FixedParameters != null){ - Parameters.FixedParameters.CopyTo (async_params, 0); - n = Parameters.FixedParameters.Length; - } - if (Parameters.ArrayParameter != null) - async_params [n] = Parameters.ArrayParameter; - - async_params [params_num] = new Parameter ( - TypeManager.system_asynccallback_expr, "callback", - Parameter.Modifier.NONE, null); - async_params [params_num + 1] = new Parameter ( - TypeManager.system_object_expr, "object", - Parameter.Modifier.NONE, null); - - Parameters async_parameters = new Parameters (async_params, null, Location); - async_parameters.ComputeAndDefineParameterTypes (ec); - - TypeManager.RegisterMethod (BeginInvokeBuilder, - new InternalParameters (async_param_types, async_parameters), - async_param_types); + async_parameters.ApplyAttributes (BeginInvokeBuilder); + TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters); // // EndInvoke is a bit more interesting, all the parameters labeled as // out or ref have to be duplicated here. // - - Type [] end_param_types = new Type [out_params + 1]; - Parameter [] end_params = new Parameter [out_params + 1]; - int param = 0; - if (out_params > 0){ - int top = Parameters.FixedParameters.Length; - for (i = 0; i < top; i++){ + + // + // Define parameters, and count out/ref parameters + // + Parameters end_parameters; + int out_params = 0; + + foreach (Parameter p in Parameters.FixedParameters) { + if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) + ++out_params; + } + + if (out_params > 0) { + Type [] end_param_types = new Type [out_params]; + Parameter [] end_params = new Parameter [out_params ]; + + int param = 0; + for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { Parameter p = Parameters.FixedParameters [i]; if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) continue; - end_param_types [param] = param_types [i]; + end_param_types [param] = p.ExternalType(); end_params [param] = p; - param++; + ++param; } + end_parameters = new Parameters (end_params, end_param_types); + } + else { + end_parameters = Parameters.EmptyReadOnlyParameters; } - end_param_types [out_params] = TypeManager.iasyncresult_type; - end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null); + end_parameters = Parameters.MergeGenerated (end_parameters, + new Parameter (TypeManager.iasyncresult_type, "result", Parameter.Modifier.NONE, null, Location)); + // // Create method, define parameters, register parameters with type system // - EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types); + EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.Types); EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); - // - // EndInvoke: Label the parameters - // - EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result"); - for (i = 0; i < end_params.Length-1; i++){ - EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name); - } - - Parameters end_parameters = new Parameters (end_params, null, Location); - end_parameters.ComputeAndDefineParameterTypes (ec); - - TypeManager.RegisterMethod ( - EndInvokeBuilder, - new InternalParameters (end_param_types, end_parameters), - end_param_types); + end_parameters.ApplyAttributes (EndInvokeBuilder); + TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters); return true; } public override void Emit () { + Parameters.ApplyAttributes (InvokeBuilder); + if (OptAttributes != null) { - Parameters.LabelParameters (ec, InvokeBuilder, Location); - OptAttributes.Emit (ec, this); + OptAttributes.Emit (); } base.Emit (); } + protected override TypeAttributes TypeAttr { + get { + return Modifiers.TypeAttr (ModFlags, IsTopLevel) | + TypeAttributes.Class | TypeAttributes.Sealed | + base.TypeAttr; + } + } + public override string[] ValidAttributeTargets { get { return attribute_targets; @@ -374,16 +295,16 @@ namespace Mono.CSharp { } //TODO: duplicate - protected override bool VerifyClsCompliance (DeclSpace ds) + protected override bool VerifyClsCompliance () { - if (!base.VerifyClsCompliance (ds)) { + if (!base.VerifyClsCompliance ()) { return false; } - AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location); + Parameters.VerifyClsCompliance (); if (!AttributeTester.IsClsCompliant (ReturnType.Type)) { - Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant", GetSignatureForError ()); + Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ()); } return true; } @@ -392,10 +313,10 @@ namespace Mono.CSharp { // Returns the MethodBase for "Invoke" from a delegate type, this is used // to extract the signature of a delegate. // - public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc) + public static MethodInfo GetInvokeMethod (Type container_type, Type delegate_type, Location loc) { - Expression ml = Expression.MemberLookup ( - ec, delegate_type, "Invoke", loc); + Expression ml = Expression.MemberLookup (container_type, delegate_type, + "Invoke", loc); if (!(ml is MethodGroupExpr)) { Report.Error (-100, loc, "Internal error: could not find Invoke method!"); @@ -409,18 +330,18 @@ namespace Mono.CSharp { /// 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 (EmitContext ec, Type delegate_type, MethodBase mb, + public static MethodBase VerifyMethod (Type container_type, Type delegate_type, MethodBase mb, Location loc) { - ParameterData pd = Invocation.GetParameterData (mb); + ParameterData pd = TypeManager.GetParameterData (mb); int pd_count = pd.Count; - MethodBase invoke_mb = GetInvokeMethod (ec, delegate_type, loc); + MethodBase invoke_mb = GetInvokeMethod (container_type, delegate_type, loc); if (invoke_mb == null) return null; - ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb); + ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb); if (invoke_pd.Count != pd_count) return null; @@ -433,6 +354,9 @@ namespace Mono.CSharp { Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i); Parameter.Modifier pd_type_mod = pd.ParameterModifier (i); + invoke_pd_type_mod &= ~Parameter.Modifier.PARAMS; + pd_type_mod &= ~Parameter.Modifier.PARAMS; + if (invoke_pd_type == pd_type && invoke_pd_type_mod == pd_type_mod) continue; @@ -479,63 +403,47 @@ namespace Mono.CSharp { arg_count = args.Count; Expression ml = Expression.MemberLookup ( - ec, delegate_type, "Invoke", loc); + ec.ContainerType, delegate_type, "Invoke", loc); - if (!(ml is MethodGroupExpr)) { + 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 = ((MethodGroupExpr) ml).Methods [0]; - ParameterData pd = Invocation.GetParameterData (mb); + MethodBase mb = me.Methods [0]; + ParameterData pd = TypeManager.GetParameterData (mb); int pd_count = pd.Count; - bool params_method = (pd_count != 0) && - (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS); + bool params_method = pd.HasParams; + bool is_params_applicable = false; + bool is_applicable = Invocation.IsApplicable (ec, args, arg_count, mb); + + if (!is_applicable && params_method && + Invocation.IsParamsMethodApplicable (ec, args, arg_count, mb)) + is_applicable = is_params_applicable = true; - if (!params_method && pd_count != arg_count) { - Report.Error (1593, loc, - "Delegate '{0}' does not take {1} arguments", - delegate_type.ToString (), arg_count); + 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; } - // - // Consider the case: - // delegate void FOO(param object[] args); - // FOO f = new FOO(...); - // f(new object[] {1, 2, 3}); - // - // This should be treated like f(1,2,3). This is done by ignoring the - // 'param' modifier for that invocation. If that fails, then the - // 'param' modifier is considered. - // - // One issue is that 'VerifyArgumentsCompat' modifies the elements of - // the 'args' array. However, the modifications appear idempotent. - // Normal 'Invocation's also have the same behaviour, implicitly. - // - - bool ans = false; - if (arg_count == pd_count) - ans = Invocation.VerifyArgumentsCompat ( - ec, args, arg_count, mb, false, + return Invocation.VerifyArgumentsCompat ( + ec, args, arg_count, mb, + is_params_applicable || (!is_applicable && params_method), delegate_type, false, loc); - if (!ans && params_method) - ans = Invocation.VerifyArgumentsCompat ( - ec, args, arg_count, mb, true, - delegate_type, false, loc); - return ans; } /// /// 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, Type probe_type, Location loc) + public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Location loc) { Expression ml = Expression.MemberLookup ( - ec, delegate_type, "Invoke", loc); + ec.ContainerType, delegate_type, "Invoke", loc); if (!(ml is MethodGroupExpr)) { Report.Error (-100, loc, "Internal error: could not find Invoke method!"); @@ -543,10 +451,10 @@ namespace Mono.CSharp { } MethodBase mb = ((MethodGroupExpr) ml).Methods [0]; - ParameterData pd = Invocation.GetParameterData (mb); + ParameterData pd = TypeManager.GetParameterData (mb); Expression probe_ml = Expression.MemberLookup ( - ec, delegate_type, "Invoke", loc); + ec.ContainerType, delegate_type, "Invoke", loc); if (!(probe_ml is MethodGroupExpr)) { Report.Error (-100, loc, "Internal error: could not find Invoke method!"); @@ -554,7 +462,7 @@ namespace Mono.CSharp { } MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0]; - ParameterData probe_pd = Invocation.GetParameterData (probe_mb); + ParameterData probe_pd = TypeManager.GetParameterData (probe_mb); if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType) return false; @@ -575,24 +483,12 @@ namespace Mono.CSharp { public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd) { - StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType)); - - sb.Append (" " + del_type.ToString ()); - sb.Append (" ("); - - int length = pd.Count; - - for (int i = length; i > 0; ) { - i--; - - sb.Append (pd.ParameterDesc (length - i - 1)); - if (i != 0) - sb.Append (", "); - } - - sb.Append (")"); - return sb.ToString (); - + 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 @@ -652,12 +548,6 @@ namespace Mono.CSharp { } } - public Type [] ParameterTypes { - get { - return param_types; - } - } - public override AttributeTargets AttributeTargets { get { return AttributeTargets.Delegate; @@ -671,14 +561,6 @@ namespace Mono.CSharp { get { return "T:"; } } - protected override void VerifyObsoleteAttribute() - { - CheckUsageOfObsoleteAttribute (ret_type); - - foreach (Type type in param_types) { - CheckUsageOfObsoleteAttribute (type); - } - } } // @@ -690,26 +572,31 @@ namespace Mono.CSharp { protected MethodGroupExpr method_group; protected Expression delegate_instance_expression; - public DelegateCreation () {} + protected DelegateCreation () {} public static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc) { string method_desc; + MethodInfo found_method = (MethodInfo)mg.Methods [0]; if (mg.Methods.Length > 1) - method_desc = mg.Methods [0].Name; + method_desc = found_method.Name; else - method_desc = Invocation.FullMethodDesc (mg.Methods [0]); + method_desc = Invocation.FullMethodDesc (found_method); Expression invoke_method = Expression.MemberLookup ( - ec, type, "Invoke", MemberTypes.Method, + ec.ContainerType, type, "Invoke", MemberTypes.Method, Expression.AllBindingFlags, loc); - MethodBase method = ((MethodGroupExpr) invoke_method).Methods [0]; - ParameterData param = Invocation.GetParameterData (method); + MethodInfo method = ((MethodGroupExpr) invoke_method).Methods [0] as MethodInfo; + + ParameterData param = TypeManager.GetParameterData (method); string delegate_desc = Delegate.FullDelegateDesc (type, method, param); - - Report.Error (123, loc, "Method '" + method_desc + "' does not " + - "match delegate '" + delegate_desc + "'"); + + if (method.ReturnType != found_method.ReturnType) { + Report.Error (407, loc, "`{0}' has the wrong return type to match the delegate `{1}'", method_desc, delegate_desc); + } else { + Report.Error (123, loc, "Method `{0}' does not match delegate `{1}'", method_desc, delegate_desc); + } } public override void Emit (EmitContext ec) @@ -730,7 +617,7 @@ namespace Mono.CSharp { protected bool ResolveConstructorMethod (EmitContext ec) { Expression ml = Expression.MemberLookup ( - ec, type, ".ctor", loc); + ec.ContainerType, type, ".ctor", loc); if (!(ml is MethodGroupExpr)) { Report.Error (-100, loc, "Internal error: Could not find delegate constructor!"); @@ -741,14 +628,19 @@ namespace Mono.CSharp { return true; } - protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg) + public static MethodBase ImplicitStandardConversionExists (MethodGroupExpr mg, Type targetType) { foreach (MethodInfo mi in mg.Methods){ - delegate_method = Delegate.VerifyMethod (ec, type, mi, loc); - - if (delegate_method != null) - break; + MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, targetType, mi, Location.Null); + if (mb != null) + return mb; } + return null; + } + + protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg) + { + delegate_method = ImplicitStandardConversionExists (mg, type); if (delegate_method == null) { Error_NoMatchingMethodForDelegate (ec, mg, type, loc); @@ -759,7 +651,7 @@ namespace Mono.CSharp { // Check safe/unsafe of the delegate // if (!ec.InUnsafe){ - ParameterData param = Invocation.GetParameterData (delegate_method); + ParameterData param = TypeManager.GetParameterData (delegate_method); int count = param.Count; for (int i = 0; i < count; i++){ @@ -774,11 +666,16 @@ namespace Mono.CSharp { IMethodData md = TypeManager.GetMethod (delegate_method); if (md == null) { if (System.Attribute.GetCustomAttribute (delegate_method, TypeManager.conditional_attribute_type) != null) { - Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); + 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 { - if (md.OptAttributes != null && md.OptAttributes.Search (TypeManager.conditional_attribute_type, ec) != null) { - Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method)); + 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; } } @@ -786,9 +683,8 @@ namespace Mono.CSharp { delegate_instance_expression = mg.InstanceExpression.Resolve (ec); else if (ec.IsStatic) { if (!delegate_method.IsStatic) { - Report.Error (120, loc, - "An object reference is required for the non-static method " + - delegate_method.Name); + 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; @@ -796,7 +692,8 @@ namespace Mono.CSharp { delegate_instance_expression = ec.GetThis (loc); if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType) - delegate_instance_expression = new BoxedCast (delegate_instance_expression); + delegate_instance_expression = new BoxedCast ( + delegate_instance_expression, TypeManager.object_type); method_group = mg; eclass = ExprClass.Value; @@ -819,14 +716,15 @@ namespace Mono.CSharp { { return this; } - - static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc) + + 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 d.ResolveMethodGroupExpr (ec, mge); - else + if (!d.ResolveConstructorMethod (ec)) return null; + + return d.ResolveMethodGroupExpr (ec, mge); } } @@ -859,27 +757,25 @@ namespace Mono.CSharp { Argument a = (Argument) Arguments [0]; - if (!a.ResolveMethodGroup (ec, loc)) + if (!a.ResolveMethodGroup (ec)) return null; Expression e = a.Expr; if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1) - return ((AnonymousMethod) e).Compatible (ec, type, false); + return ((AnonymousMethod) e).Compatible (ec, type); MethodGroupExpr mg = e as MethodGroupExpr; if (mg != null) return ResolveMethodGroupExpr (ec, mg); - Type e_type = e.Type; - - if (!TypeManager.IsDelegateType (e_type)) { - e.Error_UnexpectedKind ("method", loc); + if (!TypeManager.IsDelegateType (e.Type)) { + Report.Error (149, loc, "Method name expected"); return null; } method_group = Expression.MemberLookup ( - ec, type, "Invoke", MemberTypes.Method, + ec.ContainerType, type, "Invoke", MemberTypes.Method, Expression.AllBindingFlags, loc) as MethodGroupExpr; if (method_group == null) { @@ -889,8 +785,8 @@ namespace Mono.CSharp { // 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, e_type, loc)) { - Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " + + if (!Delegate.VerifyDelegate (ec, type, loc)) { + Report.Error (29, loc, "Cannot implicitly convert type '" + e.Type + "' " + "to type '" + type + "'"); return null; } @@ -924,7 +820,7 @@ namespace Mono.CSharp { EventInfo ei = ((EventExpr) InstanceExpr).EventInfo; Expression ml = MemberLookup ( - ec, ec.ContainerType, ei.Name, + ec.ContainerType, ec.ContainerType, ei.Name, MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc); if (ml == null) { @@ -958,7 +854,7 @@ namespace Mono.CSharp { if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc)) return null; - Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc); + Expression lookup = Expression.MemberLookup (ec.ContainerType, del_type, "Invoke", loc); if (!(lookup is MethodGroupExpr)) { Report.Error (-100, loc, "Internal error: could not find Invoke method!"); return null;