re PR bootstrap/78817 (stage2 bootstrap failure in vec.h:1613:5: error: argument 1 null where non-null expected after r243661)
PR bootstrap/78817 * tree-pass.h (make_pass_post_ipa_warn): Declare. * builtins.c (validate_arglist): Adjust get_nonnull_args call. Check for NULL pointer argument to nonnull arg here. (validate_arg): Revert 2016-12-14 changes. * calls.h (get_nonnull_args): Remove declaration. * tree-ssa-ccp.c: Include diagnostic-core.h. (pass_data_post_ipa_warn): New variable. (pass_post_ipa_warn): New class. (pass_post_ipa_warn::execute): New method. (make_pass_post_ipa_warn): New function. * tree.h (get_nonnull_args): Declare. * tree.c (get_nonnull_args): New function. * calls.c (maybe_warn_null_arg): Removed. (maybe_warn_null_arg): Removed. (initialize_argument_information): Revert 2016-12-14 changes. * passes.def: Add pass_post_ipa_warn after first ccp after IPA. c-family/ * c-common.c (struct nonnull_arg_ctx): New type. (check_function_nonnull): Return bool instead of void. Use nonnull_arg_ctx as context rather than just location_t. (check_nonnull_arg): Adjust for the new context type, set warned_p to true if a warning has been diagnosed. (check_function_arguments): Return bool instead of void. * c-common.h (check_function_arguments): Adjust prototype. c/ * c-typeck.c (build_function_call_vec): If check_function_arguments returns true, set TREE_NO_WARNING on CALL_EXPR. cp/ * typeck.c (cp_build_function_call_vec): If check_function_arguments returns true, set TREE_NO_WARNING on CALL_EXPR. * call.c (build_over_call): Likewise. From-SVN: r243874
This commit is contained in:
parent
bc2a38dff8
commit
0dba79602a
|
@ -1,3 +1,23 @@
|
|||
2016-12-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR bootstrap/78817
|
||||
* tree-pass.h (make_pass_post_ipa_warn): Declare.
|
||||
* builtins.c (validate_arglist): Adjust get_nonnull_args call.
|
||||
Check for NULL pointer argument to nonnull arg here.
|
||||
(validate_arg): Revert 2016-12-14 changes.
|
||||
* calls.h (get_nonnull_args): Remove declaration.
|
||||
* tree-ssa-ccp.c: Include diagnostic-core.h.
|
||||
(pass_data_post_ipa_warn): New variable.
|
||||
(pass_post_ipa_warn): New class.
|
||||
(pass_post_ipa_warn::execute): New method.
|
||||
(make_pass_post_ipa_warn): New function.
|
||||
* tree.h (get_nonnull_args): Declare.
|
||||
* tree.c (get_nonnull_args): New function.
|
||||
* calls.c (maybe_warn_null_arg): Removed.
|
||||
(maybe_warn_null_arg): Removed.
|
||||
(initialize_argument_information): Revert 2016-12-14 changes.
|
||||
* passes.def: Add pass_post_ipa_warn after first ccp after IPA.
|
||||
|
||||
2016-12-21 Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
||||
PR rtl-optimization/11488
|
||||
|
|
|
@ -147,7 +147,7 @@ static tree fold_builtin_classify_type (tree);
|
|||
static tree fold_builtin_strlen (location_t, tree, tree);
|
||||
static tree fold_builtin_inf (location_t, tree, int);
|
||||
static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
|
||||
static bool validate_arg (const_tree, enum tree_code code, bool = false);
|
||||
static bool validate_arg (const_tree, enum tree_code code);
|
||||
static rtx expand_builtin_fabs (tree, rtx, rtx);
|
||||
static rtx expand_builtin_signbit (tree, rtx);
|
||||
static tree fold_builtin_memcmp (location_t, tree, tree, tree);
|
||||
|
@ -1050,12 +1050,12 @@ validate_arglist (const_tree callexpr, ...)
|
|||
init_const_call_expr_arg_iterator (callexpr, &iter);
|
||||
|
||||
/* Get a bitmap of pointer argument numbers declared attribute nonnull. */
|
||||
bitmap argmap = get_nonnull_args (callexpr);
|
||||
tree fn = CALL_EXPR_FN (callexpr);
|
||||
bitmap argmap = get_nonnull_args (TREE_TYPE (TREE_TYPE (fn)));
|
||||
|
||||
for (unsigned argno = 1; ; ++argno)
|
||||
{
|
||||
code = (enum tree_code) va_arg (ap, int);
|
||||
bool nonnull = false;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
|
@ -1072,15 +1072,21 @@ validate_arglist (const_tree callexpr, ...)
|
|||
/* The actual argument must be nonnull when either the whole
|
||||
called function has been declared nonnull, or when the formal
|
||||
argument corresponding to the actual argument has been. */
|
||||
if (argmap)
|
||||
nonnull = bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno);
|
||||
if (argmap
|
||||
&& (bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno)))
|
||||
{
|
||||
arg = next_const_call_expr_arg (&iter);
|
||||
if (!validate_arg (arg, code) || integer_zerop (arg))
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
/* If no parameters remain or the parameter's code does not
|
||||
match the specified code, return false. Otherwise continue
|
||||
checking any remaining arguments. */
|
||||
arg = next_const_call_expr_arg (&iter);
|
||||
if (!validate_arg (arg, code, nonnull))
|
||||
if (!validate_arg (arg, code))
|
||||
goto end;
|
||||
break;
|
||||
}
|
||||
|
@ -9134,17 +9140,15 @@ rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...)
|
|||
}
|
||||
|
||||
/* Validate a single argument ARG against a tree code CODE representing
|
||||
a type. When NONNULL is true consider a pointer argument valid only
|
||||
if it's non-null. Return true when argument is valid. */
|
||||
a type. Return true when argument is valid. */
|
||||
|
||||
static bool
|
||||
validate_arg (const_tree arg, enum tree_code code, bool nonnull /*= false*/)
|
||||
validate_arg (const_tree arg, enum tree_code code)
|
||||
{
|
||||
if (!arg)
|
||||
return false;
|
||||
else if (code == POINTER_TYPE)
|
||||
return POINTER_TYPE_P (TREE_TYPE (arg))
|
||||
&& (!nonnull || !integer_zerop (arg));
|
||||
return POINTER_TYPE_P (TREE_TYPE (arg));
|
||||
else if (code == INTEGER_TYPE)
|
||||
return INTEGRAL_TYPE_P (TREE_TYPE (arg));
|
||||
return code == TREE_CODE (TREE_TYPE (arg));
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2016-12-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR bootstrap/78817
|
||||
* c-common.c (struct nonnull_arg_ctx): New type.
|
||||
(check_function_nonnull): Return bool instead of void. Use
|
||||
nonnull_arg_ctx as context rather than just location_t.
|
||||
(check_nonnull_arg): Adjust for the new context type, set
|
||||
warned_p to true if a warning has been diagnosed.
|
||||
(check_function_arguments): Return bool instead of void.
|
||||
* c-common.h (check_function_arguments): Adjust prototype.
|
||||
|
||||
2016-12-21 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c.opt (-fnew-ttp-matching): New flag.
|
||||
|
|
|
@ -5250,11 +5250,21 @@ c_determine_visibility (tree decl)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Data to communicate through check_function_arguments_recurse between
|
||||
check_function_nonnull and check_nonnull_arg. */
|
||||
|
||||
struct nonnull_arg_ctx
|
||||
{
|
||||
location_t loc;
|
||||
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. */
|
||||
arguments are passed in the array ARGARRAY. Return true if we have
|
||||
warned. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray)
|
||||
{
|
||||
tree a;
|
||||
|
@ -5262,7 +5272,7 @@ check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray)
|
|||
|
||||
attrs = lookup_attribute ("nonnull", attrs);
|
||||
if (attrs == NULL_TREE)
|
||||
return;
|
||||
return false;
|
||||
|
||||
a = attrs;
|
||||
/* See if any of the nonnull attributes has no arguments. If so,
|
||||
|
@ -5273,9 +5283,10 @@ 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++)
|
||||
check_function_arguments_recurse (check_nonnull_arg, &loc, argarray[i],
|
||||
check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i],
|
||||
i + 1);
|
||||
else
|
||||
{
|
||||
|
@ -5291,10 +5302,11 @@ check_function_nonnull (location_t loc, tree attrs, int nargs, tree *argarray)
|
|||
}
|
||||
|
||||
if (a != NULL_TREE)
|
||||
check_function_arguments_recurse (check_nonnull_arg, &loc,
|
||||
check_function_arguments_recurse (check_nonnull_arg, &ctx,
|
||||
argarray[i], i + 1);
|
||||
}
|
||||
}
|
||||
return ctx.warned_p;
|
||||
}
|
||||
|
||||
/* Check that the Nth argument of a function call (counting backwards
|
||||
|
@ -5379,7 +5391,7 @@ nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
|
|||
static void
|
||||
check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
|
||||
{
|
||||
location_t *ploc = (location_t *) ctx;
|
||||
struct nonnull_arg_ctx *pctx = (struct nonnull_arg_ctx *) ctx;
|
||||
|
||||
/* Just skip checking the argument if it's not a pointer. This can
|
||||
happen if the "nonnull" attribute was given without an operand
|
||||
|
@ -5391,9 +5403,12 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
|
|||
/* When not optimizing diagnose the simple cases of null arguments.
|
||||
When optimization is enabled defer the checking until expansion
|
||||
when more cases can be detected. */
|
||||
if (!optimize && integer_zerop (param))
|
||||
warning_at (*ploc, OPT_Wnonnull, "null argument where non-null required "
|
||||
"(argument %lu)", (unsigned long) param_num);
|
||||
if (integer_zerop (param))
|
||||
{
|
||||
warning_at (pctx->loc, OPT_Wnonnull, "null argument where non-null "
|
||||
"required (argument %lu)", (unsigned long) param_num);
|
||||
pctx->warned_p = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper for nonnull attribute handling; fetch the operand number
|
||||
|
@ -5587,16 +5602,19 @@ attribute_fallthrough_p (tree attr)
|
|||
|
||||
/* Check for valid arguments being passed to a function with FNTYPE.
|
||||
There are NARGS arguments in the array ARGARRAY. LOC should be used for
|
||||
diagnostics. */
|
||||
void
|
||||
diagnostics. Return true if -Wnonnull warning has been diagnosed. */
|
||||
bool
|
||||
check_function_arguments (location_t loc, const_tree fntype, int nargs,
|
||||
tree *argarray)
|
||||
{
|
||||
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. */
|
||||
|
||||
if (warn_nonnull)
|
||||
check_function_nonnull (loc, TYPE_ATTRIBUTES (fntype), nargs, argarray);
|
||||
warned_p = check_function_nonnull (loc, TYPE_ATTRIBUTES (fntype),
|
||||
nargs, argarray);
|
||||
|
||||
/* Check for errors in format strings. */
|
||||
|
||||
|
@ -5605,6 +5623,7 @@ check_function_arguments (location_t loc, const_tree fntype, int nargs,
|
|||
|
||||
if (warn_format)
|
||||
check_function_sentinel (fntype, nargs, argarray);
|
||||
return warned_p;
|
||||
}
|
||||
|
||||
/* Generic argument checking recursion routine. PARAM is the argument to
|
||||
|
|
|
@ -804,7 +804,7 @@ extern const char *fname_as_string (int);
|
|||
extern tree fname_decl (location_t, unsigned, tree);
|
||||
|
||||
extern int check_user_alignment (const_tree, bool);
|
||||
extern void check_function_arguments (location_t loc, const_tree, int, tree *);
|
||||
extern bool check_function_arguments (location_t loc, const_tree, int, tree *);
|
||||
extern void check_function_arguments_recurse (void (*)
|
||||
(void *, tree,
|
||||
unsigned HOST_WIDE_INT),
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
2016-12-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR bootstrap/78817
|
||||
* c-typeck.c (build_function_call_vec): If check_function_arguments
|
||||
returns true, set TREE_NO_WARNING on CALL_EXPR.
|
||||
|
||||
PR c/77767
|
||||
* c-decl.c (grokdeclarator): If *expr is non-NULL, append expression
|
||||
to *expr instead of overwriting it.
|
||||
|
|
|
@ -3110,14 +3110,14 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
|
|||
return error_mark_node;
|
||||
|
||||
/* Check that the arguments to the function are valid. */
|
||||
check_function_arguments (loc, fntype, nargs, argarray);
|
||||
bool warned_p = check_function_arguments (loc, fntype, nargs, argarray);
|
||||
|
||||
if (name != NULL_TREE
|
||||
&& !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
|
||||
{
|
||||
if (require_constant_value)
|
||||
result =
|
||||
fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
|
||||
result
|
||||
= fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
|
||||
function, nargs, argarray);
|
||||
else
|
||||
result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
|
||||
|
@ -3129,6 +3129,10 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
|
|||
else
|
||||
result = build_call_array_loc (loc, TREE_TYPE (fntype),
|
||||
function, nargs, argarray);
|
||||
/* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
|
||||
later. */
|
||||
if (warned_p && TREE_CODE (result) == CALL_EXPR)
|
||||
TREE_NO_WARNING (result) = 1;
|
||||
|
||||
/* In this improbable scenario, a nested function returns a VM type.
|
||||
Create a TARGET_EXPR so that the call always has a LHS, much as
|
||||
|
|
95
gcc/calls.c
95
gcc/calls.c
|
@ -1501,91 +1501,6 @@ maybe_complain_about_tail_call (tree call_expr, const char *reason)
|
|||
error_at (EXPR_LOCATION (call_expr), "cannot tail-call: %s", reason);
|
||||
}
|
||||
|
||||
/* Return a bitmap with a bit set corresponding to each argument in
|
||||
a function call expression CALLEXPR declared with attribute nonnull,
|
||||
or null if none of the function's argument are nonnull. The caller
|
||||
must free the bitmap. */
|
||||
|
||||
bitmap
|
||||
get_nonnull_args (const_tree callexpr)
|
||||
{
|
||||
tree fn = CALL_EXPR_FN (callexpr);
|
||||
if (!fn || TREE_CODE (fn) != ADDR_EXPR)
|
||||
return NULL;
|
||||
|
||||
tree fndecl = TREE_OPERAND (fn, 0);
|
||||
tree fntype = TREE_TYPE (fndecl);
|
||||
tree attrs = TYPE_ATTRIBUTES (fntype);
|
||||
if (!attrs)
|
||||
return NULL;
|
||||
|
||||
bitmap argmap = NULL;
|
||||
|
||||
/* A function declaration can specify multiple attribute nonnull,
|
||||
each with zero or more arguments. The loop below creates a bitmap
|
||||
representing a union of all the arguments. An empty (but non-null)
|
||||
bitmap means that all arguments have been declaraed nonnull. */
|
||||
for ( ; attrs; attrs = TREE_CHAIN (attrs))
|
||||
{
|
||||
attrs = lookup_attribute ("nonnull", attrs);
|
||||
if (!attrs)
|
||||
break;
|
||||
|
||||
if (!argmap)
|
||||
argmap = BITMAP_ALLOC (NULL);
|
||||
|
||||
if (!TREE_VALUE (attrs))
|
||||
{
|
||||
/* Clear the bitmap in case a previous attribute nonnull
|
||||
set it and this one overrides it for all arguments. */
|
||||
bitmap_clear (argmap);
|
||||
return argmap;
|
||||
}
|
||||
|
||||
/* Iterate over the indices of the format arguments declared nonnull
|
||||
and set a bit for each. */
|
||||
for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
|
||||
{
|
||||
unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
|
||||
bitmap_set_bit (argmap, val);
|
||||
}
|
||||
}
|
||||
|
||||
return argmap;
|
||||
}
|
||||
|
||||
/* In a call EXP to a function FNDECL some of whose arguments may have
|
||||
been declared with attribute nonnull as described by NONNULLARGS,
|
||||
check actual argument ARG at the zero-based position ARGPOS for
|
||||
equality to null and issue a warning if it is not expected to be. */
|
||||
|
||||
static void
|
||||
maybe_warn_null_arg (tree fndecl, tree exp, tree arg,
|
||||
unsigned argpos, bitmap nonnullargs)
|
||||
{
|
||||
if (!optimize
|
||||
|| !nonnullargs
|
||||
|| TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE
|
||||
|| !integer_zerop (arg)
|
||||
|| (!bitmap_empty_p (nonnullargs)
|
||||
&& !bitmap_bit_p (nonnullargs, argpos)))
|
||||
return;
|
||||
|
||||
++argpos;
|
||||
|
||||
location_t exploc EXPR_LOCATION (exp);
|
||||
|
||||
if (warning_at (exploc, OPT_Wnonnull,
|
||||
"argument %u null where non-null expected", argpos))
|
||||
{
|
||||
if (DECL_IS_BUILTIN (fndecl))
|
||||
inform (exploc, "in a call to built-in function %qD", fndecl);
|
||||
else
|
||||
inform (DECL_SOURCE_LOCATION (fndecl),
|
||||
"in a call to function %qD declared here", fndecl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
|
||||
CALL_EXPR EXP.
|
||||
|
||||
|
@ -1769,9 +1684,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
|
|||
/* Array for up to the two attribute alloc_size arguments. */
|
||||
tree alloc_args[] = { NULL_TREE, NULL_TREE };
|
||||
|
||||
/* Get a bitmap of pointer argument numbers declared attribute nonnull. */
|
||||
bitmap nonnullargs = get_nonnull_args (exp);
|
||||
|
||||
/* I counts args in order (to be) pushed; ARGPOS counts in order written. */
|
||||
for (argpos = 0; argpos < num_actuals; i--, argpos++)
|
||||
{
|
||||
|
@ -2003,11 +1915,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
|
|||
if (args[i].locate.size.var)
|
||||
ADD_PARM_SIZE (*args_size, args[i].locate.size.var);
|
||||
|
||||
/* Check pointer argument for equality to NULL that is being passed
|
||||
to arguments declared with attribute nonnull and warn. */
|
||||
maybe_warn_null_arg (fndecl, exp, args[i].tree_value, argpos,
|
||||
nonnullargs);
|
||||
|
||||
/* Increment ARGS_SO_FAR, which has info about which arg-registers
|
||||
have been used, etc. */
|
||||
|
||||
|
@ -2028,8 +1935,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
|
|||
alloc_size. */
|
||||
maybe_warn_alloc_args_overflow (fndecl, exp, alloc_args, alloc_idx);
|
||||
}
|
||||
|
||||
BITMAP_FREE (nonnullargs);
|
||||
}
|
||||
|
||||
/* Update ARGS_SIZE to contain the total size for the argument block.
|
||||
|
|
|
@ -38,6 +38,5 @@ extern bool pass_by_reference (CUMULATIVE_ARGS *, machine_mode,
|
|||
extern bool reference_callee_copied (CUMULATIVE_ARGS *, machine_mode,
|
||||
tree, bool);
|
||||
extern void maybe_warn_alloc_args_overflow (tree, tree, tree[2], int[2]);
|
||||
extern bitmap get_nonnull_args (const_tree);
|
||||
|
||||
#endif // GCC_CALLS_H
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
2016-12-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR bootstrap/78817
|
||||
* typeck.c (cp_build_function_call_vec): If check_function_arguments
|
||||
returns true, set TREE_NO_WARNING on CALL_EXPR.
|
||||
* call.c (build_over_call): Likewise.
|
||||
|
||||
PR c++/77830
|
||||
* constexpr.c (cxx_eval_array_reference): Perform out of bounds
|
||||
verification even if lval is true, just allow one past the last
|
||||
|
|
|
@ -7881,6 +7881,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
nonnull are disabled. Just in case that at least one of them is active
|
||||
the check_function_arguments function might warn about something. */
|
||||
|
||||
bool warned_p = false;
|
||||
if (warn_nonnull || warn_format || warn_suggest_attribute_format)
|
||||
{
|
||||
tree *fargs = (!nargs ? argarray
|
||||
|
@ -7888,7 +7889,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
for (j = 0; j < nargs; j++)
|
||||
fargs[j] = maybe_constant_value (argarray[j]);
|
||||
|
||||
check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs);
|
||||
warned_p = check_function_arguments (input_location, TREE_TYPE (fn),
|
||||
nargs, fargs);
|
||||
}
|
||||
|
||||
if (DECL_INHERITED_CTOR (fn))
|
||||
|
@ -8107,6 +8109,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
|||
/* build_new_op_1 will clear this when appropriate. */
|
||||
CALL_EXPR_ORDERED_ARGS (c) = true;
|
||||
}
|
||||
if (warned_p)
|
||||
{
|
||||
tree c = extract_call_expr (call);
|
||||
if (TREE_CODE (c) == CALL_EXPR)
|
||||
TREE_NO_WARNING (c) = 1;
|
||||
}
|
||||
return call;
|
||||
}
|
||||
|
||||
|
|
|
@ -3654,10 +3654,18 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
|
|||
|
||||
/* Check for errors in format strings and inappropriately
|
||||
null parameters. */
|
||||
check_function_arguments (input_location, fntype, nargs, argarray);
|
||||
bool warned_p = check_function_arguments (input_location, fntype,
|
||||
nargs, argarray);
|
||||
|
||||
ret = build_cxx_call (function, nargs, argarray, complain);
|
||||
|
||||
if (warned_p)
|
||||
{
|
||||
tree c = extract_call_expr (ret);
|
||||
if (TREE_CODE (c) == CALL_EXPR)
|
||||
TREE_NO_WARNING (c) = 1;
|
||||
}
|
||||
|
||||
if (allocated != NULL)
|
||||
release_tree_vector (allocated);
|
||||
|
||||
|
|
|
@ -193,6 +193,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
They ensure memory accesses are not indirect wherever possible. */
|
||||
NEXT_PASS (pass_strip_predict_hints);
|
||||
NEXT_PASS (pass_ccp, true /* nonzero_p */);
|
||||
NEXT_PASS (pass_post_ipa_warn);
|
||||
/* After CCP we rewrite no longer addressed locals into SSA
|
||||
form if possible. */
|
||||
NEXT_PASS (pass_complete_unrolli);
|
||||
|
@ -360,6 +361,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
NEXT_PASS (pass_lower_vector_ssa);
|
||||
/* Perform simple scalar cleanup which is constant/copy propagation. */
|
||||
NEXT_PASS (pass_ccp, true /* nonzero_p */);
|
||||
NEXT_PASS (pass_post_ipa_warn);
|
||||
NEXT_PASS (pass_object_sizes);
|
||||
/* Fold remaining builtins. */
|
||||
NEXT_PASS (pass_fold_builtins);
|
||||
|
|
|
@ -422,6 +422,7 @@ extern gimple_opt_pass *make_pass_omp_device_lower (gcc::context *ctxt);
|
|||
extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_fold_builtins (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_post_ipa_warn (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_stdarg (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_early_warn_uninitialized (gcc::context *ctxt);
|
||||
extern gimple_opt_pass *make_pass_late_warn_uninitialized (gcc::context *ctxt);
|
||||
|
|
|
@ -144,6 +144,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "optabs-query.h"
|
||||
#include "tree-ssa-ccp.h"
|
||||
#include "tree-dfa.h"
|
||||
#include "diagnostic-core.h"
|
||||
|
||||
/* Possible lattice values. */
|
||||
typedef enum
|
||||
|
@ -3316,3 +3317,97 @@ make_pass_fold_builtins (gcc::context *ctxt)
|
|||
{
|
||||
return new pass_fold_builtins (ctxt);
|
||||
}
|
||||
|
||||
/* A simple pass that emits some warnings post IPA. */
|
||||
|
||||
namespace {
|
||||
|
||||
const pass_data pass_data_post_ipa_warn =
|
||||
{
|
||||
GIMPLE_PASS, /* type */
|
||||
"post_ipa_warn", /* name */
|
||||
OPTGROUP_NONE, /* optinfo_flags */
|
||||
TV_NONE, /* tv_id */
|
||||
( PROP_cfg | PROP_ssa ), /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
0, /* todo_flags_finish */
|
||||
};
|
||||
|
||||
class pass_post_ipa_warn : public gimple_opt_pass
|
||||
{
|
||||
public:
|
||||
pass_post_ipa_warn (gcc::context *ctxt)
|
||||
: gimple_opt_pass (pass_data_post_ipa_warn, ctxt)
|
||||
{}
|
||||
|
||||
/* opt_pass methods: */
|
||||
opt_pass * clone () { return new pass_post_ipa_warn (m_ctxt); }
|
||||
virtual bool gate (function *) { return warn_nonnull != 0; }
|
||||
virtual unsigned int execute (function *);
|
||||
|
||||
}; // class pass_fold_builtins
|
||||
|
||||
unsigned int
|
||||
pass_post_ipa_warn::execute (function *fun)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
FOR_EACH_BB_FN (bb, fun)
|
||||
{
|
||||
gimple_stmt_iterator gsi;
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
if (!is_gimple_call (stmt) || gimple_no_warning_p (stmt))
|
||||
continue;
|
||||
|
||||
if (warn_nonnull)
|
||||
{
|
||||
bitmap nonnullargs
|
||||
= get_nonnull_args (gimple_call_fntype (stmt));
|
||||
if (nonnullargs)
|
||||
{
|
||||
for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
|
||||
{
|
||||
tree arg = gimple_call_arg (stmt, i);
|
||||
if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
|
||||
continue;
|
||||
if (!integer_zerop (arg))
|
||||
continue;
|
||||
if (!bitmap_empty_p (nonnullargs)
|
||||
&& !bitmap_bit_p (nonnullargs, i))
|
||||
continue;
|
||||
|
||||
location_t loc = gimple_location (stmt);
|
||||
if (warning_at (loc, OPT_Wnonnull,
|
||||
"argument %u null where non-null "
|
||||
"expected", i + 1))
|
||||
{
|
||||
tree fndecl = gimple_call_fndecl (stmt);
|
||||
if (fndecl && DECL_IS_BUILTIN (fndecl))
|
||||
inform (loc, "in a call to built-in function %qD",
|
||||
fndecl);
|
||||
else if (fndecl)
|
||||
inform (DECL_SOURCE_LOCATION (fndecl),
|
||||
"in a call to function %qD declared here",
|
||||
fndecl);
|
||||
|
||||
}
|
||||
}
|
||||
BITMAP_FREE (nonnullargs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
gimple_opt_pass *
|
||||
make_pass_post_ipa_warn (gcc::context *ctxt)
|
||||
{
|
||||
return new pass_post_ipa_warn (ctxt);
|
||||
}
|
||||
|
|
50
gcc/tree.c
50
gcc/tree.c
|
@ -14313,6 +14313,56 @@ combined_fn_name (combined_fn fn)
|
|||
return internal_fn_name (as_internal_fn (fn));
|
||||
}
|
||||
|
||||
/* Return a bitmap with a bit set corresponding to each argument in
|
||||
a function call type FNTYPE declared with attribute nonnull,
|
||||
or null if none of the function's argument are nonnull. The caller
|
||||
must free the bitmap. */
|
||||
|
||||
bitmap
|
||||
get_nonnull_args (const_tree fntype)
|
||||
{
|
||||
if (fntype == NULL_TREE)
|
||||
return NULL;
|
||||
|
||||
tree attrs = TYPE_ATTRIBUTES (fntype);
|
||||
if (!attrs)
|
||||
return NULL;
|
||||
|
||||
bitmap argmap = NULL;
|
||||
|
||||
/* A function declaration can specify multiple attribute nonnull,
|
||||
each with zero or more arguments. The loop below creates a bitmap
|
||||
representing a union of all the arguments. An empty (but non-null)
|
||||
bitmap means that all arguments have been declaraed nonnull. */
|
||||
for ( ; attrs; attrs = TREE_CHAIN (attrs))
|
||||
{
|
||||
attrs = lookup_attribute ("nonnull", attrs);
|
||||
if (!attrs)
|
||||
break;
|
||||
|
||||
if (!argmap)
|
||||
argmap = BITMAP_ALLOC (NULL);
|
||||
|
||||
if (!TREE_VALUE (attrs))
|
||||
{
|
||||
/* Clear the bitmap in case a previous attribute nonnull
|
||||
set it and this one overrides it for all arguments. */
|
||||
bitmap_clear (argmap);
|
||||
return argmap;
|
||||
}
|
||||
|
||||
/* Iterate over the indices of the format arguments declared nonnull
|
||||
and set a bit for each. */
|
||||
for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx))
|
||||
{
|
||||
unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1;
|
||||
bitmap_set_bit (argmap, val);
|
||||
}
|
||||
}
|
||||
|
||||
return argmap;
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
|
|
@ -4855,6 +4855,7 @@ extern void DEBUG_FUNCTION verify_type (const_tree t);
|
|||
extern bool gimple_canonical_types_compatible_p (const_tree, const_tree,
|
||||
bool trust_type_canonical = true);
|
||||
extern bool type_with_interoperable_signedness (const_tree);
|
||||
extern bitmap get_nonnull_args (const_tree);
|
||||
|
||||
/* Return simplified tree code of type that is used for canonical type
|
||||
merging. */
|
||||
|
|
Loading…
Reference in New Issue