]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/28656 (duplicated null argument warning on memcpy())
authorJakub Jelinek <jakub@redhat.com>
Fri, 20 Jul 2012 09:37:25 +0000 (11:37 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 20 Jul 2012 09:37:25 +0000 (11:37 +0200)
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

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr28656.c [new file with mode: 0644]
gcc/tree-vrp.c

index 2c4c273582360fce4b0d8e85e0e9d02b88c7abd2..28f7722cc8381c2620cdc33e7341d6b25f3bca6d 100644 (file)
@@ -1,3 +1,9 @@
+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
index b6c72553826a121f248d1618175ada452dbb0fa2..ddea75a00e1b38784492adc1d435f37ca6e5584f 100644 (file)
@@ -1,3 +1,9 @@
+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.
index 4a8b56d8f90aa5291331d15a2058d6bd22607a2e..b72506b212f27f25c1145328f9945ad0088f7a3a 100644 (file)
@@ -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);
        }
     }
 }
index 8ae7ff8f3c9f6c13cad4318a6ece568e2ea45b71..f02f16ededfb95f7b829e4a270f7f64d26b4fb64 100644 (file)
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/c-c++-common/pr28656.c b/gcc/testsuite/c-c++-common/pr28656.c
new file mode 100644 (file)
index 0000000..a0c2339
--- /dev/null
@@ -0,0 +1,29 @@
+/* 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 } */
index 66cc40668304f8c629f0c24d3b7981178832b88d..68c449e0acca8cecc8100355a55cf9a658eb993f 100644 (file)
@@ -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;