From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3617 invoked by alias); 17 Jul 2011 02:30:00 -0000 Received: (qmail 3518 invoked by uid 22791); 17 Jul 2011 02:29:49 -0000 X-SWARE-Spam-Status: No, hits=-4.9 required=5.0 tests=AWL,BAYES_50,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CP,TW_DF,TW_FN X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 17 Jul 2011 02:29:20 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6H2TJA4020823 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sat, 16 Jul 2011 22:29:19 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p6H2TB2L016185 for ; Sat, 16 Jul 2011 22:29:12 -0400 Received: from [0.0.0.0] (ovpn-113-36.phx2.redhat.com [10.3.113.36]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id p6H2TASg015169 for ; Sat, 16 Jul 2011 22:29:10 -0400 Message-ID: <4E2248F5.9040609@redhat.com> Date: Sun, 17 Jul 2011 07:56:00 -0000 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.18) Gecko/20110621 Fedora/3.1.11-1.fc14 Lightning/1.0b2 Thunderbird/3.1.11 MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org Subject: Re: [PATCH,c++] describe reasons for function template overload resolution failure References: <20110509224933.GR23480@codesourcery.com> <4DC99B34.7070301@redhat.com> <20110516173938.GA779@nightcrawler> <4DD405D0.4090108@redhat.com> <4DD41733.2020501@codesourcery.com> <4DD42299.2000206@redhat.com> <20110525181526.GA17555@nightcrawler> <4DDE750B.6080508@redhat.com> <20110526190429.GA6119@nightcrawler> <4DDFF833.5000305@redhat.com> <20110527202237.GA851@nightcrawler> <4DE05611.1050806@redhat.com> In-Reply-To: <4DE05611.1050806@redhat.com> Content-Type: multipart/mixed; boundary="------------080300030402040103090304" Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-07/txt/msg01341.txt.bz2 This is a multi-part message in MIME format. --------------080300030402040103090304 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1021 On 05/27/2011 09:55 PM, Jason Merrill wrote: > On 05/27/2011 04:22 PM, Nathan Froyd wrote: >> + /* The PARM is not one we're trying to unify. Just check >> + to see if it matches ARG. */ >> + int result = !(TREE_CODE (arg) == TREE_CODE (parm) >> + && cp_tree_equal (parm, arg)); >> + if (result) >> + unify_template_parameter_mismatch (explain_p, parm, tparm); > > This should be unify_template_argument_mismatch (explain_p, parm, arg); > > So we can drop unify_template_parameter_mismatch. > > OK with that change. It seems that Nathan is no longer working on this patch, so I'm going to apply it myself. The first patch is Nathan's original patch, adjusted to apply to the current trunk. The second patch makes the above requested change and avoids redundant error messages from repeating unification. The third patch makes some tangential adjustments to error message context printing that seemed like a good idea while I was looking at the new error messages. Tested x86_64-pc-linux-gnu, applying to trunk. --------------080300030402040103090304 Content-Type: text/x-patch; name="45329-1.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="45329-1.patch" Content-length: 92968 commit 8dbed75cf3439041851357f1a6a60f0ac449bec0 Author: Jason Merrill Date: Wed Jul 13 18:05:05 2011 -0400 gcc/cp/ PR c++/45329 PR c++/48934 * cp-tree.h (fn_type_unification): Add `bool' parameter. * pt.c (enum template_base_result): Define. (unify_success, unify_unknown): Define. (unify_parameter_deduction_failure): Define. (unify_invalid, unify_cv_qual_mismatch, unify_type_mismatch): Define. (unify_parameter_pack_mismatch): Define. (unify_parameter_pack_inconsistent): Define. (unify_ptrmem_cst_mismatch, unify_vla_arg): Define. (unify_expression_unequal, unify_inconsistency): Define. (unify_method_type_error, unify_arity): Likewise. (unify_too_many_parameters, unify_too_few_parameters): Define. (unify_arg_conversion, unify_no_common_base): Define. (unify_illformed_ptrmem_cst_expr): Define. (unify_substitution_failure): Define. (unify_inconsistent_template_template_parameters): Define. (unify_template_deduction_failure): Define. (unify_template_parameter_mismatch): Define. (unify_template_argument_mismatch): Define. (unify_overload_resolution_failure): Define. (comp_template_args_with_info): New function, split out from... (comp_template_args): ...here. Call it. (deduction_tsubst_fntype): Add `complain' parameter'. Pass it to tsubst. (unify): Add `explain_p' parameter. Pass to all relevant calls. Call above status functions when appropriate. (resolve_overloaded_unification, try_one_overload): Likewise. (type_unification, type_unification_real): Likewise. (unify_pack_expansion): Likewise. (get_template_base, try_class_unification): Likewise. (get_bindings, more_specialized_fn): Pass false to unification calls. (get_class_bindings, do_auto_deduction): Likewise. (convert_nontype_argument): Likewise. (fn_type_unification): Likewise. Pass tf_warning_or_error if explain_p. (get_template_base): Add `explain_p' parameter and pass it to try_class_unification. Return an enum template_base_result. * class.c (resolve_address_of_overloaded_function): Pass false to fn_type_unification. * call.c (enum rejection_reason_code): Add new codes. (struct rejection_reason): Add template_unification field. Add template_instantiation field. (template_unification_rejection): Define. (template_instantiation_rejection): Define. (invalid_copy_with_fn_template_rejection): Define. (add_template_candidate): Pass false to unify. Provide more rejection reasons when possible. (print_template_unification_rejection): Define. (print_arity_rejection): Define, split out from... (print_z_candidate): ...here. Add cases for new rejection reasons. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 56f3408..dc8cfe7 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -434,7 +434,10 @@ enum rejection_reason_code { rr_arity, rr_explicit_conversion, rr_arg_conversion, - rr_bad_arg_conversion + rr_bad_arg_conversion, + rr_template_unification, + rr_template_instantiation, + rr_invalid_copy }; struct conversion_info { @@ -462,6 +465,24 @@ struct rejection_reason { struct conversion_info conversion; /* Same, but for bad argument conversions. */ struct conversion_info bad_conversion; + /* Information about template unification failures. These are the + parameters passed to fn_type_unification. */ + struct { + tree tmpl; + tree explicit_targs; + tree targs; + const tree *args; + unsigned int nargs; + tree return_type; + unification_kind_t strict; + int flags; + } template_unification; + /* Information about template instantiation failures. These are the + parameters passed to instantiate_template. */ + struct { + tree tmpl; + tree targs; + } template_instantiation; } u; }; @@ -622,6 +643,44 @@ explicit_conversion_rejection (tree from, tree to) return r; } +static struct rejection_reason * +template_unification_rejection (tree tmpl, tree explicit_targs, tree targs, + const tree *args, unsigned int nargs, + tree return_type, unification_kind_t strict, + int flags) +{ + size_t args_n_bytes = sizeof (*args) * nargs; + tree *args1 = (tree *) conversion_obstack_alloc (args_n_bytes); + struct rejection_reason *r = alloc_rejection (rr_template_unification); + r->u.template_unification.tmpl = tmpl; + r->u.template_unification.explicit_targs = explicit_targs; + r->u.template_unification.targs = targs; + /* Copy args to our own storage. */ + memcpy (args1, args, args_n_bytes); + r->u.template_unification.args = args1; + r->u.template_unification.nargs = nargs; + r->u.template_unification.return_type = return_type; + r->u.template_unification.strict = strict; + r->u.template_unification.flags = flags; + return r; +} + +static struct rejection_reason * +template_instantiation_rejection (tree tmpl, tree targs) +{ + struct rejection_reason *r = alloc_rejection (rr_template_instantiation); + r->u.template_instantiation.tmpl = tmpl; + r->u.template_instantiation.targs = targs; + 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 * @@ -2904,14 +2963,23 @@ 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, false); if (i != 0) - goto fail; + { + reason = template_unification_rejection (tmpl, explicit_targs, + targs, args_without_in_chrg, + nargs_without_in_chrg, + return_type, strict, flags); + goto fail; + } fn = instantiate_template (tmpl, targs, tf_none); if (fn == error_mark_node) - goto fail; + { + reason = template_instantiation_rejection (tmpl, targs); + goto fail; + } /* In [class.copy]: @@ -2940,7 +3008,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) @@ -3108,6 +3179,18 @@ 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 one overload candidate CANDIDATE. MSGSTR is the text to print before the candidate itself. @@ -3154,10 +3237,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); @@ -3171,6 +3252,29 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate) "conversion", r->u.conversion.from_type, r->u.conversion.to_type); break; + case rr_template_unification: + /* Re-run template unification with diagnostics. */ + fn_type_unification (r->u.template_unification.tmpl, + r->u.template_unification.explicit_targs, + r->u.template_unification.targs, + r->u.template_unification.args, + r->u.template_unification.nargs, + r->u.template_unification.return_type, + r->u.template_unification.strict, + r->u.template_unification.flags, + true); + break; + case rr_template_instantiation: + /* Re-run template instantiation with diagnostics. */ + instantiate_template (r->u.template_instantiation.tmpl, + r->u.template_instantiation.targs, + tf_warning_or_error); + break; + case rr_invalid_copy: + inform (loc, + " a constructor taking a single argument of its own " + "class type is invalid"); + break; case rr_none: default: /* This candidate didn't have any issues or we failed to diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7de104d..61c1380 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6570,7 +6570,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, false)) /* Argument deduction failed. */ continue; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 96d9fa8..c590585 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5161,7 +5161,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, + bool); extern void mark_decl_instantiated (tree, int); extern int more_specialized_fn (tree, tree, int); extern void do_decl_instantiation (tree, tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d50e214..b8d25d4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -109,15 +109,22 @@ static GTY(()) VEC(tree,gc) *canonical_template_parms; #define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32 #define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64 +enum template_base_result { + tbr_incomplete_type, + tbr_ambiguous_baseclass, + tbr_success +}; + static void push_access_scope (tree); static void pop_access_scope (tree); static void push_deduction_access_scope (tree); static void pop_deduction_access_scope (tree); static bool resolve_overloaded_unification (tree, tree, tree, tree, - unification_kind_t, int); + unification_kind_t, int, + bool); 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, bool); +static int unify (tree, tree, tree, tree, int, bool); static void add_pending_template (tree); static tree reopen_tinst_level (struct tinst_level *); static tree tsubst_initializer_list (tree, tree); @@ -131,7 +138,8 @@ 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, + bool); static void note_template_header (int); static tree convert_nontype_argument_function (tree, tree); static tree convert_nontype_argument (tree, tree, tsubst_flags_t); @@ -156,7 +164,8 @@ 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, bool); 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); @@ -168,8 +177,9 @@ 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 enum template_base_result get_template_base (tree, tree, tree, tree, + bool , tree *); +static tree try_class_unification (tree, tree, tree, tree, bool); static int coerce_template_template_parms (tree, tree, tsubst_flags_t, tree, tree); static bool template_template_parm_bindings_ok_p (tree, tree); @@ -5267,6 +5277,220 @@ has_value_dependent_address (tree op) return false; } +/* The next set of functions are used for providing helpful explanatory + diagnostics for failed overload resolution. Their messages should be + indented by two spaces for consistency with the messages in + call.c */ + +static int +unify_success (bool explain_p ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +unify_parameter_deduction_failure (bool explain_p, tree parm) +{ + if (explain_p) + inform (input_location, + " couldn't deduce template parameter %qD", parm); + return 1; +} + +static int +unify_invalid (bool explain_p ATTRIBUTE_UNUSED) +{ + return 1; +} + +static int +unify_cv_qual_mismatch (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, + " types %qT and %qT have incompatible cv-qualifiers", + parm, arg); + return 1; +} + +static int +unify_type_mismatch (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, " mismatched types %qT and %qT", parm, arg); + return 1; +} + +static int +unify_parameter_pack_mismatch (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, + " template parameter %qD is not a parameter pack, but " + "argument %qD is", + parm, arg); + return 1; +} + +static int +unify_ptrmem_cst_mismatch (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, + " template argument %qE does not match " + "pointer-to-member constant %qE", + arg, parm); + return 1; +} + +static int +unify_expression_unequal (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, " %qE is not equivalent to %qE", parm, arg); + return 1; +} + +static int +unify_parameter_pack_inconsistent (bool explain_p, tree old_arg, tree new_arg) +{ + if (explain_p) + inform (input_location, + " inconsistent parameter pack deduction with %qT and %qT", + old_arg, new_arg); + return 1; +} + +static int +unify_inconsistency (bool explain_p, tree parm, tree first, tree second) +{ + if (explain_p) + inform (input_location, + " deduced conflicting types for parameter %qT (%qT and %qT)", + parm, first, second); + return 1; +} + +static int +unify_vla_arg (bool explain_p, tree arg) +{ + if (explain_p) + inform (input_location, + " variable-sized array type %qT is not " + "a valid template argument", + arg); + return 1; +} + +static int +unify_method_type_error (bool explain_p, tree arg) +{ + if (explain_p) + inform (input_location, + " member function type %qT is not a valid template argument", + arg); + return 1; +} + +static int +unify_arity (bool explain_p, int have, int wanted) +{ + if (explain_p) + inform_n (input_location, wanted, + " candidate expects %d argument, %d provided", + " candidate expects %d arguments, %d provided", + wanted, have); + return 1; +} + +static int +unify_too_many_arguments (bool explain_p, int have, int wanted) +{ + return unify_arity (explain_p, have, wanted); +} + +static int +unify_too_few_arguments (bool explain_p, int have, int wanted) +{ + return unify_arity (explain_p, have, wanted); +} + +static int +unify_arg_conversion (bool explain_p, tree to_type, + tree from_type, tree arg) +{ + if (explain_p) + inform (input_location, " cannot convert %qE (type %qT) to type %qT", + arg, from_type, to_type); + return 1; +} + +static int +unify_no_common_base (bool explain_p, enum template_base_result r, + tree parm, tree arg) +{ + if (explain_p) + switch (r) + { + case tbr_ambiguous_baseclass: + inform (input_location, " %qT is an ambiguous base class of %qT", + arg, parm); + break; + default: + inform (input_location, " %qT is not derived from %qT", arg, parm); + break; + } + return 1; +} + +static int +unify_inconsistent_template_template_parameters (bool explain_p) +{ + if (explain_p) + inform (input_location, + " template parameters of a template template argument are " + "inconsistent with other deduced template arguments"); + return 1; +} + +static int +unify_template_deduction_failure (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, + " can't deduce a template for %qT from non-template type %qT", + parm, arg); + return 1; +} + +static int +unify_template_parameter_mismatch (bool explain_p, tree parm, tree tparm) +{ + if (explain_p) + inform (input_location, + " template parameter %qT does not match %qD", tparm, parm); + return 1; +} + +static int +unify_template_argument_mismatch (bool explain_p, tree parm, tree arg) +{ + if (explain_p) + inform (input_location, + " template argument %qE does not match %qD", arg, parm); + return 1; +} + +static int +unify_overload_resolution_failure (bool explain_p, tree arg) +{ + if (explain_p) + inform (input_location, + " could not resolve address from overloaded function %qE", + arg); + 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 @@ -6550,11 +6774,13 @@ template_args_equal (tree ot, tree nt) return cp_tree_equal (ot, nt); } -/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets - of template arguments. Returns 0 otherwise. */ +/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of + template arguments. Returns 0 otherwise, and updates OLDARG_PTR and + NEWARG_PTR with the offending arguments if they are non-NULL. */ -int -comp_template_args (tree oldargs, tree newargs) +static int +comp_template_args_with_info (tree oldargs, tree newargs, + tree *oldarg_ptr, tree *newarg_ptr) { int i; @@ -6567,11 +6793,26 @@ comp_template_args (tree oldargs, tree newargs) tree ot = TREE_VEC_ELT (oldargs, i); if (! template_args_equal (ot, nt)) - return 0; + { + if (oldarg_ptr != NULL) + *oldarg_ptr = ot; + if (newarg_ptr != NULL) + *newarg_ptr = nt; + return 0; + } } return 1; } +/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets + of template arguments. Returns 0 otherwise. */ + +int +comp_template_args (tree oldargs, tree newargs) +{ + return comp_template_args_with_info (oldargs, newargs, NULL, NULL); +} + static void add_pending_template (tree d) { @@ -13724,7 +13965,7 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain) This is, of course, not reentrant. */ static tree -deduction_tsubst_fntype (tree fn, tree targs) +deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain) { static bool excessive_deduction_depth; static int deduction_depth; @@ -13748,7 +13989,7 @@ deduction_tsubst_fntype (tree fn, tree targs) input_location = DECL_SOURCE_LOCATION (fn); ++deduction_depth; push_deduction_access_scope (fn); - r = tsubst (fntype, targs, tf_none, NULL_TREE); + r = tsubst (fntype, targs, complain, NULL_TREE); pop_deduction_access_scope (fn); --deduction_depth; @@ -13961,7 +14202,8 @@ fn_type_unification (tree fn, unsigned int nargs, tree return_type, unification_kind_t strict, - int flags) + int flags, + bool explain_p) { tree parms; tree fntype; @@ -13996,12 +14238,15 @@ fn_type_unification (tree fn, bool incomplete = false; if (explicit_targs == error_mark_node) - return 1; + return unify_invalid (explain_p); converted_args - = (coerce_template_parms (tparms, explicit_targs, NULL_TREE, tf_none, - /*require_all_args=*/false, - /*use_default_args=*/false)); + = (coerce_template_parms (tparms, explicit_targs, NULL_TREE, + (explain_p + ? tf_warning_or_error + : tf_none), + /*require_all_args=*/false, + /*use_default_args=*/false)); if (converted_args == error_mark_node) return 1; @@ -14060,7 +14305,10 @@ fn_type_unification (tree fn, incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs); processing_template_decl += incomplete; - fntype = deduction_tsubst_fntype (fn, converted_args); + fntype = deduction_tsubst_fntype (fn, converted_args, + (explain_p + ? tf_warning_or_error + : tf_none)); processing_template_decl -= incomplete; if (fntype == error_mark_node) @@ -14092,7 +14340,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, explain_p); /* Now that we have bindings for all of the template arguments, ensure that the arguments deduced for the template template @@ -14118,7 +14366,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_inconsistent_template_template_parameters (explain_p); if (result == 0) /* All is well so far. Now, check: @@ -14131,7 +14379,10 @@ fn_type_unification (tree fn, substitution results in an invalid type, as described above, type deduction fails. */ { - tree substed = deduction_tsubst_fntype (fn, targs); + tree substed = deduction_tsubst_fntype (fn, targs, + (explain_p + ? tf_warning_or_error + : tf_none)); if (substed == error_mark_node) return 1; @@ -14148,7 +14399,8 @@ 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_type_mismatch (explain_p, args[i], + TREE_VALUE (sarg)); } } @@ -14279,7 +14531,8 @@ type_unification_real (tree tparms, unsigned int xnargs, int subr, unification_kind_t strict, - int flags) + int flags, + bool explain_p) { tree parm, arg, arg_expr; int i; @@ -14350,7 +14603,7 @@ type_unification_real (tree tparms, arg_expr = NULL; if (arg == error_mark_node) - return 1; + return unify_invalid (explain_p); if (arg == unknown_type_node) /* We can't deduce anything from this, but we might get all the template args from other function args. */ @@ -14376,7 +14629,10 @@ type_unification_real (tree tparms, flags)) continue; - return 1; + if (strict == DEDUCE_EXACT) + return unify_type_mismatch (explain_p, parm, arg); + else + return unify_arg_conversion (explain_p, parm, type, arg); } if (!TYPE_P (arg)) @@ -14392,15 +14648,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, explain_p)) continue; - return 1; + return unify_overload_resolution_failure (explain_p, arg); } arg_expr = arg; arg = unlowered_expr_type (arg); if (arg == error_mark_node) - return 1; + return unify_invalid (explain_p); } { @@ -14412,7 +14668,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, explain_p)) + /* If unification failed, the recursive call will have updated + UI appropriately. */ return 1; } } @@ -14434,7 +14692,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, explain_p)) return 1; /* Advance to the end of the list of parameters. */ @@ -14444,11 +14702,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_arguments (explain_p, 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_arguments (explain_p, ia, count); + } if (!subr) { @@ -14503,7 +14770,10 @@ type_unification_real (tree tparms, tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i)); 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, + arg = convert_template_argument (parm, arg, targs, + (explain_p + ? tf_warning_or_error + : tf_none), i, NULL_TREE); if (arg == error_mark_node) return 1; @@ -14540,7 +14810,7 @@ type_unification_real (tree tparms, continue; } - return 2; + return unify_parameter_deduction_failure (explain_p, tparm); } } #ifdef ENABLE_CHECKING @@ -14548,7 +14818,7 @@ type_unification_real (tree tparms, SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs)); #endif - return 0; + return unify_success (explain_p); } /* Subroutine of type_unification_real. Args are like the variables @@ -14563,7 +14833,8 @@ resolve_overloaded_unification (tree tparms, tree parm, tree arg, unification_kind_t strict, - int sub_strict) + int sub_strict, + bool explain_p) { tree tempargs = copy_node (targs); int good = 0; @@ -14615,7 +14886,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, explain_p) && (!goodfn || !decls_match (goodfn, elem))) { goodfn = elem; @@ -14643,7 +14914,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, explain_p) && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg)))) { goodfn = OVL_CURRENT (arg); @@ -14790,7 +15061,8 @@ try_one_overload (tree tparms, tree arg, unification_kind_t strict, int sub_strict, - bool addr_p) + bool addr_p, + bool explain_p) { int nargs; tree tempargs; @@ -14820,7 +15092,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, explain_p)) return 0; /* First make sure we didn't deduce anything that conflicts with @@ -14858,7 +15130,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, + bool explain_p) { tree copy_of_targs; @@ -14901,7 +15174,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, explain_p)) return NULL_TREE; return arg; @@ -14914,8 +15187,9 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg) a partial specialization, as well as a plain template type. Used by unify. */ -static tree -get_template_base (tree tparms, tree targs, tree parm, tree arg) +static enum template_base_result +get_template_base (tree tparms, tree targs, tree parm, tree arg, + bool explain_p, tree *result) { tree rval = NULL_TREE; tree binfo; @@ -14924,14 +15198,18 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg) binfo = TYPE_BINFO (complete_type (arg)); if (!binfo) - /* The type could not be completed. */ - return NULL_TREE; + { + /* The type could not be completed. */ + *result = NULL_TREE; + return tbr_incomplete_type; + } /* Walk in inheritance graph order. The search order is not 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), explain_p); if (r) { @@ -14944,13 +15222,17 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg) applies. */ if (rval && !same_type_p (r, rval)) - return NULL_TREE; + { + *result = NULL_TREE; + return tbr_ambiguous_baseclass; + } rval = r; } } - return rval; + *result = rval; + return tbr_success; } /* Returns the level of DECL, which declares a template parameter. */ @@ -15032,6 +15314,12 @@ template_parm_level_and_index (tree parm, int* level, int* index) } } +#define RECUR_AND_CHECK_FAILURE(TP, TA, P, A, S, EP) \ + do { \ + if (unify (TP, TA, P, A, S, EP)) \ + 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 @@ -15039,10 +15327,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, bool explain_p) { tree parm = TREE_VEC_ELT (packed_parms, TREE_VEC_LENGTH (packed_parms) - 1); @@ -15132,7 +15420,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, explain_p) != 0) return 1; skip_arg_p = true; @@ -15160,8 +15448,8 @@ 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, + explain_p); } } @@ -15252,13 +15540,21 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms, ARGUMENT_PACK_INCOMPLETE_P (old_pack) = 1; ARGUMENT_PACK_EXPLICIT_ARGS (old_pack) = explicit_args; } - else if (!comp_template_args (ARGUMENT_PACK_ARGS (old_pack), - new_args)) - /* Inconsistent unification of this parameter pack. */ - return 1; + else + { + tree bad_old_arg, bad_new_arg; + tree old_args = ARGUMENT_PACK_ARGS (old_pack); + + if (!comp_template_args_with_info (old_args, new_args, + &bad_old_arg, &bad_new_arg)) + /* Inconsistent unification of this parameter pack. */ + return unify_parameter_pack_inconsistent (explain_p, + bad_old_arg, + bad_new_arg); + } } - return 0; + return unify_success (explain_p); } /* Deduce the value of template parameters. TPARMS is the (innermost) @@ -15303,7 +15599,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, + bool explain_p) { int idx; tree targ; @@ -15318,19 +15615,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 (explain_p); 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 (explain_p); /* 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 (explain_p); /* Handle init lists early, so the rest of the function can assume we're dealing with a type. */ @@ -15349,7 +15646,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 (explain_p); elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0); @@ -15358,7 +15655,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 (explain_p); if (!BRACE_ENCLOSED_INITIALIZER_P (elt)) { @@ -15370,8 +15667,8 @@ 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, + explain_p); } /* If the std::initializer_list deduction worked, replace the @@ -15383,7 +15680,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 (explain_p); } /* Immediately reject some pairs that won't unify because of @@ -15400,7 +15697,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 (explain_p, parm, arg); if (!(strict & UNIFY_ALLOW_OUTER_LEVEL) && TYPE_P (parm) && !CP_TYPE_CONST_P (parm)) @@ -15418,21 +15715,26 @@ 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 (explain_p); 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 (explain_p); 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. */ - return (TREE_CODE (arg) == TREE_CODE (parm) - && same_type_p (parm, arg)) ? 0 : 1; + { + if (TREE_CODE (arg) == TREE_CODE (parm) + && same_type_p (parm, arg)) + return unify_success (explain_p); + else + return unify_type_mismatch (explain_p, parm, arg); + } idx = TEMPLATE_TYPE_IDX (parm); targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx); tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx)); @@ -15442,7 +15744,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; + gcc_unreachable (); if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM) { @@ -15450,7 +15752,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_template_deduction_failure (explain_p, parm, arg); { tree parmvec = TYPE_TI_ARGS (parm); @@ -15492,7 +15794,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) if (coerce_template_parms (parm_parms, full_argvec, TYPE_TI_TEMPLATE (parm), - tf_none, + (explain_p + ? tf_warning_or_error + : tf_none), /*require_all_args=*/true, /*use_default_args=*/false) == error_mark_node) @@ -15515,15 +15819,15 @@ 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_too_few_arguments (explain_p, + TREE_VEC_LENGTH (argvec), len); 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, explain_p); } if (parm_variadic_p @@ -15531,7 +15835,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) parmvec, argvec, UNIFY_ALLOW_NONE, /*call_args_p=*/false, - /*subr=*/false)) + /*subr=*/false, explain_p)) return 1; } arg = TYPE_TI_TEMPLATE (arg); @@ -15546,9 +15850,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 (explain_p); else if (targ) - return 1; + return unify_inconsistency (explain_p, parm, targ, arg); } else { @@ -15558,20 +15862,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 (explain_p, 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 (explain_p); /* Simple cases: Value already set, does match or doesn't. */ if (targ != NULL_TREE && same_type_p (targ, arg)) - return 0; + return unify_success (explain_p); else if (targ) - return 1; + return unify_inconsistency (explain_p, parm, targ, arg); /* Make sure that ARG is not a variable-sized array. (Note that were talking about variable-sized arrays (like @@ -15581,7 +15885,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 (explain_p, arg); /* Strip typedefs as in convert_template_argument. */ arg = canonicalize_type_argument (arg, tf_none); @@ -15591,35 +15895,45 @@ 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 unify_parameter_pack_mismatch (explain_p, parm, arg); /* 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_error (explain_p, arg); TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg; - return 0; + return unify_success (explain_p); case TEMPLATE_PARM_INDEX: tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0)); if (tparm == error_mark_node) - return 1; + return unify_invalid (explain_p); 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. */ - return !(TREE_CODE (arg) == TREE_CODE (parm) - && cp_tree_equal (parm, arg)); + { + /* The PARM is not one we're trying to unify. Just check + to see if it matches ARG. */ + int result = !(TREE_CODE (arg) == TREE_CODE (parm) + && cp_tree_equal (parm, arg)); + if (result) + unify_template_parameter_mismatch (explain_p, parm, tparm); + return result; + } idx = TEMPLATE_PARM_IDX (parm); targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx); if (targ) - return !cp_tree_equal (targ, arg); + { + int x = !cp_tree_equal (targ, arg); + if (x) + unify_inconsistency (explain_p, parm, targ, arg); + return x; + } /* [temp.deduct.type] If, in the declaration of a function template with a non-type template-parameter, the non-type @@ -15646,25 +15960,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 (explain_p); else - return 1; + return unify_type_mismatch (explain_p, tparm, arg); /* 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 (explain_p, parm, arg); TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg; - return 0; + return unify_success (explain_p); 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 (explain_p, parm, arg); /* Just unify the class member. It would be useless (and possibly wrong, depending on the strict flags) to unify also @@ -15677,13 +15991,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, explain_p); } case POINTER_TYPE: { if (TREE_CODE (arg) != POINTER_TYPE) - return 1; + return unify_type_mismatch (explain_p, parm, arg); /* [temp.deduct.call] @@ -15701,21 +16015,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, explain_p); } case REFERENCE_TYPE: if (TREE_CODE (arg) != REFERENCE_TYPE) - return 1; + return unify_type_mismatch (explain_p, parm, arg); return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), - strict & UNIFY_ALLOW_MORE_CV_QUAL); + strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p); case ARRAY_TYPE: if (TREE_CODE (arg) != ARRAY_TYPE) - return 1; + return unify_type_mismatch (explain_p, parm, arg); if ((TYPE_DOMAIN (parm) == NULL_TREE) != (TYPE_DOMAIN (arg) == NULL_TREE)) - return 1; + return unify_type_mismatch (explain_p, parm, arg); if (TYPE_DOMAIN (parm) != NULL_TREE) { tree parm_max; @@ -15754,7 +16068,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) Here, the type of the ARG will be "int [g(i)]", and may be a SAVE_EXPR, etc. */ if (TREE_CODE (arg_max) != MINUS_EXPR) - return 1; + return unify_vla_arg (explain_p, arg); arg_max = TREE_OPERAND (arg_max, 0); } @@ -15771,11 +16085,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, explain_p); } return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), - strict & UNIFY_ALLOW_MORE_CV_QUAL); + strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p); case REAL_TYPE: case COMPLEX_TYPE: @@ -15785,16 +16099,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 (explain_p, 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 (explain_p, parm, arg); /* As far as unification is concerned, this wins. Later checks will invalidate it if necessary. */ - return 0; + return unify_success (explain_p); /* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */ /* Type INTEGER_CST can come from ordinary constant template args. */ @@ -15803,38 +16117,41 @@ 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_template_argument_mismatch (explain_p, parm, arg); + return (tree_int_cst_equal (parm, arg) + ? unify_success (explain_p) + : unify_template_argument_mismatch (explain_p, parm, arg)); case TREE_VEC: { int i; if (TREE_CODE (arg) != TREE_VEC) - return 1; + return unify_template_argument_mismatch (explain_p, parm, arg); if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) - return 1; + return unify_arity (explain_p, TREE_VEC_LENGTH (arg), + TREE_VEC_LENGTH (parm)); 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, explain_p); + return unify_success (explain_p); } case RECORD_TYPE: case UNION_TYPE: if (TREE_CODE (arg) != TREE_CODE (parm)) - return 1; + return unify_type_mismatch (explain_p, parm, arg); if (TYPE_PTRMEMFUNC_P (parm)) { if (!TYPE_PTRMEMFUNC_P (arg)) - return 1; + return unify_type_mismatch (explain_p, parm, arg); return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm), TYPE_PTRMEMFUNC_FN_TYPE (arg), - strict); + strict, explain_p); } if (CLASSTYPE_TEMPLATE_INFO (parm)) @@ -15845,7 +16162,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, explain_p); if (!t) { @@ -15858,10 +16175,12 @@ 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); + enum template_base_result r; + r = get_template_base (tparms, targs, parm, arg, + explain_p, &t); if (!t) - return 1; + return unify_no_common_base (explain_p, r, parm, arg); } } else if (CLASSTYPE_TEMPLATE_INFO (arg) @@ -15872,14 +16191,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_type_mismatch (explain_p, parm, arg); return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm), - CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE); + CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p); } else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg)) - return 1; - return 0; + return unify_type_mismatch (explain_p, parm, arg); + return unify_success (explain_p); case METHOD_TYPE: case FUNCTION_TYPE: @@ -15890,7 +16209,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 (explain_p, parm, arg); /* CV qualifications for methods can never be deduced, they must match exactly. We need to check them explicitly here, @@ -15901,11 +16220,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 (explain_p, 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, explain_p); nargs = list_length (TYPE_ARG_TYPES (arg)); args = XALLOCAVEC (tree, nargs); @@ -15917,7 +16235,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, explain_p); } case OFFSET_TYPE: @@ -15930,11 +16248,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 (explain_p, 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, explain_p); /* Determine the type of the function we are unifying against. */ method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg)); @@ -15946,28 +16264,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, explain_p); } 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 unify_type_mismatch (explain_p, parm, arg); + RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm), + TYPE_OFFSET_BASETYPE (arg), + UNIFY_ALLOW_NONE, explain_p); return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), - strict); + strict, explain_p); 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, explain_p); if (arg != integral_constant_value (parm)) - return 1; - return 0; + return unify_template_argument_mismatch (explain_p, parm, arg); + return unify_success (explain_p); case FIELD_DECL: case TEMPLATE_DECL: /* Matched cases are handled by the ARG == PARM test above. */ - return 1; + return unify_template_argument_mismatch (explain_p, parm, arg); case VAR_DECL: /* A non-type template parameter that is a variable should be a @@ -15997,7 +16315,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 (explain_p); } } @@ -16006,25 +16324,27 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) (not counting the pack expression at the end), or we have too many arguments for a parameter list that doesn't end in a pack expression, we can't unify. */ - if (argslen < (len - parm_variadic_p) - || (argslen > len && !parm_variadic_p)) - return 1; + if (argslen < (len - parm_variadic_p)) + return unify_too_few_arguments (explain_p, argslen, len); + if (argslen > len && !parm_variadic_p) + return unify_too_many_arguments (explain_p, argslen, len); /* 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, explain_p); } 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, explain_p); + return unify_success (explain_p); } break; @@ -16034,16 +16354,16 @@ 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 (explain_p); case ERROR_MARK: /* Unification fails if we hit an error node. */ - return 1; + return unify_invalid (explain_p); default: /* An unresolved overload is a nondeduced context. */ if (type_unknown_p (parm)) - return 0; + return unify_success (explain_p); gcc_assert (EXPR_P (parm)); /* We must be looking at an expression. This can happen with @@ -16067,11 +16387,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 (explain_p, parm, arg); else - return 0; + return unify_success (explain_p); } } +#undef RECUR_AND_CHECK_FAILURE /* Note that DECL can be defined in this translation unit, if required. */ @@ -16334,10 +16655,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, /*explain_p=*/false) + == 0); /* We cannot deduce in the other direction, because ARG1 is a pack expansion but ARG2 is not. */ @@ -16358,10 +16680,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, /*explain_p=*/false) + == 0); /* We cannot deduce in the other direction, because ARG2 is a pack expansion but ARG1 is not.*/ @@ -16372,8 +16695,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, /*explain_p=*/false) + == 0); + deduce2 = (unify (tparms2, targs2, arg2, arg1, + UNIFY_ALLOW_NONE, /*explain_p=*/false) + == 0); } /* If we couldn't deduce arguments for tparms1 to make arg1 match @@ -16587,7 +16914,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, /*explain_p=*/false)) return NULL_TREE; return targs; @@ -16629,7 +16956,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, /*explain_p=*/false)) return NULL_TREE; for (i = 0; i < ntparms; ++i) @@ -19436,7 +19763,8 @@ do_auto_deduction (tree type, tree init, tree auto_node) TREE_VEC_ELT (tparms, 0) = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); val = type_unification_real (tparms, targs, parms, args, 1, 0, - DEDUCE_CALL, LOOKUP_NORMAL); + DEDUCE_CALL, LOOKUP_NORMAL, + /*explain_p=*/false); if (val > 0) { if (processing_template_decl) diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C index 352137a..120dfaa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C @@ -9,8 +9,9 @@ decltype(F()) run(F f) // { dg-message "note" } int main() { - auto l = []() { return 5; }; + auto l = []() { return 5; }; // { dg-error "lambda closure type" } run(l); // { dg-error "no match" } // { dg-message "candidate" "candidate note" { target *-*-* } 14 } + // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 14 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C index e02fd55..af661ec 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C @@ -17,10 +17,10 @@ void test_g() // Deduction to nullptr_t, no deduction to pointer type // g(nullptr); // { dg-error "no matching function for call to " } - // { dg-message "candidate" "candidate note" { target *-*-* } 19 } + // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 19 } type_equal(g((float*)nullptr)); decltype(nullptr) mynull = 0; g(mynull); // { dg-error "no matching function for call to " } - // { dg-message "candidate" "candidate note" { target *-*-* } 23 } + // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 23 } type_equal(g((float*)mynull)); } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C index 15efbc5..0764939 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C @@ -4,5 +4,5 @@ template void foo(); // { dg-message "note" } void bar() { foo(); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431.C b/gcc/testsuite/g++.dg/cpp0x/pr31431.C index 36f341f..afd3237 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31431.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31431.C @@ -4,5 +4,5 @@ template void foo(); // { dg-message "note" } void bar() { foo(); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31434.C b/gcc/testsuite/g++.dg/cpp0x/pr31434.C index 97ad079..5478616 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31434.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31434.C @@ -8,5 +8,5 @@ template 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|cannot convert)" "candidate note" { target *-*-* } 10 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C index 117b08b..e62c089 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C @@ -51,6 +51,6 @@ int main() // static_assert( noexcept( f3(y) ), "shall be ill-formed(OK)." ); noexcept( f1(z) ); // { dg-message "required" } - static_assert( noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match" } + static_assert( noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match|could not convert" } noexcept( f3(z) ); // { dg-message "required" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C index fa2bb6a..dab1650 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C @@ -8,7 +8,7 @@ void g() f(1, 'c'); // f(1,'c') f(1); // f(1,0) f(); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 10 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 } f(); // f(0,0) f(); // f(0,0) } diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing4.C b/gcc/testsuite/g++.dg/cpp0x/trailing4.C index d67b3b6..8d4baa9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing4.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing4.C @@ -8,5 +8,5 @@ auto f(T,U) -> decltype(T() + U()) template void g(T){} // { dg-message "note" } int main() { g(f); } // { dg-error "no matching function" } -// { dg-message "candidate" "candidate note" { target *-*-* } 10 } +// { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C index bd97305..018eaa3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C @@ -4,8 +4,8 @@ void g() { int i = f(5.6); int j = f(5.6); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 } f(f); f(f); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 9 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 9 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C index 5bf2116..0a777c4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C @@ -8,6 +8,6 @@ void g() f("aa",3.0); // Y is deduced to be char*, and // Z is deduced to be double f("aa",3.0); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 10 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 } f2(); // okay } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C index 24d7e15..2729b31 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C @@ -21,4 +21,5 @@ struct call_sum { int main() { // This shouldn't be an error; this is bug 35722. reverse(1,2); // { dg-bogus "no match" "" { xfail *-*-* } } + // { dg-message "sorry, unimplemented" "candidate explanation" { target *-*-* } 23 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C index 2ff7e5b..5514259 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C @@ -4,7 +4,7 @@ template void f() // { dg-message "note" } { f(); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 } } template<> diff --git a/gcc/testsuite/g++.dg/ext/vla2.C b/gcc/testsuite/g++.dg/ext/vla2.C index f6a9deb..3e83c8b 100644 --- a/gcc/testsuite/g++.dg/ext/vla2.C +++ b/gcc/testsuite/g++.dg/ext/vla2.C @@ -15,5 +15,5 @@ void bar(int i) char d[i] ; begin(d); // { dg-error "no matching function" "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 17 } + // { dg-message "(candidate|valid template argument)" "candidate note" { target *-*-* } 17 } } diff --git a/gcc/testsuite/g++.dg/other/ptrmem10.C b/gcc/testsuite/g++.dg/other/ptrmem10.C index bc386ed..a17df7f 100644 --- a/gcc/testsuite/g++.dg/other/ptrmem10.C +++ b/gcc/testsuite/g++.dg/other/ptrmem10.C @@ -13,7 +13,7 @@ template static void bar(C *c, void (C::*m) ()) { - foo((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun)" } + foo((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun|could not convert)" } // { dg-message "candidate" "candidate note" { target *-*-* } 16 } } diff --git a/gcc/testsuite/g++.dg/other/ptrmem11.C b/gcc/testsuite/g++.dg/other/ptrmem11.C index 119cbb0..e73164e 100644 --- a/gcc/testsuite/g++.dg/other/ptrmem11.C +++ b/gcc/testsuite/g++.dg/other/ptrmem11.C @@ -14,7 +14,7 @@ template int bar(int T::* p) { - return foo

