v2: Show pertinent parameter (PR c++/85110)

Message ID 1523044468-55815-1-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series
  • v2: Show pertinent parameter (PR c++/85110)
Related show

Commit Message

David Malcolm April 6, 2018, 7:54 p.m.
On Thu, 2018-03-29 at 09:20 -0400, Jason Merrill wrote:
> On Wed, Mar 28, 2018 at 4:44 PM, David Malcolm <dmalcolm@redhat.com>

> wrote:

> > This followup patch updates the specific error-handling path

> > to add a note showing the pertinent parameter decl, taking

> > the output from:

> > 

> > 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);

> >               ^~~

> > 

> > to:

> > 

> > 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);

> >               ^~~

> > test.cc:1:36: note:   initializing argument 2 of 'void callee(int,

> > const char**, int)'

> >  void callee (int one, const char **two, int three);

> >                        ~~~~~~~~~~~~~^~~

> > 

> > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu; adds

> > a further 18 PASS results to g++.sum.

> > 

> > Again, 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

> >         * call.c (get_fndecl_argument_location): Make non-static.

> >         * cp-tree.h (get_fndecl_argument_location): New decl.

> >         * typeck.c (convert_for_assignment): When complaining due

> > to

> >         conversions for an argument, show the location of the

> > parameter

> >         within the decl.

> > 

> > gcc/testsuite/ChangeLog:

> >         PR c++/85110

> >         * g++.dg/diagnostic/param-type-mismatch-2.C: Update for the

> > cases

> >         where we now show the pertinent parameter.

> > ---

> >  gcc/cp/call.c                                       |  2 +-

> >  gcc/cp/cp-tree.h                                    |  2 ++

> >  gcc/cp/typeck.c                                     | 10 +++++++

> > ---

> >  .../g++.dg/diagnostic/param-type-mismatch-2.C       | 21

> > ++++++++++++++++++---

> >  4 files changed, 28 insertions(+), 7 deletions(-)

> > 

> > diff --git a/gcc/cp/call.c b/gcc/cp/call.c

> > index 1a87f99..e1a0639 100644

> > --- a/gcc/cp/call.c

> > +++ b/gcc/cp/call.c

> > @@ -6598,7 +6598,7 @@ maybe_print_user_conv_context (conversion

> > *convs)

