OK.
On Wed, Mar 28, 2018 at 4:44 PM, David Malcolm <dmalc...@redhat.com> wrote: > As of r256448, the C++ frontend underlines many bad arguments in its > diagnostics; those where perform_overload_resolution returns a > non-NULL candidate, but there's a failure in convert_like_real. > > However, for the case where perform_overload_resolution fails, but > there's a single non-viable candidate, the error is diagnosed by > cp_build_function_call_vec, and that currently doesn't underline > the bad argument: > > $ cat test.cc > void callee (int one, const char **two, int three); > > void > caller (const char *fmt) > { > callee (1, fmt, 3); > } > > We emit: > > $ g++ test.cc > test.cc: In function 'void caller(const char*)': > test.cc:6:20: error: cannot convert 'const char*' to 'const char**' for > argument '2' to 'void callee(int, const char**, int)' > callee (1, fmt, 3); > ^ > > It's going through convert_for_assignment, and > implicitly using input_location. > > This patch updates convert_for_assignment for this case, using > an EXPR_LOCATION if there is one, or falling back to input_location > otherwise, underlining the argument in question: > > test.cc: In function 'void caller(const char*)': > test.cc:6:14: error: cannot convert 'const char*' to 'const char**' for > argument '2' to 'void callee(int, const char**, int)' > callee (1, fmt, 3); > ^~~ > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu; adds > 117 PASS results to g++.sum. > > Not a regression as such, but I've been calling out the underlined > arguments as a feature of gcc 8, so would be good to fix. > > OK for trunk? > > gcc/cp/ChangeLog: > PR c++/85110 > * typeck.c (convert_for_assignment): When complaining due to > conversions for an argument, attempt to use the location of the > argument. > > gcc/testsuite/ChangeLog: > PR c++/85110 > * g++.dg/diagnostic/param-type-mismatch-2.C: New test. > --- > gcc/cp/typeck.c | 5 +- > .../g++.dg/diagnostic/param-type-mismatch-2.C | 175 > +++++++++++++++++++++ > 2 files changed, 178 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C > > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c > index 0c2ebd1..e733c79 100644 > --- a/gcc/cp/typeck.c > +++ b/gcc/cp/typeck.c > @@ -8781,8 +8781,9 @@ convert_for_assignment (tree type, tree rhs, > parmnum, complain, flags); > } > else if (fndecl) > - error ("cannot convert %qH to %qI for argument %qP to %qD", > - rhstype, type, parmnum, fndecl); > + error_at (EXPR_LOC_OR_LOC (rhs, input_location), > + "cannot convert %qH to %qI for argument %qP to %qD", > + rhstype, type, parmnum, fndecl); > else > switch (errtype) > { > diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C > b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C > new file mode 100644 > index 0000000..ae84248 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C > @@ -0,0 +1,175 @@ > +// { dg-options "-fdiagnostics-show-caret" } > + > +/* A collection of calls where argument 2 is of the wrong type. */ > + > +/* decl, with argname. */ > + > +extern int callee_1 (int one, const char **two, float three); > + > +int test_1 (int first, const char *second, float third) > +{ > + return callee_1 (first, second, third); // { dg-error "27: cannot convert > 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int > callee_1\\(int, const char\\*\\*, float\\)'" } > + /* { dg-begin-multiline-output "" } > + return callee_1 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* decl, without argname. */ > + > +extern int callee_2 (int, const char **, float); > + > +int test_2 (int first, const char *second, float third) > +{ > + return callee_2 (first, second, third); // { dg-error "27: cannot convert > 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int > callee_2\\(int, const char\\*\\*, float\\)'" } > + /* { dg-begin-multiline-output "" } > + return callee_2 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* defn, with argname. */ > + > +static int callee_3 (int one, const char **two, float three) > +{ > + return callee_2 (one, two, three); > +} > + > +int test_3 (int first, const char *second, float third) > +{ > + return callee_3 (first, second, third); // { dg-error "27: cannot convert > 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int > callee_3\\(int, const char\\*\\*, float\\)'" } > + /* { dg-begin-multiline-output "" } > + return callee_3 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* static member, with argname. */ > + > +struct s4 { static int member_1 (int one, const char **two, float three); }; > // { dg-line s4_member_1 } > + > +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&\\)'" } > + /* { dg-begin-multiline-output "" } > + return s4::member_1 (first, second, third); > + ^ > + { 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 } > + // TODO: underline the pertinent param > +} > + > +/* non-static member, with argname. */ > + > +struct s5 { int member_1 (int one, const char **two, float three); }; // { > dg-line s5_member_1 } > + > +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&\\)'" } > + /* { dg-begin-multiline-output "" } > + return inst.member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + // { dg-message "candidate: '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 } > + // TODO: underline the pertinent param > +} > + > +/* non-static member, with argname, via a ptr. */ > + > +struct s6 { int member_1 (int one, const char **two, float three); }; // { > dg-line s6_member_1 } > + > +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&\\)'" } > + /* { dg-begin-multiline-output "" } > + return ptr->member_1 (first, second, third); > + ^ > + { 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 } > + // TODO: underline the pertinent param > +} > + > +/* Template function. */ > + > +template <typename T> > +int test_7 (int one, T two, float three); // { dg-line test_7_decl } > + > +int test_7 (int first, const char *second, float third) > +{ > + return test_7 <const char **> (first, second, third); // { dg-line > test_7_usage } > + // { dg-error "no matching function" "" { target *-*-* } test_7_usage } > + /* { dg-begin-multiline-output "" } > + return test_7 <const char **> (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + // { dg-message "candidate: 'template<class T> int test_7\\(int, T, > float\\)'" "" { target *-*-* } test_7_decl } > + /* { dg-begin-multiline-output "" } > + int test_7 (int one, T two, float three); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > + // { dg-message "template argument deduction/substitution failed:" "" { > target *-*-* } test_7_decl } > + // { dg-message "cannot convert 'second' \\(type 'const char\\*'\\) to > type 'const char\\*\\*'" "" { target *-*-* } test_7_usage } > + /* { dg-begin-multiline-output "" } > + return test_7 <const char **> (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* Template class, static function. */ > + > +template <typename T> > +struct s8 { static int member_1 (int one, T two, float three); }; // { > dg-line s8_member_1 } > + > +int test_8 (int first, const char *second, float third) > +{ > + return s8 <const char **>::member_1 (first, second, third); // { dg-error > "no matching function for call to 's8<const char\\*\\*>::member_1\\(int&, > const char\\*&, float&\\)'" } > + /* { dg-begin-multiline-output "" } > + return s8 <const char **>::member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + // { dg-message "candidate: 'static int s8<T>::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); }; > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > + // { dg-message "no known conversion for argument 2 from 'const char\\*' > to 'const char\\*\\*'" "" { target *-*-* } s8_member_1 } > + // TODO: underline the pertinent param > +} > + > +/* Template class, non-static function. */ > + > +template <typename T> > +struct s9 { int member_1 (int one, T two, float three); }; // { dg-line > s9_member_1 } > + > +int test_9 (int first, const char *second, float third) > +{ > + s9 <const char **> inst; > + return inst.member_1 (first, second, third); // { dg-error "no matching > function for call to 's9<const char\\*\\*>::member_1\\(int&, const char\\*&, > float&\\)'" } > + /* { dg-begin-multiline-output "" } > + return inst.member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + // { dg-message "candidate: 'int s9<T>::member_1\\(int, T, float\\)" "" { > 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 } > + // TODO: underline the pertinent param > +} > -- > 1.8.5.3 >