aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-typeck.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-10-04 14:10:59 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-10-04 14:10:59 +0000
commit8139a48e67ec9f178904d2bb83a17bd37ce8fb54 (patch)
tree5ac29108fd99c55bc4523d0514be93519e27187d /gcc/c/c-typeck.c
parentbed8a1e4d6234e7bb1199eaf8f72b9007dc47034 (diff)
downloadgcc-8139a48e67ec9f178904d2bb83a17bd37ce8fb54.zip
gcc-8139a48e67ec9f178904d2bb83a17bd37ce8fb54.tar.gz
gcc-8139a48e67ec9f178904d2bb83a17bd37ce8fb54.tar.bz2
C: underline parameters in mismatching function calls
In r253096 ("C++: underline parameters in mismatching function calls" aka 5d78d423a5f7a1d135c7bb678e82007678d1313c https://gcc.gnu.org/ml/gcc-patches/2017-09/msg01546.html ) I updated the C++ FE's handling of mismatched types in function calls so that it underlines the pertinent param of the callee, rather than just the function name. The following patch does the same for the C frontend. Given e.g. this type mismatch: extern int callee (int one, const char *two, float three); int caller (int first, int second, float third) { return callee (first, second, third); } the C FE currently emits (trunk): test.c: In function 'caller': test.c:5:25: warning: passing argument 2 of 'callee' makes pointer from integer without a cast [-Wint-conversion] return callee (first, second, third); ^~~~~~ test.c:1:12: note: expected 'const char *' but argument is of type 'int' extern int callee (int one, const char *two, float three); ^~~~~~ whereas with this patch the note underlines the pertinent param of the callee: test.c: In function 'caller': test.c:5:25: warning: passing argument 2 of 'callee' makes pointer from integer without a cast [-Wint-conversion] return callee (first, second, third); ^~~~~~ test.c:1:41: note: expected 'const char *' but argument is of type 'int' extern int callee (int one, const char *two, float three); ~~~~~~~~~~~~^~~ making the problem more obvious to the user. As with the C++ patch, the patch: (a) updates the locations of the params to cover the range of all of their tokens, putting the caret on the first character of the param name (if present), otherwise at the start of the first token (doing so requires adding a last_token_location to the c_parser, so we can determine the location of the last consumed token). (b) updates the "note" to use the param location, rather than the fndecl location gcc/c/ChangeLog: * c-decl.c (push_parm_decl): Store c_parm's location into the PARAM_DECL. (build_c_parm): Add "loc" param and store it within the c_parm. * c-parser.c (struct c_parser): Add "last_token_location" field. (c_parser_consume_token): Store location of the token into the new field. (c_parser_declaration_or_fndef): Store params into DECL_ARGUMENTS when handling a FUNCTION_DECL, if it doesn't already have them. (c_parser_parameter_declaration): Generate a location for the parameter, and pass it to the call to build_c_parm. * c-tree.h (struct c_parm): Add field "loc". (build_c_parm): Add location_t param. * c-typeck.c (get_fndecl_argument_location): New function. (inform_for_arg): New function. (convert_for_assignment): Use inform_for_arg when dealing with ic_argpass. gcc/testsuite/ChangeLog: * gcc.dg/diagnostic-range-bad-called-object.c: Update expected underlining for param. * gcc.dg/param-type-mismatch.c: Update expected results to reflect highlighting of parameters; add test coverage for trivial parameter decls, and for callback parameters. * gcc.dg/pr68533.c: Update location of two errors to reflect location of params. From-SVN: r253411
Diffstat (limited to 'gcc/c/c-typeck.c')
-rw-r--r--gcc/c/c-typeck.c78
1 files changed, 51 insertions, 27 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 73e7460..2a10813 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -6180,6 +6180,50 @@ 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 DECL_SOURCE_LOCATION (FNDECL) if it can't be found. */
+
+static location_t
+get_fndecl_argument_location (tree fndecl, int argnum)
+{
+ int i;
+ tree param;
+
+ /* Locate param by index within DECL_ARGUMENTS (fndecl). */
+ for (i = 0, param = DECL_ARGUMENTS (fndecl);
+ i < argnum && param;
+ i++, param = TREE_CHAIN (param))
+ ;
+
+ /* If something went wrong (e.g. if we have a builtin and thus no arguments),
+ return DECL_SOURCE_LOCATION (FNDECL). */
+ if (param == NULL)
+ return DECL_SOURCE_LOCATION (fndecl);
+
+ return DECL_SOURCE_LOCATION (param);
+}
+
+/* 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;
+ if (fundecl && !DECL_IS_BUILTIN (fundecl))
+ loc = get_fndecl_argument_location (fundecl, parmnum - 1);
+ else
+ loc = ploc;
+
+ 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
@@ -6251,10 +6295,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); \
@@ -6280,10 +6321,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); \
@@ -6309,10 +6347,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); \
@@ -6864,10 +6899,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wincompatible_pointer_types,
"passing argument %d of %qE from incompatible "
"pointer type", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wincompatible_pointer_types,
@@ -6910,10 +6942,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wint_conversion,
"passing argument %d of %qE makes pointer from "
"integer without a cast", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -6944,10 +6973,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wint_conversion,
"passing argument %d of %qE makes integer from "
"pointer without a cast", parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT",
- type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
pedwarn (location, OPT_Wint_conversion,
@@ -6985,9 +7011,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
case ic_argpass:
error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
rname);
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
- "expected %qT but argument is of type %qT", type, rhstype);
+ inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype);
break;
case ic_assign:
error_at (location, "incompatible types when assigning to type %qT from "