(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member)" } + return foo

(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member|could not convert)" } // { dg-message "candidate" "candidate note" { target *-*-* } 17 } } diff --git a/gcc/testsuite/g++.dg/overload/template5.C b/gcc/testsuite/g++.dg/overload/template5.C new file mode 100644 index 0000000..b1dc65e --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/template5.C @@ -0,0 +1,15 @@ +// { dg-do compile } + +template +int low(T a, T b, T c) { return a + b + c; } // { dg-message "template" } + +template +int high(T a, T b, T c) { return a + b + c; } // { dg-message "template" } + +int test (void) +{ + low (5, 6); // { dg-error "no matching function" } + // { dg-message "(candidate|3 arguments, 2 provided)" "" { target *-*-* } 11 } + high (5, 6, 7, 8); // { dg-error "no matching function" } + // { dg-message "(candidate|3 arguments, 4 provided)" "" { target *-*-* } 13 } +} diff --git a/gcc/testsuite/g++.dg/overload/unknown1.C b/gcc/testsuite/g++.dg/overload/unknown1.C index 935f8d4..128c434 100644 --- a/gcc/testsuite/g++.dg/overload/unknown1.C +++ b/gcc/testsuite/g++.dg/overload/unknown1.C @@ -6,5 +6,5 @@ template void bar(T f); // { dg-message "note" } void baz() { bar(foo); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 8 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 8 } } diff --git a/gcc/testsuite/g++.dg/template/conv11.C b/gcc/testsuite/g++.dg/template/conv11.C index 57d06af..f08e756 100644 --- a/gcc/testsuite/g++.dg/template/conv11.C +++ b/gcc/testsuite/g++.dg/template/conv11.C @@ -7,5 +7,5 @@ struct A int main() { A().operator int(); // { dg-error "operator int" } - // { dg-message "candidate" "candidate note" { target *-*-* } 9 } + // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 9 } } diff --git a/gcc/testsuite/g++.dg/template/dependent-expr5.C b/gcc/testsuite/g++.dg/template/dependent-expr5.C index 1e850cd..af0dfb9 100644 --- a/gcc/testsuite/g++.dg/template/dependent-expr5.C +++ b/gcc/testsuite/g++.dg/template/dependent-expr5.C @@ -40,12 +40,12 @@ struct foo { bind (&bar::baikt); bind (&barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 42 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 42 } bind (&foo::barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 44 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 44 } bindm (&barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 47 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 47 } bindm (&foo::barf); bindn (&barf); @@ -53,15 +53,15 @@ struct foo { bindb (&barf); bindb (&foo::barf); // { dg-error "ambiguous" } - // { dg-message "candidate" "candidate note" { target *-*-* } 55 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 55 } bind (&bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 58 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 58 } bind (&bar::bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 60 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 60 } bindm (&bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 63 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 63 } bindm (&bar::bark); bindn (&bark); @@ -69,7 +69,7 @@ struct foo { bindb (&bark); bindb (&bar::bark); // { dg-error "ambiguous" } - // { dg-message "candidate" "candidate note" { target *-*-* } 71 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 71 } } }; @@ -92,12 +92,12 @@ struct foo { bind (&barT::baikt); bind (&barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 94 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 94 } bind (&foo::barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 96 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 96 } bindm (&barf); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 99 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 99 } bindm (&foo::barf); bindn (&barf); @@ -105,15 +105,15 @@ struct foo { bindb (&barf); bindb (&foo::barf); // { dg-error "ambiguous" } - // { dg-message "candidate" "candidate note" { target *-*-* } 107 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 107 } bind (&bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 110 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 110 } bind (&barT::bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 112 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 112 } bindm (&bark); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 115 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 115 } bindm (&barT::bark); bindn (&bark); @@ -121,7 +121,7 @@ struct foo { bindb (&bark); bindb (&barT::bark); // { dg-error "ambiguous" } - // { dg-message "candidate" "candidate note" { target *-*-* } 123 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 123 } } }; diff --git a/gcc/testsuite/g++.dg/template/friend.C b/gcc/testsuite/g++.dg/template/friend.C index 44cbce9..e315a1a 100644 --- a/gcc/testsuite/g++.dg/template/friend.C +++ b/gcc/testsuite/g++.dg/template/friend.C @@ -26,5 +26,5 @@ int main() { s::t y; cout << y; // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 28 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 28 } } diff --git a/gcc/testsuite/g++.dg/template/incomplete2.C b/gcc/testsuite/g++.dg/template/incomplete2.C index d86ea06..b855569 100644 --- a/gcc/testsuite/g++.dg/template/incomplete2.C +++ b/gcc/testsuite/g++.dg/template/incomplete2.C @@ -9,6 +9,6 @@ A a; // { dg-error "incomplete type" } void bar() { - foo(); // { dg-error "no matching function" } + foo(); // { dg-error "(no matching function|could not convert)" } // { dg-message "candidate" "candidate note" { target *-*-* } 12 } } diff --git a/gcc/testsuite/g++.dg/template/local4.C b/gcc/testsuite/g++.dg/template/local4.C index 9a03c9a..d842076 100644 --- a/gcc/testsuite/g++.dg/template/local4.C +++ b/gcc/testsuite/g++.dg/template/local4.C @@ -5,6 +5,6 @@ template void foo() {} // { dg-message "note" } int main () { struct S {}; - foo (); // { dg-error "match" } + foo (); // { dg-error "(match|template argument for|trying to instantiate)" } // { dg-message "candidate" "candidate note" { target *-*-* } 8 } } diff --git a/gcc/testsuite/g++.dg/template/local6.C b/gcc/testsuite/g++.dg/template/local6.C index 777349a..3eb828f 100644 --- a/gcc/testsuite/g++.dg/template/local6.C +++ b/gcc/testsuite/g++.dg/template/local6.C @@ -5,7 +5,7 @@ template struct PCVector2 // { dg-message "note" } PCVector2 operator- (const PCVector2 &ov) const { return PCVector2(ov.xFIELD, ov.yFIELD); // { dg-error "matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 7 } + // { dg-message "(candidate|expects 1 argument, 2 provided|cannot convert)" "candidate note" { target *-*-* } 7 } } T xFIELD, yFIELD; diff --git a/gcc/testsuite/g++.dg/template/operator9.C b/gcc/testsuite/g++.dg/template/operator9.C index 35be778..46eef0a 100644 --- a/gcc/testsuite/g++.dg/template/operator9.C +++ b/gcc/testsuite/g++.dg/template/operator9.C @@ -5,6 +5,6 @@ template void foo(); // { dg-error "before|non-function|template" } void bar() { foo(); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 7 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 7 } } diff --git a/gcc/testsuite/g++.dg/template/overload12.C b/gcc/testsuite/g++.dg/template/overload12.C new file mode 100644 index 0000000..656dcae --- /dev/null +++ b/gcc/testsuite/g++.dg/template/overload12.C @@ -0,0 +1,17 @@ +// { dg-do compile } + +struct S {int x; int y;}; +template +int foo(T a, T b) {return a + b;} // { dg-message "template" } +template +int foo(T a, T2& b, T2 c) {return a + b;} // { dg-message "template" } +int foo(char*, S&); // { dg-message "foo" } +// { dg-message "candidate expects 2 arguments, 3 provided" "arity" { target *-*-* } 8 } + +int foo2(int x) +{ + S s={1,2}; + char c; + foo(c, 2, c); // { dg-error "no matching function" } + // { dg-message "(candidate|deduced conflicting types for)" "candidate note" { target *-*-* } 15 } +} diff --git a/gcc/testsuite/g++.dg/template/ttp25.C b/gcc/testsuite/g++.dg/template/ttp25.C index 861d187..46762ae 100644 --- a/gcc/testsuite/g++.dg/template/ttp25.C +++ b/gcc/testsuite/g++.dg/template/ttp25.C @@ -18,12 +18,12 @@ void f4(T, C<5>); // { dg-message "note" } template struct X {}; void g() { f1(5l, X<5>()); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 20 } + // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 20 } f2(X<5>(), 5); f3(X<5>(), 5l); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 23 } + // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 23 } f4(5, X<5>()); f4(5l, X<5>()); // { dg-error "no matching" } - // { dg-message "candidate" "candidate note" { target *-*-* } 26 } + // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 26 } f4((short)5, X<5>()); } diff --git a/gcc/testsuite/g++.dg/template/unify10.C b/gcc/testsuite/g++.dg/template/unify10.C index 8dc434b..7f2fd53 100644 --- a/gcc/testsuite/g++.dg/template/unify10.C +++ b/gcc/testsuite/g++.dg/template/unify10.C @@ -26,34 +26,34 @@ void cvFunction(void (CLASS::* method)() const volatile) {} // { dg-message "not int main() { mFunction(&MyClass::mMethod); mFunction(&MyClass::cMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 28 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 28 } mFunction(&MyClass::vMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 30 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 30 } mFunction(&MyClass::cvMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 32 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 32 } cFunction(&MyClass::mMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 35 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 35 } cFunction(&MyClass::cMethod); cFunction(&MyClass::vMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 38 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 38 } cFunction(&MyClass::cvMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 40 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 40 } vFunction(&MyClass::mMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 43 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 43 } vFunction(&MyClass::cMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 45 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 45 } vFunction(&MyClass::vMethod); vFunction(&MyClass::cvMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 48 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 48 } cvFunction(&MyClass::mMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 51 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 51 } cvFunction(&MyClass::cMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 53 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 53 } cvFunction(&MyClass::vMethod); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 55 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 55 } cvFunction(&MyClass::cvMethod); return 0; diff --git a/gcc/testsuite/g++.dg/template/unify11.C b/gcc/testsuite/g++.dg/template/unify11.C index ed6b31c..25606dc 100644 --- a/gcc/testsuite/g++.dg/template/unify11.C +++ b/gcc/testsuite/g++.dg/template/unify11.C @@ -20,7 +20,7 @@ struct B C (U t) { A a; - A b = foo (this, a, t); // { dg-error "no matching function" } + A b = foo (this, a, t); // { dg-error "(no matching function|is not a)" } // { dg-message "candidate" "candidate note" { target *-*-* } 23 } } } c; diff --git a/gcc/testsuite/g++.dg/template/unify6.C b/gcc/testsuite/g++.dg/template/unify6.C index b12ecb2..551c96e 100644 --- a/gcc/testsuite/g++.dg/template/unify6.C +++ b/gcc/testsuite/g++.dg/template/unify6.C @@ -19,5 +19,5 @@ void Bar () Foo3 (&Baz); Foo3 (&Baz, &Baz); // { dg-error "no matching function" "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 21 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 21 } } diff --git a/gcc/testsuite/g++.dg/template/unify7.C b/gcc/testsuite/g++.dg/template/unify7.C index 2bfa563..88d9fd9 100644 --- a/gcc/testsuite/g++.dg/template/unify7.C +++ b/gcc/testsuite/g++.dg/template/unify7.C @@ -11,5 +11,5 @@ int main() { Foo (f); Baz (f); // { dg-error "no matching function" "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 13 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 13 } } diff --git a/gcc/testsuite/g++.dg/template/unify9.C b/gcc/testsuite/g++.dg/template/unify9.C index 40f6b92..f06f83a 100644 --- a/gcc/testsuite/g++.dg/template/unify9.C +++ b/gcc/testsuite/g++.dg/template/unify9.C @@ -14,5 +14,5 @@ const X *x; int main () { f (*x, &X::g); // { dg-error "no matching function" } - // { dg-message "candidate" "candidate note" { target *-*-* } 16 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 16 } } diff --git a/gcc/testsuite/g++.dg/template/varmod1.C b/gcc/testsuite/g++.dg/template/varmod1.C index 6ae78d9..4ba1104 100644 --- a/gcc/testsuite/g++.dg/template/varmod1.C +++ b/gcc/testsuite/g++.dg/template/varmod1.C @@ -7,5 +7,5 @@ void bar() int i; int A[i][i]; foo(A); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 9 } + // { dg-message "(candidate|not a valid template argument)" "candidate note" { target *-*-* } 9 } } diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C index a22615d..e3bff80 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C @@ -278,7 +278,7 @@ SetLD::remove(const T& item) Vix x; for (first(x); 0 != x && this->REMOVE_CURRENT != a; next(x, a)) a = operator()(x) == item ? this->REMOVE_CURRENT: this->NORMAL; // { dg-error "" } .* - // { dg-message "candidate" "candidate note" { target *-*-* } 280 } + // { dg-message "(candidate|not derived from)" "candidate note" { target *-*-* } 280 } } template bool @@ -287,7 +287,7 @@ SetLD::contains(const T& item) const Vix x; for (first(x); 0 != x; next(x)) { if (operator()(x) == item)// { dg-error "" } .* - // { dg-message "candidate" "candidate note" { target *-*-* } 289 } + // { dg-message "(candidate|not derived from)" "candidate note" { target *-*-* } 289 } return TRUE; } return FALSE; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash28.C b/gcc/testsuite/g++.old-deja/g++.pt/crash28.C index 2cfed93..81ed85a 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash28.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash28.C @@ -11,5 +11,5 @@ void f(unsigned int n) { int x[n]; asize(x); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 13 } + // { dg-message "(candidate|not a valid template argument)" "candidate note" { target *-*-* } 13 } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C index 560370a..c27d131 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit41.C @@ -1,6 +1,6 @@ // { dg-do assemble } template -void f(int i); // { dg-message "note" } +void f(int i); // { dg-message "void f" } void g() { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit77.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit77.C index 1213a15..b97c1cd 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit77.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit77.C @@ -15,5 +15,5 @@ void g() { f<0>(s0, s2); f(s0, s2); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 17 } + // { dg-message "(candidate|deduced conflicting types|ambiguous base class)" "candidate note" { target *-*-* } 17 } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/expr2.C b/gcc/testsuite/g++.old-deja/g++.pt/expr2.C index 0dcc65f..06d22d5 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/expr2.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/expr2.C @@ -9,5 +9,5 @@ void foo(S); // { dg-message "note" } void bar() { foo(S<3>()); // { dg-error "" } no way to deduce J from this. - // { dg-message "candidate" "candidate note" { target *-*-* } 11 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 11 } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C index 85d3e73..8802e98 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C @@ -13,9 +13,9 @@ public: }; template -void g() {} // { dg-message "note" } +void g() {} // { dg-message "void g" } template -void h() {} // { dg-message "note" } +void h() {} // { dg-message "void h" } int main() { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec5.C b/gcc/testsuite/g++.old-deja/g++.pt/spec5.C index df7112a..96e8cf9 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec5.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec5.C @@ -14,9 +14,9 @@ template void g(int i, int j); void h() { f(3, 'c'); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 16 } + // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 16 } g(3, 'c'); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 18 } + // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 18 } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C index fc19c3c..b8f6673 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec6.C @@ -25,9 +25,9 @@ void h() { S1 s1; s1.f(3, 'c'); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 27 } + // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 27 } S2 s2; s2.f(3, 'c'); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 31 } + // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 31 } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify4.C b/gcc/testsuite/g++.old-deja/g++.pt/unify4.C index 6dd9961..9285b21 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/unify4.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify4.C @@ -8,6 +8,6 @@ int main () { f (g); // { dg-error "" } ambiguous unification - // { dg-message "candidate" "candidate note" { target *-*-* } 10 } + // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 } return 0; } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C index 3209260..3a86d97 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C @@ -16,6 +16,6 @@ void Foo (float); // { dg-message "note" } candidate void baz (int **p1) { Foo (p1); // { dg-error "match" } no such function - // { dg-message "candidate" "candidate note" { target *-*-* } 18 } + // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 18 } Bar (p1); // OK } diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb98.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb98.C index c562031..410a336 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb98.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb98.C @@ -15,5 +15,5 @@ void f() { extent(b); // { dg-error "" } no matching function - // { dg-message "candidate" "candidate note" { target *-*-* } 17 } + // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 17 } } --------------080300030402040103090304 Content-Type: text/x-patch; name="45329-2.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="45329-2.patch" Content-length: 9500 commit c51bed9b91dd53013feb770278a6e8c466001fa0 Author: Jason Merrill Date: Sat Jul 16 22:20:52 2011 -0400 * call.c (template_unification_error_rejection): Define. (add_template_candidate_real): Use it if unification caused errors. (print_z_candidate): Handle it. * pt.c (unify_template_parameter_mismatch): Remove. (unify): Use unify_expression_unequal instead. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dc8cfe7..0279066 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -666,6 +666,12 @@ template_unification_rejection (tree tmpl, tree explicit_targs, tree targs, } static struct rejection_reason * +template_unification_error_rejection (void) +{ + return alloc_rejection (rr_template_unification); +} + +static struct rejection_reason * template_instantiation_rejection (tree tmpl, tree targs) { struct rejection_reason *r = alloc_rejection (rr_template_instantiation); @@ -2918,6 +2924,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, int i; tree fn; struct rejection_reason *reason = NULL; + int errs; /* We don't do deduction on the in-charge parameter, the VTT parameter or 'this'. */ @@ -2960,6 +2967,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, } gcc_assert (ia == nargs_without_in_chrg); + errs = errorcount+sorrycount; i = fn_type_unification (tmpl, explicit_targs, targs, args_without_in_chrg, nargs_without_in_chrg, @@ -2967,10 +2975,14 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, if (i != 0) { - reason = template_unification_rejection (tmpl, explicit_targs, - targs, args_without_in_chrg, - nargs_without_in_chrg, - return_type, strict, flags); + /* Don't repeat unification later if it already resulted in errors. */ + if (errorcount+sorrycount == errs) + reason = template_unification_rejection (tmpl, explicit_targs, + targs, args_without_in_chrg, + nargs_without_in_chrg, + return_type, strict, flags); + else + reason = template_unification_error_rejection (); goto fail; } @@ -3253,7 +3265,17 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate) r->u.conversion.to_type); break; case rr_template_unification: + /* We use template_unification_error_rejection if unification caused + actual non-SFINAE errors, in which case we don't need to repeat + them here. */ + if (r->u.template_unification.tmpl == NULL_TREE) + { + inform (loc, " substitution of deduced template arguments " + "resulted in errors seen above"); + break; + } /* Re-run template unification with diagnostics. */ + inform (loc, " template argument deduction/substitution failed:"); fn_type_unification (r->u.template_unification.tmpl, r->u.template_unification.explicit_targs, r->u.template_unification.targs, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b8d25d4..8136a99 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5464,15 +5464,6 @@ unify_template_deduction_failure (bool explain_p, tree parm, tree arg) } static int -unify_template_parameter_mismatch (bool explain_p, tree parm, tree tparm) -{ - if (explain_p) - inform (input_location, - " template parameter %qT does not match %qD", tparm, parm); - return 1; -} - -static int unify_template_argument_mismatch (bool explain_p, tree parm, tree arg) { if (explain_p) @@ -15920,7 +15911,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, int result = !(TREE_CODE (arg) == TREE_CODE (parm) && cp_tree_equal (parm, arg)); if (result) - unify_template_parameter_mismatch (explain_p, parm, tparm); + unify_expression_unequal (explain_p, parm, arg); return result; } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C index 2bb79d0..70fe441 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C @@ -13,7 +13,7 @@ decltype (ft (F())) ft() {} // { dg-error "depth" } int main() { - ft(); // { dg-error "no match" } + ft(); // { dg-error "no match|wrong number" } } // { dg-prune-output "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/error4.C b/gcc/testsuite/g++.dg/cpp0x/error4.C index 29a1cdd..064c2f2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error4.C +++ b/gcc/testsuite/g++.dg/cpp0x/error4.C @@ -10,7 +10,7 @@ struct S { static U get(const volatile T&); template - static decltype(*declval()) get(...); + static decltype(*declval()) get(...); // { dg-error "operator*" } typedef decltype(get(declval())) type; // { dg-error "no match" } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C index 120dfaa..8d7d093 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C @@ -13,5 +13,5 @@ int main() run(l); // { dg-error "no match" } // { dg-message "candidate" "candidate note" { target *-*-* } 14 } - // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 14 } + // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C index 5b8cdd9..42b48eb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C @@ -32,7 +32,7 @@ struct S { template...>::value>::type*& = enabler > - S(U...){} // # + S(U...){} // { dg-error "no type named 'type'" } }; S s(0); // { dg-error "no match" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C index 2729b31..66387b2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C @@ -21,5 +21,5 @@ struct call_sum { int main() { // This shouldn't be an error; this is bug 35722. reverse(1,2); // { dg-bogus "no match" "" { xfail *-*-* } } - // { dg-message "sorry, unimplemented" "candidate explanation" { target *-*-* } 23 } + // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 } } diff --git a/gcc/testsuite/g++.dg/template/deduce3.C b/gcc/testsuite/g++.dg/template/deduce3.C index e8a1d4e..c5d6e00 100644 --- a/gcc/testsuite/g++.dg/template/deduce3.C +++ b/gcc/testsuite/g++.dg/template/deduce3.C @@ -4,8 +4,8 @@ void f(int, T (*)() = 0); // { dg-message "note" } void g() { typedef int A[2]; f(0); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-error "returning an array" "candidate explanation" { target *-*-* } 2 } typedef void F(); f(0); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 9 } + // { dg-error "returning a function" "candidate explanation" { target *-*-* } 2 } } diff --git a/gcc/testsuite/g++.dg/template/error45.C b/gcc/testsuite/g++.dg/template/error45.C index 454acc6..064554d 100644 --- a/gcc/testsuite/g++.dg/template/error45.C +++ b/gcc/testsuite/g++.dg/template/error45.C @@ -11,7 +11,7 @@ struct enable_if< true, T > template < typename T > struct enable_if< true, T >::type -f( T x ); +f( T x ); // { dg-error "not a class type" } void g( void ) diff --git a/gcc/testsuite/g++.dg/template/ptrmem2.C b/gcc/testsuite/g++.dg/template/ptrmem2.C index 1919047..5f03580 100644 --- a/gcc/testsuite/g++.dg/template/ptrmem2.C +++ b/gcc/testsuite/g++.dg/template/ptrmem2.C @@ -7,7 +7,7 @@ struct A {}; -template T A::* Foo (); // { dg-message "note" } +template T A::* Foo (); // { dg-error "reference" } void Baz () { diff --git a/gcc/testsuite/g++.dg/template/sfinae2.C b/gcc/testsuite/g++.dg/template/sfinae2.C index e39ca6b..c9e1031 100644 --- a/gcc/testsuite/g++.dg/template/sfinae2.C +++ b/gcc/testsuite/g++.dg/template/sfinae2.C @@ -8,7 +8,7 @@ template struct cl { const static int value = T; }; -template void fn (char (*) [cl::value] = 0 ); // { dg-message "note" } +template void fn (char (*) [cl::value] = 0 ); // { dg-error "zero-size array" } void foo (void) { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C index 1aad621..747af9b 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C @@ -7,7 +7,7 @@ template< typename SID, class SDR > void k( SID sid, SDR* p, void (SDR::*) - ( typename SID::T ) ); // { dg-message "note" } + ( typename SID::T ) ); // { dg-error "no type named 'T'" } struct E { }; struct S { void f( int ); }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C index 0e5c034..a6f7674 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C @@ -19,7 +19,7 @@ template<> void fn() {} // ok, specialize A template<> void fn() {} // ok, specialize A // now make sure we moan when we really should -template void foo(T const *){} // { dg-message "note" } +template void foo(T const *){} // { dg-error "pointer to reference" } void f() { --------------080300030402040103090304 Content-Type: text/x-patch; name="45329-3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="45329-3.patch" Content-length: 7071 commit b8ce4e6d5fd01abd939817fa2b5ad2088f0e4834 Author: Jason Merrill Date: Wed Jul 13 22:58:28 2011 -0400 gcc/cp/ * pt.c (tinst_level_tick, last_template_error_tick): Replace with last_error_tinst_level. (push_tinst_level, pop_tinst_level): Adjust. (problematic_instantiation_changed): Adjust. (record_last_problematic_instantiation): Adjust. * error.c (cp_print_error_function): Don't print current_function_decl if we're in a template instantiation context. (print_instantiation_full_context): Always print first line. gcc/testsuite/ * lib/prune.exp (prune_gcc_output): Prune "In substitution" too. diff --git a/gcc/cp/error.c b/gcc/cp/error.c index b16fce6..2d7c0f1 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2784,6 +2784,10 @@ static void cp_print_error_function (diagnostic_context *context, diagnostic_info *diagnostic) { + /* If we are in an instantiation context, current_function_decl is likely + to be wrong, so just rely on print_instantiation_full_context. */ + if (current_instantiation ()) + return; if (diagnostic_last_function_changed (context, diagnostic)) { const char *old_prefix = context->printer->prefix; @@ -2927,26 +2931,15 @@ print_instantiation_full_context (diagnostic_context *context) if (p) { - if (current_function_decl != p->decl - && current_function_decl != NULL_TREE) - /* We can get here during the processing of some synthesized - method. Then, P->DECL will be the function that's causing - the synthesis. */ - ; - else - { - if (current_function_decl == p->decl) - /* Avoid redundancy with the "In function" line. */; - else - pp_verbatim (context->printer, - _("%s: In instantiation of %qs:\n"), - LOCATION_FILE (location), - decl_as_string_translate (p->decl, - TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE)); + pp_verbatim (context->printer, + TREE_CODE (p->decl) == TREE_LIST + ? _("%s: In substitution of %qS:\n") + : _("%s: In instantiation of %q#D:\n"), + LOCATION_FILE (location), + p->decl); - location = p->locus; - p = p->next; - } + location = p->locus; + p = p->next; } print_instantiation_partial_context (context, p, location); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8136a99..1c2a062 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7766,8 +7766,7 @@ extern int max_tinst_depth; #ifdef GATHER_STATISTICS int depth_reached; #endif -static int tinst_level_tick; -static int last_template_error_tick; +static GTY(()) struct tinst_level *last_error_tinst_level; /* We're starting to instantiate D; record the template instantiation context for diagnostics and to restore it later. */ @@ -7779,7 +7778,7 @@ push_tinst_level (tree d) if (tinst_depth >= max_tinst_depth) { - last_template_error_tick = tinst_level_tick; + last_error_tinst_level = current_tinst_level; if (TREE_CODE (d) == TREE_LIST) error ("template instantiation depth exceeds maximum of %d (use " "-ftemplate-depth= to increase the maximum) substituting %qS", @@ -7814,7 +7813,6 @@ push_tinst_level (tree d) depth_reached = tinst_depth; #endif - ++tinst_level_tick; return 1; } @@ -7829,7 +7827,6 @@ pop_tinst_level (void) input_location = current_tinst_level->locus; current_tinst_level = current_tinst_level->next; --tinst_depth; - ++tinst_level_tick; } /* We're instantiating a deferred template; restore the template @@ -13961,6 +13958,7 @@ deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain) static bool excessive_deduction_depth; static int deduction_depth; struct pending_template *old_last_pend = last_pending_template; + struct tinst_level *old_error_tinst = last_error_tinst_level; tree fntype = TREE_TYPE (fn); tree tinst; @@ -13993,8 +13991,10 @@ deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain) } pop_tinst_level (); - /* We can't free this if a pending_template entry is pointing at it. */ - if (last_pending_template == old_last_pend) + /* We can't free this if a pending_template entry or last_error_tinst_level + is pointing at it. */ + if (last_pending_template == old_last_pend + && last_error_tinst_level == old_error_tinst) ggc_free (tinst); return r; } @@ -18564,14 +18564,14 @@ get_mostly_instantiated_function_type (tree decl) int problematic_instantiation_changed (void) { - return last_template_error_tick != tinst_level_tick; + return current_tinst_level != last_error_tinst_level; } /* Remember current template involved in diagnostics. */ void record_last_problematic_instantiation (void) { - last_template_error_tick = tinst_level_tick; + last_error_tinst_level = current_tinst_level; } struct tinst_level * diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp index f5cbc4c..4683f93 100644 --- a/gcc/testsuite/lib/prune.exp +++ b/gcc/testsuite/lib/prune.exp @@ -20,7 +20,7 @@ proc prune_gcc_output { text } { #send_user "Before:$text\n" - regsub -all "(^|\n)(\[^\n\]*: )?In ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|program|subroutine|block-data)\[^\n\]*" $text "" text + regsub -all "(^|\n)(\[^\n\]*: )?In ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|substitution|program|subroutine|block-data)\[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*(: )?At (top level|global scope):\[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*: (recursively )?required \[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*: . skipping \[0-9\]* instantiation contexts \[^\n\]*" $text "" text diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc index a56148a..a884d01 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc @@ -47,6 +47,6 @@ main() test01(); return 0; } -// { dg-error "In member function" "" { target *-*-* } 0 } +// { dg-error "In instantiation" "" { target *-*-* } 0 } // { dg-error "cannot convert" "" { target *-*-* } 0 } // { dg-error "required from" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/shared_ptr_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/shared_ptr_neg.cc index 8114531..ec41e5b 100644 --- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/shared_ptr_neg.cc +++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/assign/shared_ptr_neg.cc @@ -46,6 +46,6 @@ main() test01(); return 0; } -// { dg-error "In member function" "" { target *-*-* } 0 } +// { dg-error "In instantiation" "" { target *-*-* } 0 } // { dg-error "cannot convert" "" { target *-*-* } 0 } // { dg-error "required from" "" { target *-*-* } 0 } --------------080300030402040103090304--