From 4911b24d71955b757fdaac29b878ae33c32f3e0b Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 12 Sep 2018 18:50:08 +0000 Subject: [PATCH] C++: special-case single non-viable candidate (more PR c++/85110) I broke out the "no viable candidates" case in build_new_method_call_1 into a subroutine, and added special-case handling for when there's a single non-viable candidate where there's an argument conversion error. I turned the error-handling from convert_for_assignment into a subroutine, calling it from this new special-case. This converts: demo.cc: In function 'int test_4(int, const char*, float)': demo.cc:5:44: error: no matching function for call to 's4::member_1(int&, const char*&, float&)' 5 | return s4::member_1 (first, second, third); | ^ demo.cc:1:24: note: candidate: 'static int s4::member_1(int, const char**, float)' 1 | struct s4 { static int member_1 (int one, const char **two, float three); }; | ^~~~~~~~ demo.cc:1:56: note: no known conversion for argument 2 from 'const char*' to 'const char**' 1 | struct s4 { static int member_1 (int one, const char **two, float three); }; | ~~~~~~~~~~~~~^~~ to: demo.cc: In function 'int test_4(int, const char*, float)': demo.cc:5:31: error: cannot convert 'const char*' to 'const char**' 5 | return s4::member_1 (first, second, third); | ^~~~~~ | | | const char* demo.cc:1:56: note: initializing argument 2 of 'static int s4::member_1(int, const char**, float)' 1 | struct s4 { static int member_1 (int one, const char **two, float three); }; | ~~~~~~~~~~~~~^~~ thus highlighting the problematic argument at the callsite (and its type). gcc/cp/ChangeLog: PR c++/85110 * call.c (struct conversion_info): Add "loc" field. (arg_conversion_rejection): Add "loc" param, using it to initialize the new field. (bad_arg_conversion_rejection): Likewise. (explicit_conversion_rejection): Initialize the new field to UNKNOWN_LOCATION. (template_conversion_rejection): Likewise. (add_function_candidate): Pass on the argument location to the new param of arg_conversion_rejection. (add_conv_candidate): Likewise. (build_builtin_candidate): Likewise. (build_user_type_conversion_1): Likewise. (single_z_candidate): New function. (maybe_get_bad_conversion_for_unmatched_call): New function. (complain_about_bad_argument): New function, based on part of convert_for_assignment. (build_new_method_call_1): Split out handling of the "no viable candidates" case into... (complain_about_no_candidates_for_method_call): ...this new function, and use the new functions above to special-case the handling of a single non-viable candidate due to a bad argument. * cp-tree.h (complain_about_bad_argument): New decl. * typeck.c (convert_for_assignment): Split out one error-handling case into complain_about_bad_argument. gcc/testsuite/ChangeLog: PR c++/85110 * g++.dg/cpp0x/explicit4.C: Update expected output to reflect special-casing of diagnostic for a single non-viable candidate due to a bad argument. * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise. Add test coverage for an unmatched overloaded operator. * g++.dg/expr/pmf-1.C: Likewise. * g++.old-deja/g++.bugs/900330_02.C: Likewise. * g++.old-deja/g++.jason/conversion11.C: Likewise. * g++.old-deja/g++.law/arg11.C: Likewise. * g++.old-deja/g++.law/arm9.C: Likewise. * g++.old-deja/g++.robertl/eb131.C: Likewise. From-SVN: r264250 --- gcc/cp/ChangeLog | 28 +++ gcc/cp/call.c | 192 ++++++++++++++---- gcc/cp/cp-tree.h | 3 + gcc/cp/typeck.c | 20 +- gcc/testsuite/ChangeLog | 15 ++ gcc/testsuite/g++.dg/cpp0x/explicit4.C | 2 +- .../g++.dg/diagnostic/param-type-mismatch-2.C | 90 ++++---- gcc/testsuite/g++.dg/expr/pmf-1.C | 2 +- .../g++.old-deja/g++.bugs/900330_02.C | 2 +- .../g++.old-deja/g++.jason/conversion11.C | 4 +- gcc/testsuite/g++.old-deja/g++.law/arg11.C | 2 +- gcc/testsuite/g++.old-deja/g++.law/arm9.C | 2 +- .../g++.old-deja/g++.robertl/eb131.C | 4 +- 13 files changed, 263 insertions(+), 103 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e4d635dc47d..9201d67c0ab 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,31 @@ +2018-09-12 David Malcolm + + PR c++/85110 + * call.c (struct conversion_info): Add "loc" field. + (arg_conversion_rejection): Add "loc" param, using it to + initialize the new field. + (bad_arg_conversion_rejection): Likewise. + (explicit_conversion_rejection): Initialize the new field to + UNKNOWN_LOCATION. + (template_conversion_rejection): Likewise. + (add_function_candidate): Pass on the argument location to the new + param of arg_conversion_rejection. + (add_conv_candidate): Likewise. + (build_builtin_candidate): Likewise. + (build_user_type_conversion_1): Likewise. + (single_z_candidate): New function. + (maybe_get_bad_conversion_for_unmatched_call): New function. + (complain_about_bad_argument): New function, based on part of + convert_for_assignment. + (build_new_method_call_1): Split out handling of the "no viable + candidates" case into... + (complain_about_no_candidates_for_method_call): ...this new + function, and use the new functions above to special-case the + handling of a single non-viable candidate due to a bad argument. + * cp-tree.h (complain_about_bad_argument): New decl. + * typeck.c (convert_for_assignment): Split out one error-handling + case into complain_about_bad_argument. + 2018-09-09 Cesar Philippidis Julian Brown diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 03b4c5ab224..69503ca7920 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -436,6 +436,8 @@ struct conversion_info { tree from; /* The type of the parameter. */ tree to_type; + /* The location of the argument. */ + location_t loc; }; struct rejection_reason { @@ -627,24 +629,28 @@ arity_rejection (tree first_arg, int expected, int actual) } static struct rejection_reason * -arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to) +arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to, + location_t loc) { struct rejection_reason *r = alloc_rejection (rr_arg_conversion); int adjust = first_arg != NULL_TREE; r->u.conversion.n_arg = n_arg - adjust; r->u.conversion.from = from; r->u.conversion.to_type = to; + r->u.conversion.loc = loc; return r; } static struct rejection_reason * -bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to) +bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to, + location_t loc) { struct rejection_reason *r = alloc_rejection (rr_bad_arg_conversion); int adjust = first_arg != NULL_TREE; r->u.bad_conversion.n_arg = n_arg - adjust; r->u.bad_conversion.from = from; r->u.bad_conversion.to_type = to; + r->u.bad_conversion.loc = loc; return r; } @@ -655,6 +661,7 @@ explicit_conversion_rejection (tree from, tree to) r->u.conversion.n_arg = 0; r->u.conversion.from = from; r->u.conversion.to_type = to; + r->u.conversion.loc = UNKNOWN_LOCATION; return r; } @@ -665,6 +672,7 @@ template_conversion_rejection (tree from, tree to) r->u.conversion.n_arg = 0; r->u.conversion.from = from; r->u.conversion.to_type = to; + r->u.conversion.loc = UNKNOWN_LOCATION; return r; } @@ -2257,14 +2265,17 @@ add_function_candidate (struct z_candidate **candidates, if (! t) { viable = 0; - reason = arg_conversion_rejection (first_arg, i, argtype, to_type); + reason = arg_conversion_rejection (first_arg, i, argtype, to_type, + EXPR_LOCATION (arg)); break; } if (t->bad_p) { viable = -1; - reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type); + reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type, + EXPR_LOCATION (arg)); + } } @@ -2353,7 +2364,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, if (t->bad_p) { viable = -1; - reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type); + reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type, + EXPR_LOCATION (arg)); } if (i == 0) @@ -2414,13 +2426,14 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, /* We need something for printing the candidate. */ t = build_identity_conv (types[i], NULL_TREE); reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i], - types[i]); + types[i], EXPR_LOCATION (args[i])); } else if (t->bad_p) { viable = 0; reason = bad_arg_conversion_rejection (NULL_TREE, i, args[i], - types[i]); + types[i], + EXPR_LOCATION (args[i])); } convs[i] = t; } @@ -2439,7 +2452,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, { viable = 0; reason = arg_conversion_rejection (NULL_TREE, 0, argtypes[2], - boolean_type_node); + boolean_type_node, + EXPR_LOCATION (args[2])); } } @@ -3930,7 +3944,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, { cand->viable = 0; cand->reason = arg_conversion_rejection (NULL_TREE, -2, - rettype, totype); + rettype, totype, + EXPR_LOCATION (expr)); } else if (DECL_NONCONVERTING_P (cand->fn) && ics->rank > cr_exact) @@ -3950,7 +3965,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, cand->viable = -1; cand->reason = bad_arg_conversion_rejection (NULL_TREE, -2, - rettype, totype); + rettype, totype, + EXPR_LOCATION (expr)); } else if (primary_template_specialization_p (cand->fn) && ics->rank > cr_exact) @@ -9165,6 +9181,129 @@ name_as_c_string (tree name, tree type, bool *free_p) return CONST_CAST (char *, pretty_name); } +/* If CANDIDATES contains exactly one candidate, return it, otherwise + return NULL. */ + +static z_candidate * +single_z_candidate (z_candidate *candidates) +{ + if (candidates == NULL) + return NULL; + + if (candidates->next) + return NULL; + + return candidates; +} + +/* If CANDIDATE is invalid due to a bad argument type, return the + pertinent conversion_info. + + Otherwise, return NULL. */ + +static const conversion_info * +maybe_get_bad_conversion_for_unmatched_call (const z_candidate *candidate) +{ + /* Must be an rr_arg_conversion or rr_bad_arg_conversion. */ + rejection_reason *r = candidate->reason; + + if (r == NULL) + return NULL; + + switch (r->code) + { + default: + return NULL; + + case rr_arg_conversion: + return &r->u.conversion; + + case rr_bad_arg_conversion: + return &r->u.bad_conversion; + } +} + +/* Issue an error and note complaining about a bad argument type at a + callsite with a single candidate FNDECL. + + ARG_LOC is the location of the argument (or UNKNOWN_LOCATION, in which + case input_location is used). + FROM_TYPE is the type of the actual argument; TO_TYPE is the type of + the formal parameter. */ + +void +complain_about_bad_argument (location_t arg_loc, + tree from_type, tree to_type, + tree fndecl, int parmnum) +{ + auto_diagnostic_group d; + range_label_for_type_mismatch rhs_label (from_type, to_type); + range_label *label = &rhs_label; + if (arg_loc == UNKNOWN_LOCATION) + { + arg_loc = input_location; + label = NULL; + } + gcc_rich_location richloc (arg_loc, label); + error_at (&richloc, + "cannot convert %qH to %qI", + from_type, to_type); + inform (get_fndecl_argument_location (fndecl, parmnum), + " initializing argument %P of %qD", parmnum, fndecl); +} + +/* Subroutine of build_new_method_call_1, for where there are no viable + candidates for the call. */ + +static void +complain_about_no_candidates_for_method_call (tree instance, + z_candidate *candidates, + tree explicit_targs, + tree basetype, + tree optype, tree name, + bool skip_first_for_error, + vec *user_args) +{ + auto_diagnostic_group d; + if (!COMPLETE_OR_OPEN_TYPE_P (basetype)) + cxx_incomplete_type_error (instance, basetype); + else if (optype) + error ("no matching function for call to %<%T::operator %T(%A)%#V%>", + basetype, optype, build_tree_list_vec (user_args), + TREE_TYPE (instance)); + else + { + /* Special-case for when there's a single candidate that's failing + due to a bad argument type. */ + if (z_candidate *candidate = single_z_candidate (candidates)) + if (const conversion_info *conv + = maybe_get_bad_conversion_for_unmatched_call (candidate)) + { + complain_about_bad_argument (conv->loc, + conv->from, conv->to_type, + candidate->fn, conv->n_arg); + return; + } + + tree arglist = build_tree_list_vec (user_args); + tree errname = name; + bool twiddle = false; + if (IDENTIFIER_CDTOR_P (errname)) + { + twiddle = IDENTIFIER_DTOR_P (errname); + errname = constructor_name (basetype); + } + if (explicit_targs) + errname = lookup_template_function (errname, explicit_targs); + if (skip_first_for_error) + arglist = TREE_CHAIN (arglist); + error ("no matching function for call to %<%T::%s%E(%A)%#V%>", + basetype, &"~"[!twiddle], errname, arglist, + TREE_TYPE (instance)); + } + print_z_candidates (location_of (name), candidates); +} + /* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will be set, upon return, to the function called. ARGS may be NULL. This may change ARGS. */ @@ -9382,34 +9521,11 @@ build_new_method_call_1 (tree instance, tree fns, vec **args, if (!any_viable_p) { if (complain & tf_error) - { - auto_diagnostic_group d; - if (!COMPLETE_OR_OPEN_TYPE_P (basetype)) - cxx_incomplete_type_error (instance, basetype); - else if (optype) - error ("no matching function for call to %<%T::operator %T(%A)%#V%>", - basetype, optype, build_tree_list_vec (user_args), - TREE_TYPE (instance)); - else - { - tree arglist = build_tree_list_vec (user_args); - tree errname = name; - bool twiddle = false; - if (IDENTIFIER_CDTOR_P (errname)) - { - twiddle = IDENTIFIER_DTOR_P (errname); - errname = constructor_name (basetype); - } - if (explicit_targs) - errname = lookup_template_function (errname, explicit_targs); - if (skip_first_for_error) - arglist = TREE_CHAIN (arglist); - error ("no matching function for call to %<%T::%s%E(%A)%#V%>", - basetype, &"~"[!twiddle], errname, arglist, - TREE_TYPE (instance)); - } - print_z_candidates (location_of (name), candidates); - } + complain_about_no_candidates_for_method_call (instance, candidates, + explicit_targs, basetype, + optype, name, + skip_first_for_error, + user_args); call = error_mark_node; } else diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b78e9eb252b..6cd6e5f5886 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6088,6 +6088,9 @@ extern bool can_convert_arg_bad (tree, tree, tree, int, extern int conv_flags (int, int, tree, tree, int); extern struct conversion * good_conversion (tree, tree, tree, int, tsubst_flags_t); extern location_t get_fndecl_argument_location (tree, int); +extern void complain_about_bad_argument (location_t arg_loc, + tree from_type, tree to_type, + tree fndecl, int parmnum); /* A class for recording information about access failures (e.g. private diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 9fa4c16bf14..e9932202b46 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8820,23 +8820,9 @@ convert_for_assignment (tree type, tree rhs, parmnum, complain, flags); } else if (fndecl) - { - auto_diagnostic_group d; - location_t loc = cp_expr_location (rhs); - range_label_for_type_mismatch rhs_label (rhstype, type); - range_label *label = &rhs_label; - if (loc == UNKNOWN_LOCATION) - { - loc = input_location; - label = NULL; - } - gcc_rich_location richloc (loc, label); - error_at (&richloc, - "cannot convert %qH to %qI", - rhstype, type); - inform (get_fndecl_argument_location (fndecl, parmnum), - " initializing argument %P of %qD", parmnum, fndecl); - } + complain_about_bad_argument (cp_expr_location (rhs), + rhstype, type, + fndecl, parmnum); else switch (errtype) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4cd8859e2bf..5a50c801203 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2018-09-12 David Malcolm + + PR c++/85110 + * g++.dg/cpp0x/explicit4.C: Update expected output to reflect + special-casing of diagnostic for a single non-viable candidate due + to a bad argument. + * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise. + Add test coverage for an unmatched overloaded operator. + * g++.dg/expr/pmf-1.C: Likewise. + * g++.old-deja/g++.bugs/900330_02.C: Likewise. + * g++.old-deja/g++.jason/conversion11.C: Likewise. + * g++.old-deja/g++.law/arg11.C: Likewise. + * g++.old-deja/g++.law/arm9.C: Likewise. + * g++.old-deja/g++.robertl/eb131.C: Likewise. + 2018-09-12 Paul Thomas PR fortran/87284 diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit4.C b/gcc/testsuite/g++.dg/cpp0x/explicit4.C index 346a6e25908..065a473854d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit4.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit4.C @@ -13,5 +13,5 @@ int main() { B b; (A(b)); // OK - (A(b,1)); // { dg-error "no match" } + (A(b,1)); // { dg-error "cannot convert" } } diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C index 4957f61878e..f74f8d39e26 100644 --- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C +++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C @@ -71,17 +71,14 @@ struct s4 { static int member_1 (int one, const char **two, float three); }; // int test_4 (int first, const char *second, float third) { - return s4::member_1 (first, second, third); // { dg-error "no matching function for call to 's4::member_1\\(int&, const char\\*&, float&\\)'" } + return s4::member_1 (first, second, third); // { dg-error "31: cannot convert 'const char\\*' to 'const char\\*\\*'" } /* { dg-begin-multiline-output "" } return s4::member_1 (first, second, third); - ^ + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "candidate: 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 } - /* { dg-begin-multiline-output "" } - struct s4 { static int member_1 (int one, const char **two, float three); }; - ^~~~~~~~ - { dg-end-multiline-output "" } */ - // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s4_member_1 } + // { dg-message "initializing argument 2 of 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 } /* { dg-begin-multiline-output "" } struct s4 { static int member_1 (int one, const char **two, float three); }; ~~~~~~~~~~~~~^~~ @@ -95,18 +92,15 @@ struct s5 { int member_1 (int one, const char **two, float three); }; // { dg-li int test_5 (int first, const char *second, float third) { s5 inst; - return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's5::member_1\\(int&, const char\\*&, float&\\)'" } + return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" } /* { dg-begin-multiline-output "" } return inst.member_1 (first, second, third); - ^ + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "candidate: 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 } + // { dg-message "initializing argument 2 of 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 } /* { dg-begin-multiline-output "" } - struct s5 { int member_1 (int one, const char **two, float three); }; - ^~~~~~~~ - { dg-end-multiline-output "" } */ - // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s5_member_1 } - /* { dg-begin-multiline-output "" } struct s5 { int member_1 (int one, const char **two, float three); }; ~~~~~~~~~~~~~^~~ { dg-end-multiline-output "" } */ @@ -118,17 +112,14 @@ struct s6 { int member_1 (int one, const char **two, float three); }; // { dg-li int test_6 (int first, const char *second, float third, s6 *ptr) { - return ptr->member_1 (first, second, third); // { dg-error "no matching function for call to 's6::member_1\\(int&, const char\\*&, float&\\)'" } + return ptr->member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" } /* { dg-begin-multiline-output "" } return ptr->member_1 (first, second, third); - ^ + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "candidate: 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 } - /* { dg-begin-multiline-output "" } - struct s6 { int member_1 (int one, const char **two, float three); }; - ^~~~~~~~ - { dg-end-multiline-output "" } */ - // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s6_member_1 } + // { dg-message "initializing argument 2 of 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 } /* { dg-begin-multiline-output "" } struct s6 { int member_1 (int one, const char **two, float three); }; ~~~~~~~~~~~~~^~~ @@ -168,17 +159,14 @@ struct s8 { static int member_1 (int one, T two, float three); }; // { dg-line s int test_8 (int first, const char *second, float third) { - return s8 ::member_1 (first, second, third); // { dg-error "no matching function for call to 's8::member_1\\(int&, const char\\*&, float&\\)'" } + return s8 ::member_1 (first, second, third); // { dg-error "47: cannot convert 'const char\\*' to 'const char\\*\\*'" } /* { dg-begin-multiline-output "" } return s8 ::member_1 (first, second, third); - ^ - { dg-end-multiline-output "" } */ - // { dg-message "candidate: 'static int s8::member_1\\(int, T, float\\)" "" { target *-*-* } s8_member_1 } - /* { dg-begin-multiline-output "" } - struct s8 { static int member_1 (int one, T two, float three); }; - ^~~~~~~~ + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s8_member_1 } + // { dg-message "initializing argument 2 of 'static int s8::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s8_member_1 } /* { dg-begin-multiline-output "" } struct s8 { static int member_1 (int one, T two, float three); }; ~~^~~ @@ -193,19 +181,43 @@ struct s9 { int member_1 (int one, T two, float three); }; // { dg-line s9_membe int test_9 (int first, const char *second, float third) { s9 inst; - return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9::member_1\\(int&, const char\\*&, float&\\)'" } + return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" } /* { dg-begin-multiline-output "" } return inst.member_1 (first, second, third); - ^ + ^~~~~~ + | + const char* { dg-end-multiline-output "" } */ - // { dg-message "candidate: 'int s9::member_1\\(int, T, float\\)" "" { target *-*-* } s9_member_1 } + // { dg-message "initializing argument 2 of 'int s9::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s9_member_1 } /* { dg-begin-multiline-output "" } struct s9 { int member_1 (int one, T two, float three); }; - ^~~~~~~~ + ~~^~~ { dg-end-multiline-output "" } */ - // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s9_member_1 } +} + +/* Overloaded operator (with one candidate). */ + +struct s10 {}; + +extern int operator- (const s10&, int); // { dg-line s10_operator } + +int test_10 () +{ + s10 v10_a, v10_b; + + return v10_a - v10_b; // { dg-error "no match for" } /* { dg-begin-multiline-output "" } - struct s9 { int member_1 (int one, T two, float three); }; - ~~^~~ + return v10_a - v10_b; + ~~~~~~^~~~~~~ + { dg-end-multiline-output "" } */ + // { dg-message "candidate" "" { target *-*-* } s10_operator } + /* { dg-begin-multiline-output "" } + extern int operator- (const s10&, int); + ^~~~~~~~ + { dg-end-multiline-output "" } */ + // { dg-message "no known conversion for argument 2 from" "" { target *-*-* } s10_operator } + /* { dg-begin-multiline-output "" } + extern int operator- (const s10&, int); + ^~~ { dg-end-multiline-output "" } */ } diff --git a/gcc/testsuite/g++.dg/expr/pmf-1.C b/gcc/testsuite/g++.dg/expr/pmf-1.C index e6b72198281..35ebe5290f4 100644 --- a/gcc/testsuite/g++.dg/expr/pmf-1.C +++ b/gcc/testsuite/g++.dg/expr/pmf-1.C @@ -14,6 +14,6 @@ struct A { void (A::*p)() = &A::f; void (A::*q)() = &(A::f); // { dg-error "parenthesized" } - foo(&g); // { dg-error "no matching" } + foo(&g); // { dg-error "cannot convert" } } }; diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C index 588251d3cf0..f1591b2e5c7 100644 --- a/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C +++ b/gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C @@ -24,7 +24,7 @@ struct D : public B { void h(D* pd) { - pd->f(1); // { dg-error "no matching" } D::f(struct B) hides B::f(int) + pd->f(1); // { dg-error "cannot convert" } D::f(struct B) hides B::f(int) } int main () { return 0; } diff --git a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C index a7c0fbea974..ccbd1f58b1b 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/conversion11.C @@ -22,6 +22,6 @@ void DoSomething(Ding A); void foo(Something* pX) { DoSomething(1); // { dg-error "could not convert" } - pX->DoSomething(1); // { dg-error "no matching" } - (*pX).DoSomething(1); // { dg-error "no matching" } + pX->DoSomething(1); // { dg-error "cannot convert" } + (*pX).DoSomething(1); // { dg-error "cannot convert" } } diff --git a/gcc/testsuite/g++.old-deja/g++.law/arg11.C b/gcc/testsuite/g++.old-deja/g++.law/arg11.C index bd88844e486..d68f1842cca 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/arg11.C +++ b/gcc/testsuite/g++.old-deja/g++.law/arg11.C @@ -17,6 +17,6 @@ int foo(S *o) { // Neither call has a usable constructor for conversions of char[5] to Ack. function("adsf");// { dg-error "could not convert" } - o->method("adsf");// { dg-error "no matching" } + o->method("adsf");// { dg-error "cannot convert" } return 0; } diff --git a/gcc/testsuite/g++.old-deja/g++.law/arm9.C b/gcc/testsuite/g++.old-deja/g++.law/arm9.C index c603aab01fc..ab18189dde3 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/arm9.C +++ b/gcc/testsuite/g++.old-deja/g++.law/arm9.C @@ -23,7 +23,7 @@ void B::set (f2 f) { std::cout << "called B\n|no known conversion";} // { dg-mes int main() { B b; - b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "match" } + b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "cannot convert" } // but 13.1 of ARM clearly states that it should call B::set() // or generate an error because overloading works only for // functions within the same scope (first page of chapter 13) diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C index 6a0f1c35c0f..c2377fb2d22 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb131.C @@ -15,6 +15,6 @@ struct a { a::a() { - foo( &junk ); // { dg-error "match" } junk is an unqualified-id. - foo( &bar ); // { dg-error "match" } bar is an unqualified-id. + foo( &junk ); // { dg-error "cannot convert" } junk is an unqualified-id. + foo( &bar ); // { dg-error "cannot convert" } bar is an unqualified-id. } -- 2.30.2