> >     ARGNUM is zero based, -1 indicates the `this' argument of a

> > method.

> >     Return the location of the FNDECL itself if there are

> > problems.  */

> > 

> > -static location_t

> > +location_t

> >  get_fndecl_argument_location (tree fndecl, int argnum)

> >  {

> >    int i;

> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h

> > index d5382c2..b45880d 100644

> > --- a/gcc/cp/cp-tree.h

> > +++ b/gcc/cp/cp-tree.h

> > @@ -5965,6 +5965,8 @@ extern bool

> > can_convert_arg                       (tree, tree, tree, int,

> >                                                  tsubst_flags_t);

> >  extern bool can_convert_arg_bad                        (tree,

> > tree, tree, int,

> >                                                  tsubst_flags_t);

> > +extern location_t get_fndecl_argument_location  (tree, int);

> > +

> > 

> >  /* A class for recording information about access failures (e.g.

> > private

> >     fields), so that we can potentially supply a fix-it hint about

> > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c

> > index e733c79..742b2e9 100644

> > --- a/gcc/cp/typeck.c

> > +++ b/gcc/cp/typeck.c

> > @@ -8781,9 +8781,13 @@ convert_for_assignment (tree type, tree rhs,

> >                                                    parmnum,

> > complain, flags);

> >                 }

> >               else if (fndecl)

> > -               error_at (EXPR_LOC_OR_LOC (rhs, input_location),

> > -                         "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);

> > +                 inform (get_fndecl_argument_location (fndecl,

> > parmnum),

> > +                         "  initializing argument %P of %qD",

> > parmnum, fndecl);

> 

> If you're adding the inform, you don't need the %P of %D in the

> initial error.

> 

> Jason


Thanks.  Here's an updated version of the patch which removes them.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu; adds
18 PASS results to g++.sum.

OK for trunk?

gcc/cp/ChangeLog:
	PR c++/85110
	* call.c (get_fndecl_argument_location): Make non-static.
	* cp-tree.h (get_fndecl_argument_location): New decl.
	* typeck.c (convert_for_assignment): When complaining due to
	conversions for an argument, show the location of the parameter
	within the decl.

gcc/testsuite/ChangeLog:
	PR c++/85110
	* g++.dg/cpp1z/direct-enum-init1.C: Update for the cases
	where we now show the pertinent parameter.
	* g++.dg/diagnostic/aka2.C: Likewise.
	* g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.
---
 gcc/cp/call.c                                      |  2 +-
 gcc/cp/cp-tree.h                                   |  2 ++
 gcc/cp/typeck.c                                    | 10 +++++---
 gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C     |  6 ++---
 gcc/testsuite/g++.dg/diagnostic/aka2.C             |  2 +-
 .../g++.dg/diagnostic/param-type-mismatch-2.C      | 27 +++++++++++++++++-----
 6 files changed, 35 insertions(+), 14 deletions(-)

-- 
1.8.5.3

Comments

Jason Merrill April 9, 2018, 7:04 p.m. | #1
OK.

On Fri, Apr 6, 2018 at 3:54 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Thu, 2018-03-29 at 09:20 -0400, Jason Merrill wrote:

>> On Wed, Mar 28, 2018 at 4:44 PM, David Malcolm <dmalcolm@redhat.com>

>> wrote:

>> > This followup patch updates the specific error-handling path

>> > to add a note showing the pertinent parameter decl, taking

>> > the output from:

>> >

>> > 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);

>> >               ^~~

>> >

>> > to:

>> >

>> > 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);

>> >               ^~~

>> > test.cc:1:36: note:   initializing argument 2 of 'void callee(int,

>> > const char**, int)'

>> >  void callee (int one, const char **two, int three);

>> >                        ~~~~~~~~~~~~~^~~

>> >

>> > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu; adds

>> > a further 18 PASS results to g++.sum.

>> >

>> > Again, 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

>> >         * call.c (get_fndecl_argument_location): Make non-static.

>> >         * cp-tree.h (get_fndecl_argument_location): New decl.

>> >         * typeck.c (convert_for_assignment): When complaining due

>> > to

>> >         conversions for an argument, show the location of the

>> > parameter

>> >         within the decl.

>> >

>> > gcc/testsuite/ChangeLog:

>> >         PR c++/85110

>> >         * g++.dg/diagnostic/param-type-mismatch-2.C: Update for the

>> > cases

>> >         where we now show the pertinent parameter.

>> > ---

>> >  gcc/cp/call.c                                       |  2 +-

>> >  gcc/cp/cp-tree.h                                    |  2 ++

>> >  gcc/cp/typeck.c                                     | 10 +++++++

>> > ---

>> >  .../g++.dg/diagnostic/param-type-mismatch-2.C       | 21

>> > ++++++++++++++++++---

>> >  4 files changed, 28 insertions(+), 7 deletions(-)

>> >

>> > diff --git a/gcc/cp/call.c b/gcc/cp/call.c

>> > index 1a87f99..e1a0639 100644

>> > --- a/gcc/cp/call.c

>> > +++ b/gcc/cp/call.c

>> > @@ -6598,7 +6598,7 @@ maybe_print_user_conv_context (conversion

>> > *convs)

>> >     ARGNUM is zero based, -1 indicates the `this' argument of a

>> > method.

>> >     Return the location of the FNDECL itself if there are

>> > problems.  */

>> >

>> > -static location_t

>> > +location_t

>> >  get_fndecl_argument_location (tree fndecl, int argnum)

>> >  {

>> >    int i;

>> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h

>> > index d5382c2..b45880d 100644

>> > --- a/gcc/cp/cp-tree.h

>> > +++ b/gcc/cp/cp-tree.h

>> > @@ -5965,6 +5965,8 @@ extern bool

>> > can_convert_arg                       (tree, tree, tree, int,

>> >                                                  tsubst_flags_t);

>> >  extern bool can_convert_arg_bad                        (tree,

>> > tree, tree, int,

>> >                                                  tsubst_flags_t);

>> > +extern location_t get_fndecl_argument_location  (tree, int);

>> > +

>> >

>> >  /* A class for recording information about access failures (e.g.

>> > private

>> >     fields), so that we can potentially supply a fix-it hint about

>> > diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c

>> > index e733c79..742b2e9 100644

>> > --- a/gcc/cp/typeck.c

>> > +++ b/gcc/cp/typeck.c

>> > @@ -8781,9 +8781,13 @@ convert_for_assignment (tree type, tree rhs,

>> >                                                    parmnum,

>> > complain, flags);

>> >                 }

>> >               else if (fndecl)

>> > -               error_at (EXPR_LOC_OR_LOC (rhs, input_location),

>> > -                         "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);

>> > +                 inform (get_fndecl_argument_location (fndecl,

>> > parmnum),

>> > +                         "  initializing argument %P of %qD",

>> > parmnum, fndecl);

>>

>> If you're adding the inform, you don't need the %P of %D in the

>> initial error.

>>

>> Jason

>

> Thanks.  Here's an updated version of the patch which removes them.

>

> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu; adds

> 18 PASS results to g++.sum.

>

> OK for trunk?

>

> gcc/cp/ChangeLog:

>         PR c++/85110

>         * call.c (get_fndecl_argument_location): Make non-static.

>         * cp-tree.h (get_fndecl_argument_location): New decl.

>         * typeck.c (convert_for_assignment): When complaining due to

>         conversions for an argument, show the location of the parameter

>         within the decl.

>

> gcc/testsuite/ChangeLog:

>         PR c++/85110

>         * g++.dg/cpp1z/direct-enum-init1.C: Update for the cases

>         where we now show the pertinent parameter.

>         * g++.dg/diagnostic/aka2.C: Likewise.

>         * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.

> ---

>  gcc/cp/call.c                                      |  2 +-

>  gcc/cp/cp-tree.h                                   |  2 ++

>  gcc/cp/typeck.c                                    | 10 +++++---

>  gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C     |  6 ++---

>  gcc/testsuite/g++.dg/diagnostic/aka2.C             |  2 +-

>  .../g++.dg/diagnostic/param-type-mismatch-2.C      | 27 +++++++++++++++++-----

>  6 files changed, 35 insertions(+), 14 deletions(-)

>

> diff --git a/gcc/cp/call.c b/gcc/cp/call.c

> index f2ada27..53850c1 100644

> --- a/gcc/cp/call.c

> +++ b/gcc/cp/call.c

> @@ -6595,7 +6595,7 @@ maybe_print_user_conv_context (conversion *convs)

>     ARGNUM is zero based, -1 indicates the `this' argument of a method.

>     Return the location of the FNDECL itself if there are problems.  */

>

> -static location_t

> +location_t

>  get_fndecl_argument_location (tree fndecl, int argnum)

>  {

>    int i;

> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h

> index dbe34c0..0538351 100644

> --- a/gcc/cp/cp-tree.h

> +++ b/gcc/cp/cp-tree.h

> @@ -5994,6 +5994,8 @@ extern bool can_convert_arg                       (tree, tree, tree, int,

>                                                  tsubst_flags_t);

>  extern bool can_convert_arg_bad                        (tree, tree, tree, int,

>                                                  tsubst_flags_t);

> +extern location_t get_fndecl_argument_location  (tree, int);

> +

>

>  /* A class for recording information about access failures (e.g. private

>     fields), so that we can potentially supply a fix-it hint about

> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c

> index e5ad54d..b449b1f 100644

> --- a/gcc/cp/typeck.c

> +++ b/gcc/cp/typeck.c

> @@ -8785,9 +8785,13 @@ convert_for_assignment (tree type, tree rhs,

>                                                    parmnum, complain, flags);

>                 }

>               else if (fndecl)

> -               error_at (EXPR_LOC_OR_LOC (rhs, input_location),

> -                         "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",

> +                           rhstype, type);

> +                 inform (get_fndecl_argument_location (fndecl, parmnum),

> +                         "  initializing argument %P of %qD", parmnum, fndecl);

> +               }

>               else

>                 switch (errtype)

>                   {

> diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C

> index d8cffb4..fa2934e 100644

> --- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C

> +++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C

> @@ -40,7 +40,7 @@ foo ()

>    D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }

>    E *e5 = new E { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }

>                         // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }

> -  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }

> +  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E'" }

>    bar (E { 9 });       // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

>    V v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }

>    V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

> @@ -106,7 +106,7 @@ foo2 ()

>    D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }

>    E *e5 = new E { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }

>                         // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }

> -  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }

> +  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E'" }

>    bar (E { 9 });       // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

>    V v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }

>    V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

> @@ -174,7 +174,7 @@ foo3 ()

>    K *d7 = new K { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }

>    L *e5 = new L { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }

>                         // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }

> -  bar3 ({ 10 });       // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }

> +  bar3 ({ 10 });       // { dg-error "cannot convert \[^\n\r]* to 'E'" }

>    bar3 (E { 9 });      // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

>    M v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }

>    M v2 = { L { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }

> diff --git a/gcc/testsuite/g++.dg/diagnostic/aka2.C b/gcc/testsuite/g++.dg/diagnostic/aka2.C

> index a43f9e3..d7a3b35 100644

> --- a/gcc/testsuite/g++.dg/diagnostic/aka2.C

> +++ b/gcc/testsuite/g++.dg/diagnostic/aka2.C

> @@ -11,7 +11,7 @@ int foo(t1 *);

>  void test_1 () {

>    t2 pos;

>

> -  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'} for argument '1' to 'int foo\\(t1\\*\\)'" }

> +  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'}" }

>  }

>

>  /* Exercise %T.  */

> 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 ae84248..c3b6f00 100644

> --- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C

> +++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C

> @@ -4,44 +4,59 @@

>

>  /* decl, with argname.  */

>

> -extern int callee_1 (int one, const char **two, float three);

> +extern int callee_1 (int one, const char **two, float three); // { dg-line callee_1 }

>

>  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\\)'" }

> +  return callee_1 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }

>    /* { dg-begin-multiline-output "" }

>     return callee_1 (first, second, third);

>                             ^~~~~~

>       { dg-end-multiline-output "" } */

> +  // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_1 }

> +  /* { dg-begin-multiline-output "" }

> + extern int callee_1 (int one, const char **two, float three);

> +                               ~~~~~~~~~~~~~^~~

> +     { dg-end-multiline-output "" } */

>  }

>

>  /* decl, without argname.  */

>

> -extern int callee_2 (int, const char **, float);

> +extern int callee_2 (int, const char **, float); // { dg-line callee_2 }

>

>  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\\)'" }

> +  return callee_2 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }

>    /* { dg-begin-multiline-output "" }

>     return callee_2 (first, second, third);

>                             ^~~~~~

>       { dg-end-multiline-output "" } */

> +  // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_2 }

> +  /* { dg-begin-multiline-output "" }

> + extern int callee_2 (int, const char **, float);

> +                           ^~~~~~~~~~~~~

> +     { dg-end-multiline-output "" } */

>  }

>

>  /* defn, with argname.  */

>

> -static int callee_3 (int one, const char **two, float three)

> +static int callee_3 (int one, const char **two, float three) // { dg-line callee_3 }

>  {

>    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\\)'" }

> +  return callee_3 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }

>    /* { dg-begin-multiline-output "" }

>     return callee_3 (first, second, third);

>                             ^~~~~~

>       { dg-end-multiline-output "" } */

> +  // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_3 }

> +  /* { dg-begin-multiline-output "" }

> + static int callee_3 (int one, const char **two, float three)

> +                               ~~~~~~~~~~~~~^~~

> +     { dg-end-multiline-output "" } */

>  }

>

>  /* static member, with argname.  */

> --

> 1.8.5.3

>

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f2ada27..53850c1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6595,7 +6595,7 @@  maybe_print_user_conv_context (conversion *convs)
    ARGNUM is zero based, -1 indicates the `this' argument of a method.
    Return the location of the FNDECL itself if there are problems.  */
 
-static location_t
+location_t
 get_fndecl_argument_location (tree fndecl, int argnum)
 {
   int i;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index dbe34c0..0538351 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5994,6 +5994,8 @@  extern bool can_convert_arg			(tree, tree, tree, int,
 						 tsubst_flags_t);
 extern bool can_convert_arg_bad			(tree, tree, tree, int,
 						 tsubst_flags_t);
+extern location_t get_fndecl_argument_location  (tree, int);
+
 
 /* A class for recording information about access failures (e.g. private
    fields), so that we can potentially supply a fix-it hint about
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e5ad54d..b449b1f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8785,9 +8785,13 @@  convert_for_assignment (tree type, tree rhs,
 						   parmnum, complain, flags);
 		}
 	      else if (fndecl)
-		error_at (EXPR_LOC_OR_LOC (rhs, input_location),
-			  "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",
+			    rhstype, type);
+		  inform (get_fndecl_argument_location (fndecl, parmnum),
+			  "  initializing argument %P of %qD", parmnum, fndecl);
+		}
 	      else
 		switch (errtype)
 		  {
diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
index d8cffb4..fa2934e 100644
--- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
@@ -40,7 +40,7 @@  foo ()
   D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
   E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
-  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E'" }
   bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
   V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
   V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
@@ -106,7 +106,7 @@  foo2 ()
   D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
   E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
-  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E'" }
   bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
   V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
   V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
@@ -174,7 +174,7 @@  foo3 ()
   K *d7 = new K { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
   L *e5 = new L { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++17 } .-1 }
-  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to 'E'" }
   bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
   M v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
   M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka2.C b/gcc/testsuite/g++.dg/diagnostic/aka2.C
index a43f9e3..d7a3b35 100644
--- a/gcc/testsuite/g++.dg/diagnostic/aka2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/aka2.C
@@ -11,7 +11,7 @@  int foo(t1 *);
 void test_1 () {
   t2 pos;
 
-  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'} for argument '1' to 'int foo\\(t1\\*\\)'" }
+  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'}" }
 }
 
 /* Exercise %T.  */
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 ae84248..c3b6f00 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -4,44 +4,59 @@ 
 
 /* decl, with argname.  */
 
-extern int callee_1 (int one, const char **two, float three);
+extern int callee_1 (int one, const char **two, float three); // { dg-line callee_1 }
 
 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\\)'" }
+  return callee_1 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_1 (first, second, third);
                            ^~~~~~
      { dg-end-multiline-output "" } */
+  // { dg-message "initializing argument 2 of 'int callee_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_1 }
+  /* { dg-begin-multiline-output "" }
+ extern int callee_1 (int one, const char **two, float three);
+                               ~~~~~~~~~~~~~^~~
+     { dg-end-multiline-output "" } */
 }
 
 /* decl, without argname.  */
 
-extern int callee_2 (int, const char **, float);
+extern int callee_2 (int, const char **, float); // { dg-line callee_2 }
 
 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\\)'" }
+  return callee_2 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_2 (first, second, third);
                            ^~~~~~
      { dg-end-multiline-output "" } */
+  // { dg-message "initializing argument 2 of 'int callee_2\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_2 }
+  /* { dg-begin-multiline-output "" }
+ extern int callee_2 (int, const char **, float);
+                           ^~~~~~~~~~~~~
+     { dg-end-multiline-output "" } */
 }
 
 /* defn, with argname.  */
 
-static int callee_3 (int one, const char **two, float three)
+static int callee_3 (int one, const char **two, float three) // { dg-line callee_3 }
 {
   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\\)'" }
+  return callee_3 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return callee_3 (first, second, third);
                            ^~~~~~
      { dg-end-multiline-output "" } */
+  // { dg-message "initializing argument 2 of 'int callee_3\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } callee_3 }
+  /* { dg-begin-multiline-output "" }
+ static int callee_3 (int one, const char **two, float three)
+                               ~~~~~~~~~~~~~^~~
+     { dg-end-multiline-output "" } */
 }
 
 /* static member, with argname.  */