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>
* 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>
* c-gimplify.c: Include dumpfile.h instead of tree-dump.h.
......
......@@ -8051,26 +8051,42 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
static void
check_function_nonnull (tree attrs, int nargs, tree *argarray)
{
tree a, args;
tree a;
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);
/* 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++)
for (a = attrs; ; a = TREE_CHAIN (a))
{
if (!args || nonnull_check_p (args, i + 1))
check_function_arguments_recurse (check_nonnull_arg, NULL,
argarray[i],
i + 1);
a = lookup_attribute ("nonnull", a);
if (a == NULL_TREE || nonnull_check_p (TREE_VALUE (a), i + 1))
break;
}
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>
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)
return true;
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 (attrs == NULL_TREE)
return false;
/* If "nonnull" wasn't specified, we know nothing about the argument. */
if (attrs == NULL_TREE)
return false;
/* If "nonnull" applies to all the arguments, then ARG is non-null. */
if (TREE_VALUE (attrs) == NULL_TREE)
return true;
/* If "nonnull" applies to all the arguments, then ARG is non-null. */
if (TREE_VALUE (attrs) == NULL_TREE)
return true;
/* Get the position number for ARG in the function signature. */
for (arg_num = 1, t = DECL_ARGUMENTS (current_function_decl);
t;
t = DECL_CHAIN (t), arg_num++)
{
if (t == arg)
break;
}
/* Get the position number for ARG in the function signature. */
for (arg_num = 1, t = DECL_ARGUMENTS (current_function_decl);
t;
t = DECL_CHAIN (t), arg_num++)
{
if (t == arg)
break;
}
gcc_assert (t == arg);
gcc_assert (t == arg);
/* Now see if ARG_NUM is mentioned in the nonnull list. */
for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
{
if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
return true;
/* Now see if ARG_NUM is mentioned in the nonnull list. */
for (t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
{
if (compare_tree_int (TREE_VALUE (t), arg_num) == 0)
return true;
}
}
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