@@ -430,7 +430,10 @@ enum rejection_reason_code {
rr_none,
rr_arity,
rr_arg_conversion,
- rr_bad_arg_conversion
+ rr_bad_arg_conversion,
+ rr_template_unification,
+ rr_template_instantiation,
+ rr_invalid_copy
};
struct conversion_info {
@@ -458,6 +461,8 @@ struct rejection_reason {
struct conversion_info conversion;
/* Same, but for bad argument conversions. */
struct conversion_info bad_conversion;
+ /* Information about template unification failures. */
+ struct unification_info template_unification;
} u;
};
@@ -607,6 +612,28 @@ bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
return r;
}
+static struct rejection_reason *
+template_unification_rejection (struct unification_info *ui)
+{
+ struct rejection_reason *r = alloc_rejection (rr_template_unification);
+ r->u.template_unification = *ui;
+ return r;
+}
+
+static struct rejection_reason *
+template_instantiation_rejection (void)
+{
+ struct rejection_reason *r = alloc_rejection (rr_template_instantiation);
+ return r;
+}
+
+static struct rejection_reason *
+invalid_copy_with_fn_template_rejection (void)
+{
+ struct rejection_reason *r = alloc_rejection (rr_invalid_copy);
+ return r;
+}
+
/* Dynamically allocate a conversion. */
static conversion *
@@ -2844,6 +2871,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
int i;
tree fn;
struct rejection_reason *reason = NULL;
+ struct unification_info ui;
+
+ ui.result = ur_unknown;
/* We don't do deduction on the in-charge parameter, the VTT
parameter or 'this'. */
@@ -2889,14 +2919,20 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
nargs_without_in_chrg,
- return_type, strict, flags);
+ return_type, strict, flags, &ui);
if (i != 0)
- goto fail;
+ {
+ reason = template_unification_rejection (&ui);
+ goto fail;
+ }
fn = instantiate_template (tmpl, targs, tf_none);
if (fn == error_mark_node)
- goto fail;
+ {
+ reason = template_instantiation_rejection ();
+ goto fail;
+ }
/* In [class.copy]:
@@ -2925,7 +2961,10 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
- goto fail;
+ {
+ reason = invalid_copy_with_fn_template_rejection ();
+ goto fail;
+ }
}
if (obj != NULL_TREE)
@@ -3088,6 +3127,112 @@ print_conversion_rejection (location_t loc, struct conversion_info *info)
info->n_arg+1, info->from_type, info->to_type);
}
+/* Print information about a candidate with WANT parameters and we found
+ HAVE. */
+
+static void
+print_arity_information (location_t loc, unsigned int have, unsigned int want)
+{
+ inform_n (loc, want,
+ " candidate expects %d argument, %d provided",
+ " candidate expects %d arguments, %d provided",
+ want, have);
+}
+
+/* Print information about a candidate being rejected due to UI. */
+
+static void
+print_template_unification_rejection (location_t loc,
+ struct unification_info *ui)
+{
+ switch (ui->result)
+ {
+ case ur_invalid_arg:
+ case ur_invalid_parm:
+ case ur_invalid_init_list:
+ case ur_invalid_template_parm:
+ inform (loc, " an error occurred during template argument deduction");
+ break;
+ case ur_unification_inconsistency:
+ inform (loc,
+ " deduced conflicting types for parameter %qT (%qT and %qT)",
+ ui->u.inconsistent.template_parm,
+ ui->u.inconsistent.earlier,
+ ui->u.inconsistent.later);
+ break;
+ case ur_cv_qual_mismatch:
+ inform (loc,
+ " types %qT and %qT differ in their qualifiers",
+ ui->u.mismatch.parm,
+ ui->u.mismatch.arg);
+ break;
+ case ur_type_mismatch:
+ case ur_pointer_mismatch:
+ case ur_reference_mismatch:
+ inform (loc, " mismatched types %qT and %qT",
+ ui->u.mismatch.parm,
+ ui->u.mismatch.arg);
+ break;
+ case ur_vla_arg:
+ inform (loc, " variable-sized array type %qT is not permitted",
+ ui->u.vla_arg.array_type);
+ break;
+ case ur_too_many_parameters:
+ case ur_too_few_parameters:
+ print_arity_information (loc, ui->u.arity.have, ui->u.arity.wanted);
+ break;
+ case ur_arg_conversion:
+ inform (loc, " cannot convert %qE (type %qT) to type %qT",
+ ui->u.arg_conversion.arg, ui->u.arg_conversion.from_type,
+ ui->u.arg_conversion.to_type);
+ break;
+ case ur_expanding_pack_to_fixed_arg_list:
+ if (TREE_CODE (ui->u.expanding_pack.arg) == EXPR_PACK_EXPANSION)
+ inform (loc, " cannot expand %<%E%> into a fixed-length argument list",
+ ui->u.expanding_pack.arg);
+ else
+ inform (loc, " cannot expand %<%T%> into a fixed-length argument list",
+ ui->u.expanding_pack.arg);
+ break;
+ case ur_no_common_base:
+ inform (loc, " %qT is not derived from %qT",
+ ui->u.common_base.arg, ui->u.common_base.potential_base);
+ break;
+ case ur_illformed_ptrmem_cst_expr:
+ inform (loc, " %qE is not a valid pointer-to-member of type %qT",
+ ui->u.illformed_ptrmem_cst.expr,
+ ui->u.illformed_ptrmem_cst.type);
+ break;
+ case ur_failure:
+ inform (loc, " couldn't deduce template argument %qD", ui->u.parm);
+ break;
+ case ur_substitution_failure:
+ inform (loc, " substitution failure");
+ break;
+ case ur_invalid_explicit_arg:
+ if (DECL_P (ui->u.invalid_explicit_arg.parm)
+ && DECL_NAME (ui->u.invalid_explicit_arg.parm))
+ inform (loc, " invalid explicit argument for template parameter %qD",
+ ui->u.invalid_explicit_arg.parm);
+ else
+ inform (loc, " invalid explicit argument for template parameter %d",
+ ui->u.invalid_explicit_arg.parm_index + 1);
+ break;
+ case ur_unknown:
+ /* Template deduction and instantiation fails for a multitude of
+ reasons. In the worst case, don't print anything, as we might
+ not have caught all of the cases. */
+ break;
+ case ur_success:
+ /* We should never see this; it means we forgot to provide a
+ rejection reason someplace else (probably from template
+ instantiation). */
+ /* Fallthrough. */
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Print information about one overload candidate CANDIDATE. MSGSTR
is the text to print before the candidate itself.
@@ -3134,10 +3279,8 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
switch (r->code)
{
case rr_arity:
- inform_n (loc, r->u.arity.expected,
- " candidate expects %d argument, %d provided",
- " candidate expects %d arguments, %d provided",
- r->u.arity.expected, r->u.arity.actual);
+ print_arity_information (loc, r->u.arity.actual,
+ r->u.arity.expected);
break;
case rr_arg_conversion:
print_conversion_rejection (loc, &r->u.conversion);
@@ -3145,6 +3288,18 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
case rr_bad_arg_conversion:
print_conversion_rejection (loc, &r->u.bad_conversion);
break;
+ case rr_template_unification:
+ print_template_unification_rejection (loc,
+ &r->u.template_unification);
+ break;
+ case rr_template_instantiation:
+ inform (loc, " failed to instantiate template");
+ break;
+ case rr_invalid_copy:
+ inform (loc,
+ " cannot instantiate member function templates to "
+ "copy class objects to their class type");
+ break;
case rr_none:
default:
/* This candidate didn't have any issues or we failed to
@@ -6487,7 +6487,7 @@ resolve_address_of_overloaded_function (tree target_type,
targs = make_tree_vec (DECL_NTPARMS (fn));
if (fn_type_unification (fn, explicit_targs, targs, args, nargs,
target_ret_type, DEDUCE_EXACT,
- LOOKUP_NORMAL))
+ LOOKUP_NORMAL, NULL))
/* Argument deduction failed. */
continue;
@@ -5051,6 +5051,118 @@ extern tree locate_ctor (tree);
extern bool maybe_clone_body (tree);
/* in pt.c */
+/* Status codes for the result of unification. */
+enum unification_result {
+ /* Unification succeeded. */
+ ur_success = 0,
+ /* Unification failed for an unknown reason. */
+ ur_unknown,
+ ur_failure,
+ /* Error due to invalid argument. */
+ ur_invalid_arg,
+ /* Invalid template parameter. */
+ ur_invalid_parm,
+ /* Invalid init list. */
+ ur_invalid_init_list,
+ /* CV-qualification mismatch. */
+ ur_cv_qual_mismatch,
+ /* Invalid template parameter. */
+ ur_invalid_template_parm,
+ /* Unification resulted in a METHOD_TYPE. */
+ ur_method_type_result,
+ /* Argument is a parameter pack/expansion and parm isn't. */
+ ur_parameter_pack_mismatch,
+ /* Argument is a variable-sized array. */
+ ur_vla_arg,
+ /* Parameter is a pointer-to-member constant, arg isn't. */
+ ur_ptrmem_cst_mismatch,
+ /* Types of parameter and argument do not match. */
+ ur_type_mismatch,
+ /* Parameter is a pointer, arg isn't. */
+ ur_pointer_mismatch,
+ /* Parameter is a reference, arg isn't. */
+ ur_reference_mismatch,
+ /* Parameter is a constant, arg isn't. */
+ ur_constant_mismatch,
+ /* Parameter and argument are unequal constants. */
+ ur_constant_unequal,
+ /* Unequal expressions. */
+ ur_expression_unequal,
+ /* Unification of parameter packs produced inconsistencies. */
+ ur_parameter_pack_inconsistent,
+ /* Unification of earlier parameters produced inconsistencies with
+ later ones. */
+ ur_unification_inconsistency,
+ /* Too many parameters. */
+ ur_too_many_parameters,
+ /* Too few parameters. */
+ ur_too_few_parameters,
+ /* Failed argument conversion. */
+ ur_arg_conversion,
+ ur_expanding_pack_to_fixed_arg_list,
+ ur_no_common_base,
+ ur_illformed_ptrmem_cst_expr,
+ ur_substitution_failure,
+ ur_invalid_explicit_arg,
+};
+
+/* Information gathered during the unification process. */
+struct unification_info {
+ /* Status code. Also indicates which member of U, below, is valid. */
+ enum unification_result result;
+ union {
+ tree invalid; /* For ur_invalid_*. */
+ tree method_type_result; /* For ur_method_type_result. */
+ tree parm; /* For generic failure. */
+ /* For anything where we found differences between PARM and ARG. */
+ struct {
+ tree parm;
+ tree arg;
+ } mismatch;
+ /* For inconsistent unifications. */
+ struct {
+ tree template_parm;
+ tree earlier;
+ tree later;
+ } inconsistent;
+ /* For variably-sized array types appearing in templates. */
+ struct {
+ tree parm;
+ tree array_type;
+ } vla_arg;
+ /* For arity issues. */
+ struct {
+ unsigned int have;
+ unsigned int wanted;
+ } arity;
+ /* For ur_arg_conversion. */
+ struct {
+ tree to_type;
+ tree from_type;
+ tree arg;
+ } arg_conversion;
+ /* For ur_expanding_pack_to_fixed_arg_list. */
+ struct {
+ tree arg;
+ } expanding_pack;
+ /* For ur_no_common_base. */
+ struct {
+ tree potential_base;
+ tree arg;
+ } common_base;
+ struct {
+ tree expr;
+ tree type;
+ } illformed_ptrmem_cst;
+ struct {
+ tree parm;
+ /* We ought to be able to get this from TEMPLATE_PARM_IDX
+ (DECL_INITIAL (parm)), but parm might not be a decl. */
+ int parm_index;
+ } invalid_explicit_arg;
+ } u;
+};
+
extern bool check_template_shadow (tree);
extern tree get_innermost_template_args (tree, int);
extern void maybe_begin_member_template_processing (tree);
@@ -5089,7 +5201,8 @@ extern tree instantiate_class_template (tree);
extern tree instantiate_template (tree, tree, tsubst_flags_t);
extern int fn_type_unification (tree, tree, tree,
const tree *, unsigned int,
- tree, unification_kind_t, int);
+ tree, unification_kind_t, int,
+ struct unification_info *);
extern void mark_decl_instantiated (tree, int);
extern int more_specialized_fn (tree, tree, int);
extern void do_decl_instantiation (tree, tree);
@@ -112,16 +112,19 @@ static GTY(()) VEC(tree,gc) *canonical_template_parms;
static void push_access_scope (tree);
static void pop_access_scope (tree);
static bool resolve_overloaded_unification (tree, tree, tree, tree,
- unification_kind_t, int);
+ unification_kind_t, int,
+ struct unification_info *);
static int try_one_overload (tree, tree, tree, tree, tree,
- unification_kind_t, int, bool);
-static int unify (tree, tree, tree, tree, int);
+ unification_kind_t, int, bool,
+ struct unification_info *);
+static int unify (tree, tree, tree, tree, int, struct unification_info *);
static void add_pending_template (tree);
static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
- bool, bool);
+ bool, bool,
+ struct unification_info *);
static void tsubst_enum (tree, tree, tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
@@ -129,12 +132,15 @@ static bool check_instantiated_args (tree, tree, tsubst_flags_t);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
static int type_unification_real (tree, tree, tree, const tree *,
- unsigned int, int, unification_kind_t, int);
+ unsigned int, int, unification_kind_t, int,
+ struct unification_info *ui);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree);
-static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
+static tree convert_nontype_argument (tree, tree, tsubst_flags_t,
+ struct unification_info *);
static tree convert_template_argument (tree, tree, tree,
- tsubst_flags_t, int, tree);
+ tsubst_flags_t, int, tree,
+ struct unification_info *);
static int for_each_template_parm (tree, tree_fn_t, void*,
struct pointer_set_t*, bool);
static tree expand_template_argument_pack (tree);
@@ -154,7 +160,9 @@ static tree get_bindings (tree, tree, tree, bool);
static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static void template_parm_level_and_index (tree, int*, int*);
-static int unify_pack_expansion (tree, tree, tree, tree, int, bool, bool);
+static int unify_pack_expansion (tree, tree, tree,
+ tree, int, bool, bool,
+ struct unification_info *);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
@@ -166,8 +174,10 @@ static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
static void set_current_access_from_decl (tree);
-static tree get_template_base (tree, tree, tree, tree);
-static tree try_class_unification (tree, tree, tree, tree);
+static tree get_template_base (tree, tree, tree, tree,
+ struct unification_info *);
+static tree try_class_unification (tree, tree, tree, tree,
+ struct unification_info *);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
static bool template_template_parm_bindings_ok_p (tree, tree);
@@ -5265,6 +5275,237 @@ has_value_dependent_address (tree op)
return false;
}
+static int
+unify_success (struct unification_info *ui)
+{
+ if (ui)
+ ui->result = ur_success;
+ return 0;
+}
+
+static int
+unify_unknown (struct unification_info *ui)
+{
+ if (ui)
+ ui->result = ur_unknown;
+ return 1;
+}
+
+static int
+unify_failure (struct unification_info *ui, tree parm)
+{
+ if (ui)
+ {
+ ui->result = ur_failure;
+ ui->u.parm = parm;
+ }
+ return 1;
+}
+
+static int
+unify_invalid (enum unification_result ur, struct unification_info *ui)
+{
+ if (ui)
+ ui->result = ur;
+ return 1;
+}
+
+static int
+unify_method_type_result (struct unification_info *ui, tree t)
+{
+ if (ui)
+ {
+ ui->result = ur_method_type_result;
+ ui->u.method_type_result = t;
+ }
+ return 1;
+}
+
+static int
+unify_mismatch_1 (enum unification_result ur, struct unification_info *ui,
+ tree parm, tree arg)
+{
+ if (ui)
+ {
+ ui->result = ur;
+ ui->u.mismatch.parm = parm;
+ ui->u.mismatch.arg = arg;
+ }
+ return 1;
+}
+
+static int
+unify_cv_qual_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_cv_qual_mismatch, ui, parm, arg);
+}
+
+static int
+unify_type_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_type_mismatch, ui, parm, arg);
+}
+
+static int
+unify_parameter_pack_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_parameter_pack_mismatch, ui, parm, arg);
+}
+
+static int
+unify_parameter_pack_inconsistent (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_parameter_pack_inconsistent, ui, parm, arg);
+}
+
+static int
+unify_ptrmem_cst_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_ptrmem_cst_mismatch, ui, parm, arg);
+}
+
+static int
+unify_pointer_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_pointer_mismatch, ui, parm, arg);
+}
+
+static int
+unify_reference_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_reference_mismatch, ui, parm, arg);
+}
+
+static int
+unify_constant_mismatch (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_constant_mismatch, ui, parm, arg);
+}
+
+static int
+unify_constant_unequal (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_constant_unequal, ui, parm, arg);
+}
+
+static int
+unify_expression_unequal (struct unification_info *ui, tree parm, tree arg)
+{
+ return unify_mismatch_1 (ur_expression_unequal, ui, parm, arg);
+}
+
+static int
+unify_inconsistency (struct unification_info *ui, tree parm,
+ tree first, tree second)
+{
+ if (ui)
+ {
+ ui->result = ur_unification_inconsistency;
+ ui->u.inconsistent.template_parm = parm;
+ ui->u.inconsistent.earlier = first;
+ ui->u.inconsistent.later = second;
+ }
+ return 1;
+}
+
+static int
+unify_vla_arg (struct unification_info *ui, tree parm, tree arg)
+{
+ if (ui)
+ {
+ ui->result = ur_vla_arg;
+ ui->u.vla_arg.parm = parm;
+ ui->u.vla_arg.array_type = arg;
+ }
+ return 1;
+}
+
+static int
+unify_too_many_parameters (struct unification_info *ui, unsigned int have,
+ unsigned int wanted)
+{
+ if (ui)
+ {
+ ui->result = ur_too_many_parameters;
+ ui->u.arity.have = have;
+ ui->u.arity.wanted = wanted;
+ }
+ return 1;
+}
+
+static int
+unify_too_few_parameters (struct unification_info *ui, unsigned int have,
+ unsigned int wanted)
+{
+ if (ui)
+ {
+ ui->result = ur_too_few_parameters;
+ ui->u.arity.have = have;
+ ui->u.arity.wanted = wanted;
+ }
+ return 1;
+}
+
+static int
+unify_arg_conversion (struct unification_info *ui, tree to_type,
+ tree from_type, tree arg)
+{
+ if (ui)
+ {
+ ui->result = ur_arg_conversion;
+ ui->u.arg_conversion.to_type = to_type;
+ ui->u.arg_conversion.from_type = from_type;
+ ui->u.arg_conversion.arg = arg;
+ }
+ return 1;
+}
+
+static int
+unify_no_common_base (struct unification_info *ui, tree parm, tree arg)
+{
+ if (ui)
+ {
+ ui->result = ur_no_common_base;
+ ui->u.common_base.potential_base = parm;
+ ui->u.common_base.arg = arg;
+ }
+ return 1;
+}
+
+static int
+unify_illformed_ptrmem_cst_expr (struct unification_info *ui,
+ tree expr, tree type)
+{
+ if (ui)
+ {
+ ui->result = ur_illformed_ptrmem_cst_expr;
+ ui->u.illformed_ptrmem_cst.expr = expr;
+ ui->u.illformed_ptrmem_cst.type = type;
+ }
+ return 1;
+}
+
+static int
+unify_substitution_failure (struct unification_info *ui)
+{
+ if (ui)
+ ui->result = ur_substitution_failure;
+ return 1;
+}
+
+static int
+unify_invalid_explicit_argument (struct unification_info *ui, tree parm,
+ int parm_index)
+{
+ if (ui)
+ {
+ ui->result = ur_invalid_explicit_arg;
+ ui->u.invalid_explicit_arg.parm = parm;
+ ui->u.invalid_explicit_arg.parm_index = parm_index;
+ }
+ return 1;
+}
+
/* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return
@@ -5286,7 +5527,8 @@ has_value_dependent_address (tree op)
hacks can go away after we fix the double coercion problem. */
static tree
-convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
+convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain,
+ struct unification_info *ui)
{
tree expr_type;
@@ -5610,7 +5852,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
/* [temp.arg.nontype] bullet 1 says the pointer to member
expression must be a pointer-to-member constant. */
if (!check_valid_ptrmem_cst_expr (type, expr, complain))
- return error_mark_node;
+ {
+ unify_illformed_ptrmem_cst_expr (ui, expr, type);
+ return error_mark_node;
+ }
/* There is no way to disable standard conversions in
resolve_address_of_overloaded_function (called by
@@ -5642,7 +5887,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
/* [temp.arg.nontype] bullet 1 says the pointer to member
expression must be a pointer-to-member constant. */
if (!check_valid_ptrmem_cst_expr (type, expr, complain))
- return error_mark_node;
+ {
+ unify_illformed_ptrmem_cst_expr (ui, expr, type);
+ return error_mark_node;
+ }
expr = perform_qualification_conversions (type, expr);
if (expr == error_mark_node)
@@ -5927,7 +6175,8 @@ convert_template_argument (tree parm,
tree args,
tsubst_flags_t complain,
int i,
- tree in_decl)
+ tree in_decl,
+ struct unification_info *ui)
{
tree orig_arg;
tree val;
@@ -6120,7 +6369,7 @@ convert_template_argument (tree parm,
conversions can occur is part of determining which
function template to call, or whether a given explicit
argument specification is valid. */
- val = convert_nontype_argument (t, orig_arg, complain);
+ val = convert_nontype_argument (t, orig_arg, complain, ui);
else
val = orig_arg;
@@ -6156,7 +6405,8 @@ coerce_template_parameter_pack (tree parms,
tree new_args,
int* lost,
tree in_decl,
- tsubst_flags_t complain)
+ tsubst_flags_t complain,
+ struct unification_info *ui)
{
tree parm = TREE_VEC_ELT (parms, parm_idx);
int nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
@@ -6238,7 +6488,7 @@ coerce_template_parameter_pack (tree parms,
if (arg != error_mark_node)
arg = convert_template_argument (actual_parm,
arg, new_args, complain, parm_idx,
- in_decl);
+ in_decl, ui);
if (arg == error_mark_node)
(*lost)++;
TREE_VEC_ELT (packed_args, arg_idx - parm_idx) = arg;
@@ -6281,7 +6531,8 @@ coerce_template_parms (tree parms,
tree in_decl,
tsubst_flags_t complain,
bool require_all_args,
- bool use_default_args)
+ bool use_default_args,
+ struct unification_info *ui)
{
int nparms, nargs, parm_idx, arg_idx, lost = 0;
tree inner_args;
@@ -6343,6 +6594,13 @@ coerce_template_parms (tree parms,
if (in_decl)
error ("provided for %q+D", in_decl);
}
+ else
+ {
+ if (nargs > nparms)
+ unify_too_many_parameters (ui, nargs, nparms);
+ else
+ unify_too_few_parameters (ui, nargs, nparms);
+ }
return error_mark_node;
}
@@ -6359,6 +6617,7 @@ coerce_template_parms (tree parms,
{
tree arg;
tree parm;
+ int last_lost = lost;
/* Get the Ith template parameter. */
parm = TREE_VEC_ELT (parms, parm_idx);
@@ -6383,7 +6642,7 @@ coerce_template_parms (tree parms,
arg = coerce_template_parameter_pack (parms, parm_idx, args,
inner_args, arg_idx,
new_args, &lost,
- in_decl, complain);
+ in_decl, complain, ui);
/* Store this argument. */
if (arg == error_mark_node)
@@ -6446,10 +6705,12 @@ coerce_template_parms (tree parms,
else
arg = convert_template_argument (TREE_VALUE (parm),
arg, new_args, complain,
- parm_idx, in_decl);
+ parm_idx, in_decl, ui);
if (arg == error_mark_node)
lost++;
+ if (last_lost == 0 && lost)
+ unify_invalid_explicit_argument (ui, TREE_VALUE (parm), parm_idx);
TREE_VEC_ELT (new_inner_args, arg_idx) = arg;
}
cp_unevaluated_operand = saved_unevaluated_operand;
@@ -6806,7 +7067,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
arglist2 = coerce_template_parms (parmlist, arglist, templ,
complain,
/*require_all_args=*/true,
- /*use_default_args=*/true);
+ /*use_default_args=*/true, NULL);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
&& check_instantiated_args (templ, arglist2, complain)))
@@ -6879,7 +7140,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
arglist, gen_tmpl,
complain,
/*require_all_args=*/true,
- /*use_default_args=*/true);
+ /*use_default_args=*/true, NULL);
else
/* Outer levels should have already been coerced. */
a = TMPL_ARGS_LEVEL (arglist, i);
@@ -6913,7 +7174,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
gen_tmpl,
complain,
/*require_all_args=*/true,
- /*use_default_args=*/true);
+ /*use_default_args=*/true, NULL);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
@@ -13685,7 +13946,8 @@ fn_type_unification (tree fn,
unsigned int nargs,
tree return_type,
unification_kind_t strict,
- int flags)
+ int flags,
+ struct unification_info *ui)
{
tree parms;
tree fntype;
@@ -13725,7 +13987,7 @@ fn_type_unification (tree fn,
converted_args
= (coerce_template_parms (tparms, explicit_targs, NULL_TREE, tf_none,
/*require_all_args=*/false,
- /*use_default_args=*/false));
+ /*use_default_args=*/false, ui));
if (converted_args == error_mark_node)
return 1;
@@ -13788,7 +14050,7 @@ fn_type_unification (tree fn,
processing_template_decl -= incomplete;
if (fntype == error_mark_node)
- return 1;
+ return unify_substitution_failure (ui);
/* Place the explicitly specified arguments in TARGS. */
for (i = NUM_TMPL_ARGS (converted_args); i--;)
@@ -13816,7 +14078,7 @@ fn_type_unification (tree fn,
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, nargs, /*subr=*/0,
- strict, flags);
+ strict, flags, ui);
/* Now that we have bindings for all of the template arguments,
ensure that the arguments deduced for the template template
@@ -13842,7 +14104,7 @@ fn_type_unification (tree fn,
if (result == 0
&& !template_template_parm_bindings_ok_p
(DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
- return 1;
+ return unify_unknown (ui);
if (result == 0)
/* All is well so far. Now, check:
@@ -13857,7 +14119,7 @@ fn_type_unification (tree fn,
{
tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
if (substed == error_mark_node)
- return 1;
+ return unify_substitution_failure (ui);
/* If we're looking for an exact match, check that what we got
is indeed an exact match. It might not be if some template
@@ -13872,7 +14134,7 @@ fn_type_unification (tree fn,
sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
if (!same_type_p (args[i], TREE_VALUE (sarg)))
- return 1;
+ return unify_unknown (ui);
}
}
@@ -14003,7 +14265,8 @@ type_unification_real (tree tparms,
unsigned int xnargs,
int subr,
unification_kind_t strict,
- int flags)
+ int flags,
+ struct unification_info *ui)
{
tree parm, arg, arg_expr;
int i;
@@ -14061,7 +14324,7 @@ type_unification_real (tree tparms,
arg_expr = NULL;
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_arg, ui);
if (arg == unknown_type_node)
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
@@ -14087,7 +14350,7 @@ type_unification_real (tree tparms,
flags))
continue;
- return 1;
+ return unify_arg_conversion (ui, parm, type, arg);
}
if (!TYPE_P (arg))
@@ -14103,15 +14366,15 @@ type_unification_real (tree tparms,
function templates and at most one of a set of
overloaded functions provides a unique match. */
if (resolve_overloaded_unification
- (tparms, targs, parm, arg, strict, sub_strict))
+ (tparms, targs, parm, arg, strict, sub_strict, ui))
continue;
- return 1;
+ return unify_unknown (ui);
}
arg_expr = arg;
arg = unlowered_expr_type (arg);
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_arg, ui);
}
{
@@ -14123,7 +14386,9 @@ type_unification_real (tree tparms,
if (arg == init_list_type_node && arg_expr)
arg = arg_expr;
- if (unify (tparms, targs, parm, arg, arg_strict))
+ if (unify (tparms, targs, parm, arg, arg_strict, ui))
+ /* If unification failed, the recursive call will have updated
+ UI appropriately. */
return 1;
}
}
@@ -14145,7 +14410,7 @@ type_unification_real (tree tparms,
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
- /*call_args_p=*/true, /*subr=*/subr))
+ /*call_args_p=*/true, /*subr=*/subr, ui))
return 1;
/* Advance to the end of the list of parameters. */
@@ -14155,11 +14420,20 @@ type_unification_real (tree tparms,
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
if (ia < nargs && parms == void_list_node)
- return 1;
+ return unify_too_many_parameters (ui, nargs, ia);
/* Fail if parms are left and they don't have default values. */
if (parms && parms != void_list_node
&& TREE_PURPOSE (parms) == NULL_TREE)
- return 1;
+ {
+ unsigned int count = nargs;
+ tree p = parms;
+ while (p && p != void_list_node)
+ {
+ count++;
+ p = TREE_CHAIN (p);
+ }
+ return unify_too_few_parameters (ui, ia, count);
+ }
if (!subr)
{
@@ -14215,9 +14489,9 @@ type_unification_real (tree tparms,
tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
arg = tsubst_template_arg (arg, targs, tf_none, NULL_TREE);
arg = convert_template_argument (parm, arg, targs, tf_none,
- i, NULL_TREE);
+ i, NULL_TREE, ui);
if (arg == error_mark_node)
- return 1;
+ return unify_failure (ui, tparm);
else
{
TREE_VEC_ELT (targs, i) = arg;
@@ -14251,7 +14525,7 @@ type_unification_real (tree tparms,
continue;
}
- return 2;
+ return unify_failure (ui, tparm);
}
}
#ifdef ENABLE_CHECKING
@@ -14259,7 +14533,7 @@ type_unification_real (tree tparms,
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
#endif
- return 0;
+ return unify_success (ui);
}
/* Subroutine of type_unification_real. Args are like the variables
@@ -14274,7 +14548,8 @@ resolve_overloaded_unification (tree tparms,
tree parm,
tree arg,
unification_kind_t strict,
- int sub_strict)
+ int sub_strict,
+ struct unification_info *ui)
{
tree tempargs = copy_node (targs);
int good = 0;
@@ -14325,7 +14600,7 @@ resolve_overloaded_unification (tree tparms,
{
elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
if (try_one_overload (tparms, targs, tempargs, parm,
- elem, strict, sub_strict, addr_p)
+ elem, strict, sub_strict, addr_p, ui)
&& (!goodfn || !decls_match (goodfn, elem)))
{
goodfn = elem;
@@ -14345,7 +14620,7 @@ resolve_overloaded_unification (tree tparms,
for (; arg; arg = OVL_NEXT (arg))
if (try_one_overload (tparms, targs, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
- strict, sub_strict, addr_p)
+ strict, sub_strict, addr_p, ui)
&& (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
{
goodfn = OVL_CURRENT (arg);
@@ -14491,7 +14766,8 @@ try_one_overload (tree tparms,
tree arg,
unification_kind_t strict,
int sub_strict,
- bool addr_p)
+ bool addr_p,
+ struct unification_info *ui)
{
int nargs;
tree tempargs;
@@ -14521,7 +14797,7 @@ try_one_overload (tree tparms,
nargs = TREE_VEC_LENGTH (targs);
tempargs = make_tree_vec (nargs);
- if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+ if (unify (tparms, tempargs, parm, arg, sub_strict, ui))
return 0;
/* First make sure we didn't deduce anything that conflicts with
@@ -14559,7 +14835,8 @@ try_one_overload (tree tparms,
TARGS are as for unify. */
static tree
-try_class_unification (tree tparms, tree targs, tree parm, tree arg)
+try_class_unification (tree tparms, tree targs, tree parm, tree arg,
+ struct unification_info *ui)
{
tree copy_of_targs;
@@ -14602,7 +14879,7 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg)
/* If unification failed, we're done. */
if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
+ CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, ui))
return NULL_TREE;
return arg;
@@ -14616,7 +14893,8 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg)
by unify. */
static tree
-get_template_base (tree tparms, tree targs, tree parm, tree arg)
+get_template_base (tree tparms, tree targs, tree parm, tree arg,
+ struct unification_info *ui)
{
tree rval = NULL_TREE;
tree binfo;
@@ -14632,7 +14910,8 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg)
important, and this avoids multiple walks of virtual bases. */
for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
{
- tree r = try_class_unification (tparms, targs, parm, BINFO_TYPE (binfo));
+ tree r = try_class_unification (tparms, targs, parm,
+ BINFO_TYPE (binfo), ui);
if (r)
{
@@ -14733,6 +15012,12 @@ template_parm_level_and_index (tree parm, int* level, int* index)
}
}
+#define RECUR_AND_CHECK_FAILURE(TP, TA, P, A, S, UI) \
+ do { \
+ if (unify (TP, TA, P, A, S, UI)) \
+ return 1; \
+ } while (0);
+
/* Unifies the remaining arguments in PACKED_ARGS with the pack
expansion at the end of PACKED_PARMS. Returns 0 if the type
deduction succeeds, 1 otherwise. STRICT is the same as in
@@ -14740,10 +15025,10 @@ template_parm_level_and_index (tree parm, int* level, int* index)
call argument list. We'll need to adjust the arguments to make them
types. SUBR tells us if this is from a recursive call to
type_unification_real. */
-int
+static int
unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
tree packed_args, int strict, bool call_args_p,
- bool subr)
+ bool subr, struct unification_info *ui)
{
tree parm
= TREE_VEC_ELT (packed_parms, TREE_VEC_LENGTH (packed_parms) - 1);
@@ -14833,7 +15118,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
if (resolve_overloaded_unification
(tparms, targs, parm, arg,
(unification_kind_t) strict,
- sub_strict)
+ sub_strict, ui)
!= 0)
return 1;
skip_arg_p = true;
@@ -14861,8 +15146,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
/* For deduction from an init-list we need the actual list. */
if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
arg = arg_expr;
- if (unify (tparms, targs, parm, arg, arg_strict))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, parm, arg, arg_strict, ui);
}
}
@@ -14956,10 +15240,10 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
else if (!comp_template_args (ARGUMENT_PACK_ARGS (old_pack),
new_args))
/* Inconsistent unification of this parameter pack. */
- return 1;
+ return unify_parameter_pack_inconsistent (ui, NULL_TREE, NULL_TREE);
}
- return 0;
+ return unify_success (ui);
}
/* Deduce the value of template parameters. TPARMS is the (innermost)
@@ -15004,7 +15288,8 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
qualified at this point. */
static int
-unify (tree tparms, tree targs, tree parm, tree arg, int strict)
+unify (tree tparms, tree targs, tree parm, tree arg, int strict,
+ struct unification_info *ui)
{
int idx;
tree targ;
@@ -15019,19 +15304,19 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
parm = TREE_OPERAND (parm, 0);
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_arg, ui);
if (arg == unknown_type_node
|| arg == init_list_type_node)
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
- return 0;
+ return unify_success (ui);
/* If PARM uses template parameters, then we can't bail out here,
even if ARG == PARM, since we won't record unifications for the
template parameters. We might need them if we're trying to
figure out which of two things is more specialized. */
if (arg == parm && !uses_template_parms (parm))
- return 0;
+ return unify_success (ui);
/* Handle init lists early, so the rest of the function can assume
we're dealing with a type. */
@@ -15050,7 +15335,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* We can only deduce from an initializer list argument if the
parameter is std::initializer_list; otherwise this is a
non-deduced context. */
- return 0;
+ return unify_success (ui);
elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
@@ -15059,7 +15344,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
int elt_strict = strict;
if (elt == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_init_list, ui);
if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
{
@@ -15071,8 +15356,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
elt = type;
}
- if (unify (tparms, targs, elttype, elt, elt_strict))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict, ui);
}
/* If the std::initializer_list<T> deduction worked, replace the
@@ -15084,7 +15368,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
targ = listify (targ);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
}
- return 0;
+ return unify_success (ui);
}
/* Immediately reject some pairs that won't unify because of
@@ -15101,7 +15385,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
is more specialized, for example. */
&& TREE_CODE (arg) != TEMPLATE_TYPE_PARM
&& !check_cv_quals_for_unify (strict_in, arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (ui, parm, arg);
if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
&& TYPE_P (parm) && !CP_TYPE_CONST_P (parm))
@@ -15119,19 +15403,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters used
within the nested-name-specifier. */
- return 0;
+ return unify_success (ui);
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
if (tparm == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_template_parm, ui);
if (TEMPLATE_TYPE_LEVEL (parm)
!= template_decl_level (tparm))
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
+ /* FIXME: What to return here? */
return (TREE_CODE (arg) == TREE_CODE (parm)
&& same_type_p (parm, arg)) ? 0 : 1;
idx = TEMPLATE_TYPE_IDX (parm);
@@ -15143,7 +15428,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
&& TREE_CODE (tparm) != TYPE_DECL)
|| (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (tparm) != TEMPLATE_DECL))
- return 1;
+ return unify_failure (ui);
if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
@@ -15151,7 +15436,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
&& !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
- return 1;
+ return unify_failure (ui);
{
tree parmvec = TYPE_TI_ARGS (parm);
@@ -15195,9 +15480,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
- /*use_default_args=*/false)
+ /*use_default_args=*/false, ui)
== error_mark_node)
- return 1;
+ /* FIXME: need to return something sane here. */
+ return unify_failure (ui);
/* Deduce arguments T, i from TT<T> or TT<i>.
We check each element of PARMVEC and ARGVEC individually
@@ -15216,15 +15502,14 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
parm_variadic_p = 1;
if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
- return 1;
+ return unify_failure (ui);
for (i = 0; i < len - parm_variadic_p; ++i)
{
- if (unify (tparms, targs,
- TREE_VEC_ELT (parmvec, i),
- TREE_VEC_ELT (argvec, i),
- UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (parmvec, i),
+ TREE_VEC_ELT (argvec, i),
+ UNIFY_ALLOW_NONE, ui);
}
if (parm_variadic_p
@@ -15232,8 +15517,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
parmvec, argvec,
UNIFY_ALLOW_NONE,
/*call_args_p=*/false,
- /*subr=*/false))
- return 1;
+ /*subr=*/false, ui))
+ return unify_failure (ui);
}
arg = TYPE_TI_TEMPLATE (arg);
@@ -15247,9 +15532,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* Simple cases: Value already set, does match or doesn't. */
if (targ != NULL_TREE && template_args_equal (targ, arg))
- return 0;
+ return unify_success (ui);
else if (targ)
- return 1;
+ return unify_inconsistency (ui, parm, targ, arg);
}
else
{
@@ -15259,20 +15544,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
that binds `const int' to `T'. */
if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (ui, parm, arg);
/* Consider the case where ARG is `const volatile int' and
PARM is `const T'. Then, T should be `volatile int'. */
arg = cp_build_qualified_type_real
(arg, cp_type_quals (arg) & ~cp_type_quals (parm), tf_none);
if (arg == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_arg, ui);
/* Simple cases: Value already set, does match or doesn't. */
if (targ != NULL_TREE && same_type_p (targ, arg))
- return 0;
+ return unify_success (ui);
else if (targ)
- return 1;
+ return unify_inconsistency (ui, parm, targ, arg);
/* Make sure that ARG is not a variable-sized array. (Note
that were talking about variable-sized arrays (like
@@ -15282,7 +15567,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
instantiation. Besides, such types are not allowed in
ISO C++, so we can do as we please here. */
if (variably_modified_type_p (arg, NULL_TREE))
- return 1;
+ return unify_vla_arg (ui, parm, arg);
/* Strip typedefs as in convert_template_argument. */
arg = strip_typedefs (arg);
@@ -15292,27 +15577,28 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
against it unless PARM is also a parameter pack. */
if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
&& !template_parameter_pack_p (parm))
- return 1;
+ return ur_parameter_pack_mismatch;
/* If the argument deduction results is a METHOD_TYPE,
then there is a problem.
METHOD_TYPE doesn't map to any real C++ type the result of
the deduction can not be of that type. */
if (TREE_CODE (arg) == METHOD_TYPE)
- return 1;
+ return unify_method_type_result (ui, arg);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
- return 0;
+ return unify_success (ui);
case TEMPLATE_PARM_INDEX:
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
if (tparm == error_mark_node)
- return 1;
+ return unify_invalid (ur_invalid_template_parm, ui);
if (TEMPLATE_PARM_LEVEL (parm)
!= template_decl_level (tparm))
/* The PARM is not one we're trying to unify. Just check
to see if it matches ARG. */
+ /* FIXME: What to return here? */
return !(TREE_CODE (arg) == TREE_CODE (parm)
&& cp_tree_equal (parm, arg));
@@ -15320,6 +15606,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
if (targ)
+ /* FIXME: what's the rationale here? */
return !cp_tree_equal (targ, arg);
/* [temp.deduct.type] If, in the declaration of a function template
@@ -15347,25 +15634,25 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
else if (uses_template_parms (tparm))
/* We haven't deduced the type of this parameter yet. Try again
later. */
- return 0;
+ return unify_success (ui);
else
- return 1;
+ return unify_failure (ui);
/* If ARG is a parameter pack or an expansion, we cannot unify
against it unless PARM is also a parameter pack. */
if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
&& !TEMPLATE_PARM_PARAMETER_PACK (parm))
- return 1;
+ return unify_parameter_pack_mismatch (ui, parm, arg);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
- return 0;
+ return unify_success (ui);
case PTRMEM_CST:
{
/* A pointer-to-member constant can be unified only with
another constant. */
if (TREE_CODE (arg) != PTRMEM_CST)
- return 1;
+ return unify_ptrmem_cst_mismatch (ui, parm, arg);
/* Just unify the class member. It would be useless (and possibly
wrong, depending on the strict flags) to unify also
@@ -15378,13 +15665,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
Unification of &A::x and &B::x must succeed. */
return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
- PTRMEM_CST_MEMBER (arg), strict);
+ PTRMEM_CST_MEMBER (arg), strict, ui);
}
case POINTER_TYPE:
{
if (TREE_CODE (arg) != POINTER_TYPE)
- return 1;
+ return unify_pointer_mismatch (ui, parm, arg);
/* [temp.deduct.call]
@@ -15402,21 +15689,21 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
strict |= (strict_in & UNIFY_ALLOW_DERIVED);
return unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), strict);
+ TREE_TYPE (arg), strict, ui);
}
case REFERENCE_TYPE:
if (TREE_CODE (arg) != REFERENCE_TYPE)
- return 1;
+ return unify_reference_mismatch (ui, parm, arg);
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict & UNIFY_ALLOW_MORE_CV_QUAL);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL, ui);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
if ((TYPE_DOMAIN (parm) == NULL_TREE)
!= (TYPE_DOMAIN (arg) == NULL_TREE))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
if (TYPE_DOMAIN (parm) != NULL_TREE)
{
tree parm_max;
@@ -15472,11 +15759,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
arg_max,
integer_one_node);
- if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, parm_max, arg_max,
+ UNIFY_ALLOW_INTEGER, ui);
}
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict & UNIFY_ALLOW_MORE_CV_QUAL);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL, ui);
case REAL_TYPE:
case COMPLEX_TYPE:
@@ -15486,16 +15773,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
case ENUMERAL_TYPE:
case VOID_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
/* We have already checked cv-qualification at the top of the
function. */
if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
/* As far as unification is concerned, this wins. Later checks
will invalidate it if necessary. */
- return 0;
+ return unify_success (ui);
/* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */
/* Type INTEGER_CST can come from ordinary constant template args. */
@@ -15504,8 +15791,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (arg) != INTEGER_CST)
- return 1;
- return !tree_int_cst_equal (parm, arg);
+ return unify_constant_mismatch (ui, parm, arg);
+ return (tree_int_cst_equal (parm, arg)
+ ? unify_success (ui)
+ : unify_constant_unequal (ui, parm, arg));
case TREE_VEC:
{
@@ -15515,27 +15804,27 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
return 1;
for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
- if (unify (tparms, targs,
- TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- UNIFY_ALLOW_NONE))
- return 1;
- return 0;
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (parm, i),
+ TREE_VEC_ELT (arg, i),
+ UNIFY_ALLOW_NONE, ui);
+ return unify_success (ui);
}
case RECORD_TYPE:
case UNION_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
if (TYPE_PTRMEMFUNC_P (parm))
{
if (!TYPE_PTRMEMFUNC_P (arg))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
return unify (tparms, targs,
TYPE_PTRMEMFUNC_FN_TYPE (parm),
TYPE_PTRMEMFUNC_FN_TYPE (arg),
- strict);
+ strict, ui);
}
if (CLASSTYPE_TEMPLATE_INFO (parm))
@@ -15546,7 +15835,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
/* First, we try to unify the PARM and ARG directly. */
t = try_class_unification (tparms, targs,
- parm, arg);
+ parm, arg, ui);
if (!t)
{
@@ -15559,10 +15848,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
a class of the form template-id, A can be a
pointer to a derived class pointed to by the
deduced A. */
- t = get_template_base (tparms, targs, parm, arg);
+ t = get_template_base (tparms, targs, parm, arg, ui);
+ /* FIXME: Is this clobbering information in UI? */
if (!t)
- return 1;
+ return unify_no_common_base (ui, parm, arg);
}
}
else if (CLASSTYPE_TEMPLATE_INFO (arg)
@@ -15573,14 +15863,14 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
t = arg;
else
/* There's no chance of unification succeeding. */
- return 1;
+ return unify_failure (ui);
return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
- CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
+ CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, ui);
}
else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
- return 1;
- return 0;
+ return unify_type_mismatch (ui, parm, arg);
+ return unify_success (ui);
case METHOD_TYPE:
case FUNCTION_TYPE:
@@ -15591,7 +15881,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
unsigned int i;
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ return unify_type_mismatch (ui, parm, arg);
/* CV qualifications for methods can never be deduced, they must
match exactly. We need to check them explicitly here,
@@ -15602,11 +15892,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
(UNIFY_ALLOW_NONE,
class_of_this_parm (arg),
class_of_this_parm (parm))))
- return 1;
+ return unify_cv_qual_mismatch (ui, parm, arg);
- if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE, ui);
nargs = list_length (TYPE_ARG_TYPES (arg));
args = XALLOCAVEC (tree, nargs);
@@ -15618,7 +15907,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
args, nargs, 1, DEDUCE_EXACT,
- LOOKUP_NORMAL);
+ LOOKUP_NORMAL, ui);
}
case OFFSET_TYPE:
@@ -15631,11 +15920,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* Check top-level cv qualifiers */
if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
- return 1;
+ return unify_cv_qual_mismatch (ui, parm, arg);
- if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_PTRMEMFUNC_OBJECT_TYPE (arg),
+ UNIFY_ALLOW_NONE, ui);
/* Determine the type of the function we are unifying against. */
method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
@@ -15647,28 +15936,28 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
implicit object parameter and place them on the function
type to be restored later. */
fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
- return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+ return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, ui);
}
if (TREE_CODE (arg) != OFFSET_TYPE)
- return 1;
- if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
+ return ur_type_mismatch;
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_OFFSET_BASETYPE (arg),
+ UNIFY_ALLOW_NONE, ui);
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- strict);
+ strict, ui);
case CONST_DECL:
if (DECL_TEMPLATE_PARM_P (parm))
- return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
+ return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, ui);
if (arg != integral_constant_value (parm))
- return 1;
- return 0;
+ return unify_constant_mismatch (ui, parm, arg);
+ return unify_success (ui);
case FIELD_DECL:
case TEMPLATE_DECL:
/* Matched cases are handled by the ARG == PARM test above. */
- return 1;
+ return unify_failure (ui);
case VAR_DECL:
/* A non-type template parameter that is a variable should be a
@@ -15698,7 +15987,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* Since there is something following the pack
expansion, we cannot unify this template argument
list. */
- return 0;
+ return unify_success (ui);
}
}
@@ -15709,23 +15998,24 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
a pack expression, we can't unify. */
if (argslen < (len - parm_variadic_p)
|| (argslen > len && !parm_variadic_p))
- return 1;
+ return unify_failure (ui);
/* Unify all of the parameters that precede the (optional)
pack expression. */
for (i = 0; i < len - parm_variadic_p; ++i)
{
- if (unify (tparms, targs, TREE_VEC_ELT (packed_parms, i),
- TREE_VEC_ELT (packed_args, i), strict))
- return 1;
+ RECUR_AND_CHECK_FAILURE (tparms, targs,
+ TREE_VEC_ELT (packed_parms, i),
+ TREE_VEC_ELT (packed_args, i),
+ strict, ui);
}
if (parm_variadic_p)
return unify_pack_expansion (tparms, targs,
packed_parms, packed_args,
strict, /*call_args_p=*/false,
- /*subr=*/false);
- return 0;
+ /*subr=*/false, ui);
+ return unify_success (ui);
}
break;
@@ -15735,11 +16025,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
case UNDERLYING_TYPE:
/* Cannot deduce anything from TYPEOF_TYPE, DECLTYPE_TYPE,
or UNDERLYING_TYPE nodes. */
- return 0;
+ return unify_success (ui);
case ERROR_MARK:
/* Unification fails if we hit an error node. */
- return 1;
+ return unify_invalid (ur_invalid_parm, ui);
default:
/* An unresolved overload is a nondeduced context. */
@@ -15768,11 +16058,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
if (!uses_template_parms (parm)
&& !template_args_equal (parm, arg))
- return 1;
+ return unify_expression_unequal (ui, parm, arg);
else
- return 0;
+ return unify_success (ui);
}
}
+#undef RECUR_AND_CHECK_FAILURE
/* Note that DECL can be defined in this translation unit, if
required. */
@@ -16035,10 +16326,11 @@ more_specialized_fn (tree pat1, tree pat2, int len)
for (i = 0; i < len2; i++, ta = TREE_CHAIN (ta))
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
- deduce1 = !unify_pack_expansion (tparms1, targs1, parmvec,
+ deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec,
argvec, UNIFY_ALLOW_NONE,
/*call_args_p=*/false,
- /*subr=*/0);
+ /*subr=*/0, NULL)
+ == 0);
/* We cannot deduce in the other direction, because ARG1 is
a pack expansion but ARG2 is not. */
@@ -16059,10 +16351,11 @@ more_specialized_fn (tree pat1, tree pat2, int len)
for (i = 0; i < len1; i++, ta = TREE_CHAIN (ta))
TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
- deduce2 = !unify_pack_expansion (tparms2, targs2, parmvec,
+ deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec,
argvec, UNIFY_ALLOW_NONE,
/*call_args_p=*/false,
- /*subr=*/0);
+ /*subr=*/0, NULL)
+ == 0);
/* We cannot deduce in the other direction, because ARG2 is
a pack expansion but ARG1 is not.*/
@@ -16073,8 +16366,12 @@ more_specialized_fn (tree pat1, tree pat2, int len)
{
/* The normal case, where neither argument is a pack
expansion. */
- deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE);
- deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
+ deduce1 = (unify (tparms1, targs1, arg1, arg2,
+ UNIFY_ALLOW_NONE, NULL)
+ == 0);
+ deduce2 = (unify (tparms2, targs2, arg2, arg1,
+ UNIFY_ALLOW_NONE, NULL)
+ == 0);
}
/* If we couldn't deduce arguments for tparms1 to make arg1 match
@@ -16264,7 +16561,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
explicit_args, NULL_TREE,
tf_none,
/*require_all_args=*/false,
- /*use_default_args=*/false);
+ /*use_default_args=*/false, NULL);
if (converted_args == error_mark_node)
return NULL_TREE;
@@ -16288,7 +16585,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, LOOKUP_NORMAL))
+ DEDUCE_EXACT, LOOKUP_NORMAL, NULL))
return NULL_TREE;
return targs;
@@ -16330,7 +16627,7 @@ get_class_bindings (tree tparms, tree spec_args, tree args)
if (unify (tparms, deduced_args,
INNERMOST_TEMPLATE_ARGS (spec_args),
INNERMOST_TEMPLATE_ARGS (args),
- UNIFY_ALLOW_NONE))
+ UNIFY_ALLOW_NONE, NULL))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
@@ -16567,7 +16864,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
partial_spec_args),
tmpl, tf_none,
/*require_all_args=*/true,
- /*use_default_args=*/true);
+ /*use_default_args=*/true, NULL);
--processing_template_decl;
@@ -19050,8 +19347,10 @@ do_auto_deduction (tree type, tree init, tree auto_node)
targs = make_tree_vec (1);
TREE_VEC_ELT (tparms, 0)
= build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+ /* FIXME: Should we pass in unification information and then use that
+ to elaborate on the error messages below? */
val = type_unification_real (tparms, targs, parms, args, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL);
+ DEDUCE_CALL, LOOKUP_NORMAL, NULL);
if (val > 0)
{
if (type && type != error_mark_node)
@@ -1,5 +1,6 @@
// { dg-options "-std=gnu++0x" }
template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
+// { dg-message "cannot convert" "overload failure" { target *-*-* } 2 }
{
union { T t; }; // { dg-error "not expanded with|T" }
return t;
@@ -8,5 +9,5 @@ template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
void bar()
{
foo(0); // { dg-error "no matching" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
}
new file mode 100644
@@ -0,0 +1,17 @@
+// { dg-do compile }
+
+template<typename T>
+int low(T a, T b, T c) { return a + b + c; } // { dg-message "template" }
+// { dg-message "expects 3 arguments, 2 provided" "arity" { target *-*-* } 4 }
+
+template<typename T>
+int high(T a, T b, T c) { return a + b + c; } // { dg-message "template" }
+// { dg-message "expects 3 arguments, 4 provided" "arity" { target *-*-* } 8 }
+
+int test (void)
+{
+ low (5, 6); // { dg-error "no matching function" }
+ // { dg-message "candidate" "" { target *-*-* } 13 }
+ high (5, 6, 7, 8); // { dg-error "no matching function" }
+ // { dg-message "candidate" "" { target *-*-* } 15 }
+}
new file mode 100644
@@ -0,0 +1,19 @@
+// { dg-do compile }
+
+struct S {int x; int y;};
+template<typename T>
+int foo(T a, T b) {return a + b;} // { dg-message "template" }
+// { dg-message "deduced conflicting types for parameter" "deduction" { target *-*-* } 5 }
+template<typename T, typename T2>
+int foo(T a, T2& b, T2 c) {return a + b;} // { dg-message "template" }
+// { dg-message "deduced conflicting types for parameter" "deduction" { target *-*-* } 8 }
+int foo(char*, S&); // { dg-message "foo" }
+// { dg-message "candidate expects 2 arguments, 3 provided" "arity" { target *-*-* } 10 }
+
+int foo2(int x)
+{
+ S s={1,2};
+ char c;
+ foo(c, 2, c); // { dg-error "no matching function" }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
+}
@@ -1,10 +1,11 @@
// { dg-do assemble }
template <int I>
-void f(int i); // { dg-message "note" }
+void f(int i); // { dg-message "void f" }
+// { dg-message "invalid explicit argument for template parameter 'I'" "argument note" { target *-*-* } 3 }
void g()
{
int i;
f<i>(7); // { dg-error "" } template argument 1 is invalid.
- // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
}
@@ -13,30 +13,32 @@ public:
};
template <void (A::*)() >
-void g() {} // { dg-message "note" }
+void g() {} // { dg-message "void g" }
+// { dg-message "invalid explicit argument for template parameter 1" "info" { target *-*-* } 16 }
template <int A::*>
-void h() {} // { dg-message "note" }
+void h() {} // { dg-message "void h" }
+// { dg-message "invalid explicit argument for template parameter 1" "info" { target *-*-* } 19 }
int main() {
g<&A::f>();
h<&A::i>();
g<&B::f>(); // { dg-error "" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 24 }
- h<&B::j>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 26 }
- g<(void (A::*)()) &A::f>(); // { dg-error "" }
+ h<&B::j>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 28 }
- h<(int A::*) &A::i>(); // { dg-error "" }
+ g<(void (A::*)()) &A::f>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 30 }
- g<(void (A::*)()) &B::f>(); // { dg-error "" }
+ h<(int A::*) &A::i>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 32 }
- h<(int A::*) &B::j>(); // { dg-error "" }
+ g<(void (A::*)()) &B::f>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 34 }
- g<(void (A::*)()) 0>(); // { dg-error "" }
+ h<(int A::*) &B::j>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 36 }
- h<(int A::*) 0>(); // { dg-error "" }
+ g<(void (A::*)()) 0>(); // { dg-error "" }
// { dg-message "candidate" "candidate note" { target *-*-* } 38 }
+ h<(int A::*) 0>(); // { dg-error "" }
+ // { dg-message "candidate" "candidate note" { target *-*-* } 40 }
return 0;
}