diff options
author | Martin Sebor <msebor@redhat.com> | 2020-06-28 14:22:14 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-06-28 14:24:52 -0600 |
commit | 75ff24e1920ea6b198350a2961e23175e6108e75 (patch) | |
tree | 88dfd1e43a652ff5f769d9543cd22d764cbe29e3 /gcc/c-family | |
parent | ce56fd949f359a62b86a45aaf975ac2ecc48fa64 (diff) | |
download | gcc-75ff24e1920ea6b198350a2961e23175e6108e75.zip gcc-75ff24e1920ea6b198350a2961e23175e6108e75.tar.gz gcc-75ff24e1920ea6b198350a2961e23175e6108e75.tar.bz2 |
Underline argument in -Wnonnull and in C++ extend warning to the this pointer [PR c++/86568].
Resolves:
PR c++/86568 - -Wnonnull warnings should highlight the relevant argument not the closing parenthesis
gcc/c-family/ChangeLog:
PR c++/86568
* c-common.c (struct nonnull_arg_ctx): Add members.
(check_function_nonnull): Use nonnull_arg_ctx as argument. Handle
C++ member functions specially. Consider the this pointer implicitly
nonnull.
(check_nonnull_arg): Use location of argument when available.
(check_function_arguments): Use nonnull_arg_ctx as argument.
gcc/ChangeLog:
PR c++/86568
* calls.c (maybe_warn_rdwr_sizes): Use location of argument if
available.
* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same. Adjust
indentation.
* tree.c (get_nonnull_args): Consider the this pointer implicitly
nonnull.
* var-tracking.c (deps_vec): New type.
(var_loc_dep_vec): New function.
(VAR_LOC_DEP_VEC): Use it.
gcc/testsuite/ChangeLog:
PR c++/86568
* g++.dg/warn/Wnonnull5.C: New test.
* c-c++-common/pr28656.c: Adjust text of expected warning.
* c-c++-common/pr66208.c: Same.
* g++.dg/cpp0x/nullptr22.C: Same.
* g++.dg/ext/attr-nonnull.C: Same.
* g++.dg/ext/attrib49.C: Same.
* g++.dg/pr71973-2.C: Same.
* g++.dg/warn/Wnonnull3.C: Same.
* g++.dg/warn/Wnonnull4.C: Same.
* obj-c++.dg/attributes/method-nonnull-1.mm: Same.
* objc.dg/attributes/method-nonnull-1.m: Same.
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/c-common.c | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index a9fa0d1..cfd12c0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -5288,26 +5288,39 @@ c_determine_visibility (tree decl) struct nonnull_arg_ctx { + /* Location of the call. */ location_t loc; + /* The function whose arguments are being checked and its type (used + for calls through function pointers). */ + const_tree fndecl, fntype; + /* True if a warning has been issued. */ bool warned_p; }; -/* Check the argument list of a function call for null in argument slots - that are marked as requiring a non-null pointer argument. The NARGS - arguments are passed in the array ARGARRAY. Return true if we have - warned. */ +/* Check the argument list of a function call to CTX.FNDECL of CTX.FNTYPE + for null in argument slots that are marked as requiring a non-null + pointer argument. The NARGS arguments are passed in the array ARGARRAY. + Return true if we have warned. */ static bool -check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray) +check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) { - tree a; - int i; + int firstarg = 0; + if (TREE_CODE (ctx.fntype) == METHOD_TYPE) + { + /* In calls to C++ non-static member functions check the this + pointer regardless of whether the function is declared with + attribute nonnull. */ + firstarg = 1; + check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0], + firstarg); + } - attrs = lookup_attribute ("nonnull", attrs); + tree attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (ctx.fntype)); if (attrs == NULL_TREE) - return false; + return ctx.warned_p; - a = attrs; + tree a = attrs; /* See if any of the nonnull attributes has no arguments. If so, then every pointer argument is checked (in which case the check for pointer type is done in check_nonnull_arg). */ @@ -5316,16 +5329,15 @@ check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray) a = lookup_attribute ("nonnull", TREE_CHAIN (a)); while (a != NULL_TREE && TREE_VALUE (a) != NULL_TREE); - struct nonnull_arg_ctx ctx = { loc, false }; if (a != NULL_TREE) - for (i = 0; i < nargs; i++) + for (int i = firstarg; i < nargs; i++) check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i], i + 1); else { /* Walk the argument list. If we encounter an argument number we should check for non-null, do it. */ - for (i = 0; i < nargs; i++) + for (int i = firstarg; i < nargs; i++) { for (a = attrs; ; a = TREE_CHAIN (a)) { @@ -5495,12 +5507,39 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num) return; /* Diagnose the simple cases of null arguments. */ - if (integer_zerop (fold_for_warn (param))) + if (!integer_zerop (fold_for_warn (param))) + return; + + auto_diagnostic_group adg; + + const location_t loc = EXPR_LOC_OR_LOC (param, pctx->loc); + + if (TREE_CODE (pctx->fntype) == METHOD_TYPE) + --param_num; + + bool warned; + if (param_num == 0) + { + warned = warning_at (loc, OPT_Wnonnull, + "%qs pointer null", "this"); + if (pctx->fndecl) + inform (DECL_SOURCE_LOCATION (pctx->fndecl), + "in a call to non-static member function %qD", + pctx->fndecl); + } + else { - warning_at (pctx->loc, OPT_Wnonnull, "null argument where non-null " - "required (argument %lu)", (unsigned long) param_num); - pctx->warned_p = true; + warned = warning_at (loc, OPT_Wnonnull, + "argument %u null where non-null expected", + (unsigned) param_num); + if (pctx->fndecl) + inform (DECL_SOURCE_LOCATION (pctx->fndecl), + "in a call to function %qD declared %qs", + pctx->fndecl, "nonnull"); } + + if (warned) + pctx->warned_p = true; } /* Helper for attribute handling; fetch the operand number from @@ -5717,11 +5756,13 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, bool warned_p = false; /* Check for null being passed in a pointer argument that must be - non-null. We also need to do this if format checking is enabled. */ - + non-null. In C++, this includes the this pointer. We also need + to do this if format checking is enabled. */ if (warn_nonnull) - warned_p = check_function_nonnull (loc, TYPE_ATTRIBUTES (fntype), - nargs, argarray); + { + nonnull_arg_ctx ctx = { loc, fndecl, fntype, false }; + warned_p = check_function_nonnull (ctx, nargs, argarray); + } /* Check for errors in format strings. */ |