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
>

Reply via email to