Commit 332f1d24 by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/28656 (duplicated null argument warning on memcpy())

	PR c++/28656
	* tree-vrp.c (nonnull_arg_p): Handle all nonnull attributes instead
	of just the first one.

	* c-common.c (check_function_nonnull): Handle multiple nonnull
	attributes properly.

	* c-c++-common/pr28656.c: New test.

From-SVN: r189707
parent 3c82efd9
2012-07-20 Jakub Jelinek <jakub@redhat.com>
PR c++/28656
* tree-vrp.c (nonnull_arg_p): Handle all nonnull attributes instead
of just the first one.
2012-07-20 Richard Guenther <rguenther@suse.de> 2012-07-20 Richard Guenther <rguenther@suse.de>
* builtins.c (get_object_alignment_2): Correct offset handling * builtins.c (get_object_alignment_2): Correct offset handling
......
2012-07-20 Jakub Jelinek <jakub@redhat.com>
PR c++/28656
* c-common.c (check_function_nonnull): Handle multiple nonnull
attributes properly.
2012-07-16 Steven Bosscher <steven@gcc.gnu.org> 2012-07-16 Steven Bosscher <steven@gcc.gnu.org>
* c-gimplify.c: Include dumpfile.h instead of tree-dump.h. * c-gimplify.c: Include dumpfile.h instead of tree-dump.h.
......
...@@ -8051,26 +8051,42 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), ...@@ -8051,26 +8051,42 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
static void static void
check_function_nonnull (tree attrs, int nargs, tree *argarray) check_function_nonnull (tree attrs, int nargs, tree *argarray)
{ {
tree a, args; tree a;
int i; int i;
for (a = attrs; a; a = TREE_CHAIN (a)) attrs = lookup_attribute ("nonnull", attrs);
if (attrs == NULL_TREE)
return;
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). */
if (TREE_VALUE (a) != NULL_TREE)
do
a = lookup_attribute ("nonnull", TREE_CHAIN (a));
while (a != NULL_TREE && TREE_VALUE (a) != NULL_TREE);
if (a != NULL_TREE)
for (i = 0; i < nargs; i++)
check_function_arguments_recurse (check_nonnull_arg, NULL, argarray[i],
i + 1);
else
{ {
if (is_attribute_p ("nonnull", TREE_PURPOSE (a))) /* Walk the argument list. If we encounter an argument number we
should check for non-null, do it. */
for (i = 0; i < nargs; i++)
{ {
args = TREE_VALUE (a); for (a = attrs; ; a = TREE_CHAIN (a))
/* Walk the argument list. If we encounter an argument number we
should check for non-null, do it. If the attribute has no args,
then every pointer argument is checked (in which case the check
for pointer type is done in check_nonnull_arg). */
for (i = 0; i < nargs; i++)
{ {
if (!args || nonnull_check_p (args, i + 1)) a = lookup_attribute ("nonnull", a);
check_function_arguments_recurse (check_nonnull_arg, NULL, if (a == NULL_TREE || nonnull_check_p (TREE_VALUE (a), i + 1))
argarray[i], break;
i + 1);
} }
if (a != NULL_TREE)
check_function_arguments_recurse (check_nonnull_arg, NULL,
argarray[i], i + 1);
} }
} }
} }
......
2012-07-20 Jakub Jelinek <jakub@redhat.com>
PR c++/28656
* c-c++-common/pr28656.c: New test.
2012-07-19 Jason Merrill <jason@redhat.com> 2012-07-19 Jason Merrill <jason@redhat.com>
PR c++/54026 PR c++/54026
......
/* PR c++/28656 */
/* { dg-do compile } */
/* { dg-options "-Wnonnull" } */
#ifdef __cplusplus
extern "C" {
#endif
extern void *memcpy (void *__restrict, const void *__restrict, __SIZE_TYPE__)
__attribute__((nonnull (1), nonnull (2), nonnull (1, 2), nonnull));
#ifdef __cplusplus
}
#endif
extern void bar (void *p1, void *p2, void *p3, void *p4, void *p5)
__attribute__((nonnull (1), nonnull (1, 3), nonnull (3, 5), nonnull (4)));
void
foo (void)
{
memcpy (0, 0, 0);
bar (0, 0, 0, 0, 0);
}
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 1" "" { target *-*-* } 20 } */
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 2" "" { target *-*-* } 20 } */
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 1" "" { target *-*-* } 21 } */
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 3" "" { target *-*-* } 21 } */
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 4" "" { target *-*-* } 21 } */
/* { dg-warning "null argument where non-null required\[^\n\r\]*argument 5" "" { target *-*-* } 21 } */
...@@ -353,32 +353,35 @@ nonnull_arg_p (const_tree arg) ...@@ -353,32 +353,35 @@ nonnull_arg_p (const_tree arg)
return true; return true;
fntype = TREE_TYPE (current_function_decl); fntype = TREE_TYPE (current_function_decl);
attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (fntype)); for (attrs = TYPE_ATTRIBUTES (fntype); attrs; attrs = TREE_CHAIN (attrs))
{
attrs = lookup_attribute ("nonnull", attrs);
/* If "nonnull" wasn't specified, we know nothing about the argument. */ /* If "nonnull" wasn't specified, we know nothing about the argument. */
if (attrs == NULL_TREE) if (attrs == NULL_TREE)
return false; return false;
/* If "nonnull" applies to all the arguments, then ARG is non-null. */ /* If "nonnull" applies to all the arguments, then ARG is non-null. */
if (TREE_VALUE (attrs) == NULL_TREE) if (TREE_VALUE (attrs) == NULL_TREE)
return true; return true;
/* Get the position number for ARG in the function signature. */ /* Get the position number for ARG in the function signature. */
for (arg_num = 1, t = DECL_ARGUMENTS (current_function_decl); for (arg_num = 1, t = DECL_ARGUMENTS (current_function_decl);
t; t;
t = DECL_CHAIN (t), arg_num++) t = DECL_CHAIN (t), arg_num++)
{ {
if (t == arg) if (t == arg)
break; break;
} }
gcc_assert (t == arg); gcc_assert (t == arg);
/* Now see if ARG_NUM is mentioned in the nonnull list. */ /* Now see if ARG_NUM is mentioned in the nonnull list. */
for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t)) for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
{ {
if (compare_tree_int (TREE_VALUE (t), arg_num) == 0) if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
return true; return true;
}
} }
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment