2008-08-08 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / delegate.cs
index d7fc9e19cc454bcd5fcd98c7e3b03b44fe1a4c95..e0065e2dd7cb548de7776aa8168e08827799693a 100644 (file)
@@ -364,7 +364,8 @@ 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;
                }
@@ -446,20 +447,23 @@ namespace Mono.CSharp {
                        return (MethodInfo) mg.Methods[0];
                }
 
+               //
+               // 15.2 Delegate compatibility
+               //
                public static bool IsTypeCovariant (Expression a, Type b)
                {
-                       Type a_type = a.Type;
-                       if (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;
 
-                       if (a.Type.IsValueType)
-                               return false;
-
-                       return Convert.ImplicitReferenceConversionCore (
-                               a, b);
+                       return Convert.ImplicitReferenceConversionExists (a, b);
                }
                
                /// <summary>
@@ -467,8 +471,7 @@ namespace Mono.CSharp {
                ///  Returns the method itself if okay and null if not.
                /// </summary>
                public static MethodBase VerifyMethod (Type container_type, Type delegate_type,
-                                                      MethodGroupExpr old_mg, MethodBase mb,
-                                                      Location loc)
+                                                      MethodGroupExpr old_mg, MethodBase mb)
                {
                        MethodInfo invoke_mb = GetInvokeMethod (container_type, delegate_type);
                        if (invoke_mb == null)
@@ -660,7 +663,7 @@ namespace Mono.CSharp {
                protected MethodGroupExpr method_group;
                protected Expression delegate_instance_expression;
 
-               ArrayList CreateDelegateMethodArguments (MethodInfo invoke_method)
+               public static ArrayList CreateDelegateMethodArguments (MethodInfo invoke_method, Location loc)
                {
                        ParameterData pd = TypeManager.GetParameterData (invoke_method);
                        ArrayList delegate_arguments = new ArrayList (pd.Count);
@@ -715,12 +718,14 @@ namespace Mono.CSharp {
                        method_group.DelegateType = type;
                        method_group.CustomErrorHandler = this;
 
-                       ArrayList arguments = CreateDelegateMethodArguments (invoke_method);
+                       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;
+                       Invocation.IsSpecialMethodInvocation (delegate_method, loc);
+
                        ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr;
                        if (emg != null) {
                                delegate_instance_expression = emg.ExtensionExpression;
@@ -749,15 +754,17 @@ namespace Mono.CSharp {
                        //
                        if (delegate_instance_expression != null)
                                return;
-                       
-                       if (method_group.InstanceExpression != null)
+
+                       if (method_group.InstanceExpression != null) {
                                delegate_instance_expression = method_group.InstanceExpression;
-                       else if (!delegate_method.IsStatic && !ec.IsStatic)
+                               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);
-
-                       if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType)
-                               delegate_instance_expression = new BoxedCast (
-                                       delegate_instance_expression, TypeManager.object_type);
+                       }
                }
                
                public override void Emit (EmitContext ec)
@@ -807,13 +814,22 @@ namespace Mono.CSharp {
                                return null;
 
                        foreach (MethodInfo mi in mg.Methods){
-                               MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, target_type, mg, mi, Location.Null);
+                               MethodBase mb = Delegate.VerifyMethod (mg.DeclaringType, target_type, mg, mi);
                                if (mb != null)
                                        return mb;
                        }
                        return null;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (delegate_instance_expression != null)
+                               delegate_instance_expression.MutateHoistedGenericType (storey);
+
+                       delegate_method = storey.MutateGenericMethod (delegate_method);
+                       constructor_method = storey.MutateConstructor (constructor_method);
+               }
+
                #region IErrorHandler Members
 
                public bool NoExactMatch (EmitContext ec, MethodBase method)
@@ -875,12 +891,15 @@ namespace Mono.CSharp {
                        Argument a = (Argument) Arguments [0];
                        if (!a.ResolveMethodGroup (ec))
                                return null;
-                       
+
                        Expression e = a.Expr;
-                       if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1) {
-                               e = ((AnonymousMethodExpression) e).Compatible (ec, type);
+
+                       AnonymousMethodExpression ame = e as AnonymousMethodExpression;
+                       if (ame != null && RootContext.Version != LanguageVersion.ISO_1) {
+                               e = ame.Compatible (ec, type);
                                if (e == null)
                                        return null;
+
                                return e.Resolve (ec);
                        }
 
@@ -907,7 +926,7 @@ namespace Mono.CSharp {
                                        TypeManager.GetFullNameSignature (delegate_method));
                        }
 
-                       if (Invocation.IsMethodExcluded (delegate_method)) {
+                       if (Invocation.IsMethodExcluded (delegate_method, loc)) {
                                Report.SymbolRelatedToPreviousError (delegate_method);
                                Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute",
                                        TypeManager.CSharpSignature (delegate_method));
@@ -927,7 +946,7 @@ namespace Mono.CSharp {
                readonly Expression InstanceExpr;
                readonly ArrayList  Arguments;
 
-               MethodBase method;
+               MethodInfo method;
                
                public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
                {
@@ -975,8 +994,7 @@ namespace Mono.CSharp {
                                return null;
 
                        method = Delegate.GetInvokeMethod (ec.ContainerType, del_type);
-                       type = ((MethodInfo) method).ReturnType;
-                       type = TypeManager.TypeToCoreType (type);
+                       type = TypeManager.TypeToCoreType (method.ReturnType);
                        eclass = ExprClass.Value;
                        
                        return this;
@@ -997,12 +1015,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);
+               }
        }
 }