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