From 128fe6cd7d5aa6c3c724b8179bd7e4f0e8d9c97b Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Thu, 29 Mar 2018 14:43:01 +0000 Subject: [PATCH] More underlining of bad arguments (PR c++/85110) 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); ^~~ 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@258957 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 7 + gcc/cp/typeck.c | 5 +- gcc/testsuite/ChangeLog | 5 + .../g++.dg/diagnostic/param-type-mismatch-2.C | 175 +++++++++++++++++++++ 4 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b7a4f4381e4..344105844a6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2018-03-29 David Malcolm + + PR c++/85110 + * typeck.c (convert_for_assignment): When complaining due to + conversions for an argument, attempt to use the location of the + argument. + 2018-03-28 Paolo Carlini PR c++/85028 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d3183b5321d..d454c6c5a29 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8782,8 +8782,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/ChangeLog b/gcc/testsuite/ChangeLog index 788dbaa48c2..912d406b5c4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-03-29 David Malcolm + + PR c++/85110 + * g++.dg/diagnostic/param-type-mismatch-2.C: New test. + 2018-03-29 Jakub Jelinek PR c++/85108 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 00000000000..ae84248b417 --- /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 +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 (first, second, third); // { dg-line test_7_usage } + // { dg-error "no matching function" "" { target *-*-* } test_7_usage } + /* { dg-begin-multiline-output "" } + return test_7 (first, second, third); + ^ + { dg-end-multiline-output "" } */ + // { dg-message "candidate: 'template 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 (first, second, third); + ^~~~~~ + { dg-end-multiline-output "" } */ +} + +/* Template class, static function. */ + +template +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 ::member_1 (first, second, third); // { dg-error "no matching function for call to 's8::member_1\\(int&, const char\\*&, float&\\)'" } + /* { 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); }; + ^~~~~~~~ + { 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 +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 inst; + return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9::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::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 +} -- 2.11.4.GIT