Example #1
0
        public bool VerifyArgumentsCompat(ResolveContext ec, ref Arguments arguments,
            int arg_count, MethodSpec method,
            bool chose_params_expanded,
            bool may_fail, Location loc)
        {
            AParametersCollection pd = method.Parameters;
            int param_count = GetApplicableParametersCount (method, pd);

            int errors = ec.Report.Errors;
            Parameter.Modifier p_mod = 0;
            TypeSpec pt = null;
            int a_idx = 0, a_pos = 0;
            Argument a = null;
            ArrayInitializer params_initializers = null;
            bool has_unsafe_arg = method.ReturnType.IsPointer;

            for (; a_idx < arg_count; a_idx++, ++a_pos) {
                a = arguments [a_idx];
                if (p_mod != Parameter.Modifier.PARAMS) {
                    p_mod = pd.FixedParameters [a_idx].ModFlags;
                    pt = pd.Types [a_idx];
                    has_unsafe_arg |= pt.IsPointer;

                    if (p_mod == Parameter.Modifier.PARAMS) {
                        if (chose_params_expanded) {
                            params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location);
                            pt = TypeManager.GetElementType (pt);
                        }
                    }
                }

                //
                // Types have to be identical when ref or out modifer is used
                //
                if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) {
                    if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
                        break;

                    if (!TypeManager.IsEqual (a.Expr.Type, pt))
                        break;

                    continue;
                } else {
                    NamedArgument na = a as NamedArgument;
                    if (na != null) {
                        int name_index = pd.GetParameterIndexByName (na.Name);
                        if (name_index < 0 || name_index >= param_count) {
                            if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
                                ec.Report.SymbolRelatedToPreviousError (DeclaringType);
                                ec.Report.Error (1746, na.Location,
                                    "The delegate `{0}' does not contain a parameter named `{1}'",
                                    TypeManager.CSharpName (DeclaringType), na.Name);
                            } else {
                                ec.Report.SymbolRelatedToPreviousError (best_candidate);
                                ec.Report.Error (1739, na.Location,
                                    "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
                                    TypeManager.CSharpSignature (method), na.Name);
                            }
                        } else if (arguments[name_index] != a) {
                            if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
                                ec.Report.SymbolRelatedToPreviousError (DeclaringType);
                            else
                                ec.Report.SymbolRelatedToPreviousError (best_candidate);

                            ec.Report.Error (1744, na.Location,
                                "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
                                na.Name);
                        }
                    }
                }

                if (a.Expr.Type == InternalType.Dynamic)
                    continue;

                if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
                    break;

                Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
                if (conv == null)
                    break;

                //
                // Convert params arguments to an array initializer
                //
                if (params_initializers != null) {
                    // we choose to use 'a.Expr' rather than 'conv' so that
                    // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
                    params_initializers.Add (a.Expr);
                    arguments.RemoveAt (a_idx--);
                    --arg_count;
                    continue;
                }

                // Update the argument with the implicit conversion
                a.Expr = conv;
            }

            if (a_idx != arg_count) {
                if (!may_fail && ec.Report.Errors == errors) {
                    if (CustomErrorHandler != null)
                        CustomErrorHandler.NoExactMatch (ec, best_candidate);
                    else
                        Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
                }
                return false;
            }

            //
            // Fill not provided arguments required by params modifier
            //
            if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
                if (arguments == null)
                    arguments = new Arguments (1);

                pt = pd.Types [param_count - 1];
                pt = TypeManager.GetElementType (pt);
                has_unsafe_arg |= pt.IsPointer;
                params_initializers = new ArrayInitializer (0, loc);
            }

            //
            // Append an array argument with all params arguments
            //
            if (params_initializers != null) {
                arguments.Add (new Argument (
                    new ArrayCreation (new TypeExpression (pt, loc), "[]", params_initializers, loc).Resolve (ec)));
                arg_count++;
            }

            if (arg_count < param_count) {
                if (!may_fail)
                    Error_ArgumentCountWrong (ec, arg_count);
                return false;
            }

            if (has_unsafe_arg && !ec.IsUnsafe) {
                if (!may_fail)
                    UnsafeError (ec, loc);
                return false;
            }

            return true;
        }