Commit 9fa1b661 by David Malcolm Committed by David Malcolm

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.

From-SVN: r258957
parent 059cc8ac
2018-03-29 David Malcolm <dmalcolm@redhat.com>
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 <paolo.carlini@oracle.com> 2018-03-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/85028 PR c++/85028
......
...@@ -8782,8 +8782,9 @@ convert_for_assignment (tree type, tree rhs, ...@@ -8782,8 +8782,9 @@ convert_for_assignment (tree type, tree rhs,
parmnum, complain, flags); parmnum, complain, flags);
} }
else if (fndecl) else if (fndecl)
error ("cannot convert %qH to %qI for argument %qP to %qD", error_at (EXPR_LOC_OR_LOC (rhs, input_location),
rhstype, type, parmnum, fndecl); "cannot convert %qH to %qI for argument %qP to %qD",
rhstype, type, parmnum, fndecl);
else else
switch (errtype) switch (errtype)
{ {
......
2018-03-29 David Malcolm <dmalcolm@redhat.com>
PR c++/85110
* g++.dg/diagnostic/param-type-mismatch-2.C: New test.
2018-03-29 Jakub Jelinek <jakub@redhat.com> 2018-03-29 Jakub Jelinek <jakub@redhat.com>
PR c++/85108 PR c++/85108
......
// { 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment