On Mon, Jul 24, 2017 at 4:04 PM, David Malcolm <dmalc...@redhat.com> wrote: > Amongst other things, this patch kit aims to improve our handling > of mismatched types within function calls. > > For example, given: > > extern int callee_1 (int one, const char *two, float three); > > int test_1 (int first, int second, float third) > { > return callee_1 (first, second, third); > } > > the C++ FE currently reports: > > error: invalid conversion from 'int' to 'const char*' [-fpermissive] > return callee_1 (first, second, third); > ^ > note: initializing argument 2 of 'int callee_1(int, const char*, float)' > extern int callee_1 (int one, const char *two, float three); > ^~~~~~~~ > > when it ought to underline the pertinent parts of the code: > > error: invalid conversion from 'int' to 'const char*' [-fpermissive] > return callee_1 (first, second, third); > ^~~~~~ > note: initializing argument 2 of 'int callee_1(int, const char*, float)' > extern int callee_1 (int one, const char *two, float three); > ^~~~~~~~~~~~~~~ > > The C FE currently does better, underlining the pertinent argument at > the callsite (due to the "vec<location_t> arg_loc" passed around > when the call is created); but, like the C++ frontend, it doesn't > underline the pertinent parameter at the decl of the callee. > > This patch adds a pair of test cases to exercise various cases of > this in the C and C++ frontends, to establish a baseline for how > we currently handle these; the "TODO" comments in the test cases > note the aspects where we could do better (some of which are fixed > by this kit). > > Patches 6 and 7 of the kit fix the parameter highlighting, for > C and C++ respectively (making use of -fblt).
Speaking of mismatched types for arguments to function calls, while you're at it, could you update gcc.dg/Wtraditional-conversion-2.c to use underlining, too? Currently it just checks the message and not any of the location information. > > gcc/testsuite/ChangeLog: > * g++.dg/diagnostic/param-type-mismatch.C: New test acse. > * gcc.dg/param-type-mismatch.c: New test case. > --- > .../g++.dg/diagnostic/param-type-mismatch.C | 162 > +++++++++++++++++++++ > gcc/testsuite/gcc.dg/param-type-mismatch.c | 63 ++++++++ > 2 files changed, 225 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C > create mode 100644 gcc/testsuite/gcc.dg/param-type-mismatch.c > > diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C > b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C > new file mode 100644 > index 0000000..864ead1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C > @@ -0,0 +1,162 @@ > +// { dg-options "-fdiagnostics-show-caret" } > + > +/* A collection of calls where argument 2 is of the wrong type. > + > + TODO: we should put the caret and underline for the diagnostic > + at the second argument, rather than the close paren. > + > + TODO: we should highlight the second parameter of the callee, rather > + than its name. */ > + > +/* decl, with argname. */ > + > +extern int callee_1 (int one, const char *two, float three); // { dg-line > callee_1 } > + > +int test_1 (int first, int second, float third) > +{ > + return callee_1 (first, second, third); // { dg-error "invalid conversion > from 'int' 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); // { dg-line callee_2 } > + > +int test_2 (int first, int second, float third) > +{ > + return callee_2 (first, second, third); // { dg-error "invalid conversion > from 'int' 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) // { dg-line > callee_3 } > +{ > + return callee_2 (one, two, three); > +} > + > +int test_3 (int first, int second, float third) > +{ > + return callee_3 (first, second, third); // { dg-error "invalid conversion > from 'int' 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. */ > + > +struct s4 { static int member_1 (int one, const char *two, float three); }; > + > +int test_4 (int first, int second, float third) > +{ > + return s4::member_1 (first, second, third); // { dg-error "invalid > conversion from 'int' to 'const char\\*'" } > + /* { dg-begin-multiline-output "" } > + return s4::member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + struct s4 { static int member_1 (int one, const char *two, float three); }; > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* non-static member, with argname. */ > + > +struct s5 { int member_1 (int one, const char *two, float three); }; > + > +int test_5 (int first, int second, float third) > +{ > + s5 inst; > + return inst.member_1 (first, second, third); // { dg-error "invalid > conversion from 'int' to 'const char\\*'" } > + /* { dg-begin-multiline-output "" } > + return inst.member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + struct s5 { int member_1 (int one, const char *two, float three); }; > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* Template function. */ > + > +template <typename T> > +int test_6 (int one, T two, float three); > + > +int test_6 (int first, int second, float third) > +{ > + return test_6 <const char *> (first, second, third); // { dg-error "no > matching function" } > + /* { dg-begin-multiline-output "" } > + return test_6 <const char *> (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + return test_6 <const char *> (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + int test_6 (int one, T two, float three); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* Template class, static function. */ > + > +template <typename T> > +struct s7 { static int member_1 (int one, T two, float three); }; > + > +int test_7 (int first, int second, float third) > +{ > + return s7 <const char *>::member_1 (first, second, third); // { dg-error > "invalid conversion from 'int' to 'const char\\*'" } > + /* { dg-begin-multiline-output "" } > + return s7 <const char *>::member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + struct s7 { static int member_1 (int one, T two, float three); }; > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +/* Template class, non-static function. */ > + > +template <typename T> > +struct s8 { int member_1 (int one, T two, float three); }; > + > +int test_8 (int first, int second, float third) > +{ > + s8 <const char *> inst; > + return inst.member_1 (first, second, third); // { dg-error "invalid > conversion from 'int' to 'const char\\*'" } > + /* { dg-begin-multiline-output "" } > + return inst.member_1 (first, second, third); > + ^ > + { dg-end-multiline-output "" } */ > + /* { dg-begin-multiline-output "" } > + struct s8 { int member_1 (int one, T two, float three); }; > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > +} > + > +// TODO: template callsite > diff --git a/gcc/testsuite/gcc.dg/param-type-mismatch.c > b/gcc/testsuite/gcc.dg/param-type-mismatch.c > new file mode 100644 > index 0000000..70ea0bc > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/param-type-mismatch.c > @@ -0,0 +1,63 @@ > +/* { dg-options "-fdiagnostics-show-caret" } */ > + > +/* A collection of calls where argument 2 is of the wrong type. > + > + TODO: we should highlight the second parameter of the callee, rather > + than its name. */ > + > +/* decl, with argname. */ > + > +extern int callee_1 (int one, const char *two, float three); /* { dg-line > callee_1 } */ > + > +int test_1 (int first, int second, float third) > +{ > + return callee_1 (first, second, third); /* { dg-warning "passing argument > 2 of 'callee_1' makes pointer from integer without a cast" } */ > + /* { dg-begin-multiline-output "" } > + return callee_1 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > + /* { dg-message "expected 'const char \\*' but argument is of type 'int'" > "" { 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); /* { dg-line callee_2 } */ > + > +int test_2 (int first, int second, float third) > +{ > + return callee_2 (first, second, third); /* { dg-warning "passing argument > 2 of 'callee_2' makes pointer from integer without a cast" } */ > + /* { dg-begin-multiline-output "" } > + return callee_2 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > + /* { dg-message "expected 'const char \\*' but argument is of type 'int'" > "" { 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) /* { dg-line > callee_3 } */ > +{ > + return callee_2 (one, two, three); > +} > + > +int test_3 (int first, int second, float third) > +{ > + return callee_3 (first, second, third); // { dg-warning "passing argument > 2 of 'callee_3' makes pointer from integer without a cast" } > + /* { dg-begin-multiline-output "" } > + return callee_3 (first, second, third); > + ^~~~~~ > + { dg-end-multiline-output "" } */ > + /* { dg-message "expected 'const char \\*' but argument is of type 'int'" > "" { target *-*-* } callee_3 } */ > + /* { dg-begin-multiline-output "" } > + static int callee_3 (int one, const char *two, float three) > + ^~~~~~~~ > + { dg-end-multiline-output "" } */ > +} > -- > 1.8.5.3 >