From a9fe04327a7c24634a3657639d661a04317dbdf7 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 18 Jul 2017 17:15:11 -0400 Subject: [PATCH 06/27] C: use BLT to highlight parameter of callee decl for mismatching types This patch to the C frontend uses the BLT infrastructure to improve: 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); } from: warning: passing argument 2 of 'callee_1' makes pointer from integer without a cast [-Wint-conversion] return callee_1 (first, second, third); ^~~~~~ note: expected 'const char *' but argument is of type 'int' extern int callee_1 (int one, const char *two, float three); ^~~~~~~~ to: warning: passing argument 2 of 'callee_1' makes pointer from integer without a cast [-Wint-conversion] return callee_1 (first, second, third); ^~~~~~ note: expected 'const char *' but argument is of type 'int' extern int callee_1 (int one, const char *two, float three); ^~~~~~~~~~~~~~~ by locating the pertinent parameter within the decl, by traversing the BLT tree (if present). gcc/c/ChangeLog: * c-typeck.c: Include "blt.h". (get_fndecl_argument_location): New function. (convert_for_assignment): Replace calls to "inform" with... (inform_for_arg): ...this new function, attempting to highlight the pertinent parameter. gcc/testsuite/ChangeLog: * gcc.dg/param-type-mismatch.c: Add -fblt to options. Update expected underlining to show the pertinent parameters. --- gcc/c/c-typeck.c | 63 ++++++++++++++++++++++++------ gcc/testsuite/gcc.dg/param-type-mismatch.c | 13 +++--- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 4d067e9..c37cc33 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "spellcheck-tree.h" #include "gcc-rich-location.h" #include "asan.h" +#include "blt.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -6112,6 +6113,53 @@ maybe_warn_string_init (location_t loc, tree type, struct c_expr expr) "array initialized from parenthesized string constant"); } +/* Attempt to locate the parameter with the given index within FNDECL, + returning LOC if it can't be found (or blt was not enabled). */ + +static location_t +get_fndecl_argument_location (tree fundecl, int argnum, location_t loc) +{ + blt_node *node = blt_get_node_for_tree (fundecl); + if (!node) + return loc; + + if (node->get_kind () != BLT_DIRECT_DECLARATOR) + return loc; + + /* We expect a parameter-list containing parameter-declaration. */ + node = node->get_first_child_of_kind (BLT_PARAMETER_LIST); + if (!node) + return loc; + + auto_vec params; + node->get_children_of_kind (params, BLT_PARAMETER_DECLARATION); + + if (argnum >= (int)params.length ()) + return loc; + + blt_node *param = params[argnum]; + return param->get_range (); +} + +/* Issue a note about a mismatching argument for parameter PARMNUM + to FUNDECL, for types EXPECTED_TYPE and ACTUAL_TYPE. + Attempt to issue the note at the pertinent parameter of the decl; + failing that issue it at the location of FUNDECL; failing that + issue it at PLOC. */ + +static void +inform_for_arg (tree fundecl, location_t ploc, int parmnum, + tree expected_type, tree actual_type) +{ + location_t loc = (fundecl && !DECL_IS_BUILTIN (fundecl) + ? DECL_SOURCE_LOCATION (fundecl) : ploc); + loc = get_fndecl_argument_location (fundecl, parmnum - 1, loc); + + inform (loc, + "expected %qT but argument is of type %qT", + expected_type, actual_type); +} + /* Convert value RHS to type TYPE as preparation for an assignment to an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the original type of RHS; this differs from TREE_TYPE (RHS) for enum @@ -6183,10 +6231,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, { \ case ic_argpass: \ if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \ - inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ - ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \ - "expected %qT but argument is of type %qT", \ - type, rhstype); \ + inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \ break; \ case ic_assign: \ pedwarn (LOCATION, OPT, AS); \ @@ -6212,10 +6257,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, { \ case ic_argpass: \ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \ - inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ - ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \ - "expected %qT but argument is of type %qT", \ - type, rhstype); \ + inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \ break; \ case ic_assign: \ pedwarn (LOCATION, OPT, AS, QUALS); \ @@ -6241,10 +6283,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, { \ case ic_argpass: \ if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \ - inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ - ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \ - "expected %qT but argument is of type %qT", \ - type, rhstype); \ + inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \ break; \ case ic_assign: \ warning_at (LOCATION, OPT, AS, QUALS); \ diff --git a/gcc/testsuite/gcc.dg/param-type-mismatch.c b/gcc/testsuite/gcc.dg/param-type-mismatch.c index 70ea0bc..eb3169b 100644 --- a/gcc/testsuite/gcc.dg/param-type-mismatch.c +++ b/gcc/testsuite/gcc.dg/param-type-mismatch.c @@ -1,9 +1,6 @@ -/* { dg-options "-fdiagnostics-show-caret" } */ +/* { dg-options "-fdiagnostics-show-caret -fblt" } */ -/* 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. */ +/* A collection of calls where argument 2 is of the wrong type. */ /* decl, with argname. */ @@ -19,7 +16,7 @@ int test_1 (int first, int second, float third) /* { 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 "" } */ } @@ -37,7 +34,7 @@ int test_2 (int first, int second, float third) /* { 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 "" } */ } @@ -58,6 +55,6 @@ int test_3 (int first, int second, float third) /* { 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