PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping memcpy...
authorMartin Sebor <msebor@redhat.com>
Mon, 12 Mar 2018 18:04:16 +0000 (18:04 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Mon, 12 Mar 2018 18:04:16 +0000 (12:04 -0600)
gcc/ChangeLog:

PR tree-optimization/83456
* gimple-fold.c (gimple_fold_builtin_memory_op): Avoid warning
for perfectly overlapping calls to memcpy.
(gimple_fold_builtin_memory_chk): Same.
(gimple_fold_builtin_strcpy): Handle no-warning.
(gimple_fold_builtin_stxcpy_chk): Same.
* tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Handle no-warning.

gcc/c-family/ChangeLog:

PR tree-optimization/83456
* gcc/c-family/c-common.c (check_function_restrict): Return bool.
Restore checking of bounded built-in functions.
(check_function_arguments): Also return the result
of warn_for_restrict.
* gcc/c-family/c-common.c (check_function_restrict): Return bool.
* gcc/c-family/c-warn.c (warn_for_restrict): Return bool.

gcc/testsuite/ChangeLog:

PR tree-optimization/83456
* c-c++-common/Wrestrict-2.c: Remove test cases.
* c-c++-common/Wrestrict.c: Same.
* gcc.dg/Wrestrict-12.c: New test.
* gcc.dg/Wrestrict-14.c: New test.

From-SVN: r258455

12 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-warn.c
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wrestrict-2.c
gcc/testsuite/c-c++-common/Wrestrict.c
gcc/testsuite/gcc.dg/Wrestrict-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wrestrict-14.c [new file with mode: 0644]
gcc/tree-ssa-strlen.c

index f9f986bfab58be341ee3e2f33bc8b615793b58dc..bc771c64a6148bfa7b2f3d3d7bcaffa8b45c6d96 100644 (file)
@@ -1,3 +1,13 @@
+2018-03-12  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/83456
+       * gimple-fold.c (gimple_fold_builtin_memory_op): Avoid warning
+       for perfectly overlapping calls to memcpy.
+       (gimple_fold_builtin_memory_chk): Same.
+       (gimple_fold_builtin_strcpy): Handle no-warning.
+       (gimple_fold_builtin_stxcpy_chk): Same.
+       * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Handle no-warning.
+
 2018-03-12  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * config/rs6000/rs6000.c (abi_v4_pass_in_fpr): Add bool "named"
index fe1fc81139ed039374e0bb3876ddec9ff7d442f4..259445365c4232171407cede8bb1a0d292e35482 100644 (file)
@@ -1,3 +1,13 @@
+2018-03-12  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/83456
+       * gcc/c-family/c-common.c (check_function_restrict): Return bool.
+       Restore checking of bounded built-in functions.
+       (check_function_arguments): Also return the result
+       of warn_for_restrict.
+       * gcc/c-family/c-common.c (check_function_restrict): Return bool.
+       * gcc/c-family/c-warn.c (warn_for_restrict): Return bool.
+
 2018-03-02  Marek Polacek  <polacek@redhat.com>
 
        PR c++/84171
index 858ed68f2d1c76a035319aba9893d60a748970eb..e1df1d3b73bfad849f48b57e1446be722025aa4b 100644 (file)
@@ -5309,10 +5309,11 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
     }
 }
 
-/* Check that the same argument isn't passed to restrict arguments
-   and other arguments.  */
+/* Check that the same argument isn't passed to two or more
+   restrict-qualified formal and issue a -Wrestrict warning
+   if it is.  Return true if a warning has been issued.  */
 
-static void
+static bool
 check_function_restrict (const_tree fndecl, const_tree fntype,
                         int nargs, tree *argarray)
 {
@@ -5322,11 +5323,14 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
   if (fndecl
       && TREE_CODE (fndecl) == FUNCTION_DECL)
     {
-      /* Skip checking built-ins here.  They are checked in more
-        detail elsewhere.  */
+      /* Avoid diagnosing calls built-ins with a zero size/bound
+        here.  They are checked in more detail elsewhere.  */
       if (DECL_BUILT_IN (fndecl)
-         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
-       return;
+         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+         && nargs == 3
+         && TREE_CODE (argarray[2]) == INTEGER_CST
+         && integer_zerop (argarray[2]))
+       return false;
 
       if (DECL_ARGUMENTS (fndecl))
        parms = DECL_ARGUMENTS (fndecl);
@@ -5335,6 +5339,8 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
   for (i = 0; i < nargs; i++)
     TREE_VISITED (argarray[i]) = 0;
 
+  bool warned = false;
+
   for (i = 0; i < nargs && parms && parms != void_list_node; i++)
     {
       tree type;
@@ -5351,11 +5357,13 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
       if (POINTER_TYPE_P (type)
          && TYPE_RESTRICT (type)
          && !TYPE_READONLY (TREE_TYPE (type)))
-       warn_for_restrict (i, argarray, nargs);
+       warned |= warn_for_restrict (i, argarray, nargs);
     }
 
   for (i = 0; i < nargs; i++)
     TREE_VISITED (argarray[i]) = 0;
+
+  return warned;
 }
 
 /* Helper for check_function_nonnull; given a list of operands which
@@ -5596,8 +5604,10 @@ attribute_fallthrough_p (tree attr)
 
 \f
 /* 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.  Return true if -Wnonnull warning has been diagnosed.  */
+   There are NARGS arguments in the array ARGARRAY.  LOC should be used
+   for diagnostics.  Return true if either -Wnonnull or -Wrestrict has
+   been issued.  */
+
 bool
 check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
                          int nargs, tree *argarray, vec<location_t> *arglocs)
@@ -5620,7 +5630,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
     check_function_sentinel (fntype, nargs, argarray);
 
   if (warn_restrict)
-    check_function_restrict (fndecl, fntype, nargs, argarray);
+    warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
   return warned_p;
 }
 
index 95bb0fd2b06b7f0eb6ebefddc78a81d1f473ac9d..6cf7614f68207c9ea26e293aa2e9600c3af53df8 100644 (file)
@@ -1269,7 +1269,7 @@ extern void warnings_for_convert_and_check (location_t, tree, tree, tree);
 extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
                                  bool);
 extern void warn_for_omitted_condop (location_t, tree);
-extern void warn_for_restrict (unsigned, tree *, unsigned);
+extern bool warn_for_restrict (unsigned, tree *, unsigned);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.
    Used to select diagnostic messages in lvalue_error and
index 7c385959c4f6f90705d76b43468bff6060f63cfe..51c376b7c37fdda2671e831da97df03a823789a0 100644 (file)
@@ -2372,14 +2372,15 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
 }
 
 /* Warn if an argument at position param_pos is passed to a
-   restrict-qualified param, and it aliases with another argument.  */
+   restrict-qualified param, and it aliases with another argument.
+   Return true if a warning has been issued.  */
 
-void
+bool
 warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
 {
   tree arg = argarray[param_pos];
   if (TREE_VISITED (arg) || integer_zerop (arg))
-    return;
+    return false;
 
   location_t loc = EXPR_LOC_OR_LOC (arg, input_location);
   gcc_rich_location richloc (loc);
@@ -2395,13 +2396,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
       tree current_arg = argarray[i];
       if (operand_equal_p (arg, current_arg, 0))
        {
-         TREE_VISITED (current_arg) = 1; 
+         TREE_VISITED (current_arg) = 1;
          arg_positions.safe_push (i + 1);
        }
     }
 
   if (arg_positions.is_empty ())
-    return;
+    return false;
 
   int pos;
   FOR_EACH_VEC_ELT (arg_positions, i, pos)
@@ -2411,13 +2412,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
        richloc.add_range (EXPR_LOCATION (arg), false);
     }
 
-  warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
-            "passing argument %i to restrict-qualified parameter"
-            " aliases with argument %Z",
-            "passing argument %i to restrict-qualified parameter"
-            " aliases with arguments %Z",
-            param_pos + 1, arg_positions.address (),
-            arg_positions.length ());
+  return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
+                   "passing argument %i to restrict-qualified parameter"
+                   " aliases with argument %Z",
+                   "passing argument %i to restrict-qualified parameter"
+                   " aliases with arguments %Z",
+                   param_pos + 1, arg_positions.address (),
+                   arg_positions.length ());
 }
 
 /* Callback function to determine whether an expression TP or one of its
index 8257873dd20ce40cfd04ab1834df37b419d3e28a..7771988b83782d0bdcf64d40fe3a68a9678591d5 100644 (file)
@@ -682,11 +682,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
   tree destvar, srcvar;
   location_t loc = gimple_location (stmt);
 
-  tree func = gimple_call_fndecl (stmt);
   bool nowarn = gimple_no_warning_p (stmt);
-  bool check_overlap = (DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE
-                       && DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE_CHK
-                       && !nowarn);
 
   /* If the LEN parameter is a constant zero or in range where
      the only valid value is zero, return DEST.  */
@@ -713,13 +709,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
     {
       /* Avoid diagnosing exact overlap in calls to __builtin_memcpy.
         It's safe and may even be emitted by GCC itself (see bug
-        32667).  However, diagnose it in explicit calls to the memcpy
-        function.  */
-      if (check_overlap && *IDENTIFIER_POINTER (DECL_NAME (func)) != '_')
-       warning_at (loc, OPT_Wrestrict,
-                   "%qD source argument is the same as destination",
-                   func);
-
+        32667).  */
       unlink_stmt_vdef (stmt);
       if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
        release_ssa_name (gimple_vdef (stmt));
@@ -1622,11 +1612,14 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
   /* If SRC and DEST are the same (and not volatile), return DEST.  */
   if (operand_equal_p (src, dest, 0))
     {
-      tree func = gimple_call_fndecl (stmt);
+      if (!gimple_no_warning_p (stmt))
+       {
+         tree func = gimple_call_fndecl (stmt);
 
-      warning_at (loc, OPT_Wrestrict,
-                 "%qD source argument is the same as destination",
-                 func);
+         warning_at (loc, OPT_Wrestrict,
+                     "%qD source argument is the same as destination",
+                     func);
+       }
 
       replace_call_with_value (gsi, dest);
       return true;
@@ -2499,15 +2492,6 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterator *gsi,
      (resp. DEST+LEN for __mempcpy_chk).  */
   if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
     {
-      if (fcode != BUILT_IN_MEMMOVE && fcode != BUILT_IN_MEMMOVE_CHK)
-       {
-         tree func = gimple_call_fndecl (stmt);
-
-         warning_at (loc, OPT_Wrestrict,
-                     "%qD source argument is the same as destination",
-                     func);
-       }
-
       if (fcode != BUILT_IN_MEMPCPY_CHK)
        {
          replace_call_with_value (gsi, dest);
@@ -2609,11 +2593,14 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi,
   /* If SRC and DEST are the same (and not volatile), return DEST.  */
   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
     {
-      tree func = gimple_call_fndecl (stmt);
+      if (!gimple_no_warning_p (stmt))
+       {
+         tree func = gimple_call_fndecl (stmt);
 
-      warning_at (loc, OPT_Wrestrict,
-                 "%qD source argument is the same as destination",
-                 func);
+         warning_at (loc, OPT_Wrestrict,
+                     "%qD source argument is the same as destination",
+                     func);
+       }
 
       replace_call_with_value (gsi, dest);
       return true;
index 5dead01586c103758fce94db56ff6342207bd975..a5e3408c4c4d28b6b47b2814a23a0f13ad038610 100644 (file)
@@ -1,3 +1,18 @@
+2018-03-12  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/83456
+       * c-c++-common/Wrestrict-2.c: Remove test cases.
+       * c-c++-common/Wrestrict.c: Same.
+       * gcc.dg/Wrestrict-12.c: New test.
+       * gcc.dg/Wrestrict-14.c: New test.
+Index: gcc/c-family/c-common.c
+===================================================================
+--- gcc/c-family/c-common.c    (revision 258366)
++++ gcc/c-family/c-common.c    (working copy)
+@@ -5309,10 +5309,11 @@ check_function_sentinel (const_tree fntype, int na
+     }
+ }
+
 2018-03-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        * g++.dg/pr84821.C: New test.
index 2c10eeffb515d6573b0a17a295337c7dc4035abf..c3e9ac82d6412ec8e68b2effd834e937ed7b3d0e 100644 (file)
 
 static void wrap_memcpy (void *d, const void *s, size_t n)
 {
-  memcpy (d, s, n);   /* { dg-warning "source argument is the same as destination" "memcpy" } */
+  memcpy (d, s, n);   /* { dg-warning "accessing 2 bytes at offsets 0 and 1 overlaps 1 byte at offset 1" "memcpy" } */
 }
 
-void call_memcpy (void *d, size_t n)
+void call_memcpy (char *d)
 {
-  const void *s = d;
-  wrap_memcpy (d, s, n);
+  const void *s = d + 1;
+  wrap_memcpy (d, s, 2);
 }
 
 
index e62652f78e1a97d1797785fff51f8b70e9a476cd..36a1ffa412c45f7695a6a0160990f16368d2d7ee 100644 (file)
@@ -52,7 +52,6 @@ void test_memcpy_cst (void *d, const void *s)
   } while (0)
 
   T (a, a, 0);
-  T (a, s = a, 3);           /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 
   /* This isn't detected because memcpy calls with small power-of-2 sizes
      are intentionally folded into safe copies equivalent to memmove.
@@ -63,19 +62,6 @@ void test_memcpy_cst (void *d, const void *s)
   T (a, a + 3, 3);
   T (a, a + 3, 5);           /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 
-  {
-    char a[3] = { 1, 2, 3 };
-
-    /* Verify that a call to memcpy with an exact overlap is diagnosed
-       (also tested above) but an excplicit one to __builtin_memcpy is
-       not.  See bug 32667 for the rationale.  */
-    (memcpy)(a, a, sizeof a);   /* { dg-warning "source argument is the same as destination" "memcpy" } */
-    sink (a);
-
-    __builtin_memcpy (a, a, sizeof a);
-    sink (a);
-  }
-
   {
     char a[3][7];
     sink (a);
@@ -116,11 +102,6 @@ void test_memcpy_cst (void *d, const void *s)
     memcpy (d, s, sizeof x.a);
     sink (&x);
 
-    d = x.a;
-    s = x.a;
-    memcpy (d, s, sizeof x.a);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
-    sink (&x);
-
     d = x.a + 4;
     s = x.b;
     memcpy (d, s, sizeof x.a);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
@@ -447,22 +428,10 @@ void test_memcpy_var (char *d, const char *s)
 {
   size_t n = unsigned_value ();
 
+  /* Since no copying takes place no warning should be issued.  */
   memcpy (d, d, 0);
   sink (d);
 
-  memcpy (d, d, n);               /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  memcpy (d, &d[0], n);           /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  memcpy (&d[0], d,  n);          /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
-  s = d;
-  memcpy (d, s, n);               /* { dg-warning "source argument is the same as destination" "memcpy" } */
-  sink (d);
-
   /* The following overlaps if n is greater than 1.  */
   s = d + 1;
   memcpy (d, s, n);
@@ -499,10 +468,6 @@ void test_memcpy_var (char *d, const char *s)
   s = d + 5;
   n = 7;
   memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
-
-  n = UR (0, 1);
-  s = d;
-  memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
 }
 
 
@@ -941,7 +906,7 @@ void test_strncpy_range (char *d, size_t n)
 
   /* The following overlaps except in the unlikely case that value ()
      is zero, so it's diagnosed.  */
-  T ("012", a, a, n);             /* { dg-warning "source argument is the same as destination " "strncpy" } */
+  T ("012", a, a, n);             /* { dg-warning "\\\[-Wrestrict]" "strncpy" } */
 }
 
 
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-12.c b/gcc/testsuite/gcc.dg/Wrestrict-12.c
new file mode 100644 (file)
index 0000000..84ab6b5
--- /dev/null
@@ -0,0 +1,66 @@
+/* PR tree-optimization/83456 - -Wrestrict false positive on
+   a non-overlapping memcpy in an inline function
+   { dg-do compile }
+   { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" }  */
+
+extern void* memcpy (void*, const void*, __SIZE_TYPE__);
+
+/* Test case from comment #0.  */
+
+inline void pr83456_comment0 (void *d, void *s, unsigned N)
+{
+  if (s != d)
+    memcpy (d, s, N);
+}
+
+void call_pr83456_comment0 (void* src)
+{
+  pr83456_comment0 (src, src, 1);
+}
+
+
+/* Test case from comment #1.  */
+
+char a[4];
+
+void pr83456_comment1 (unsigned n)
+{
+  for (int i = 0; i < 1; i++)
+    {
+      if (!i)
+       continue;
+
+      memcpy (a, a, n);
+    }
+}
+
+/* Test case from comment #2.  */
+
+struct netdevice {
+  void *priv;
+};
+
+struct ip_tunnel {
+  struct netdevice *dev;
+  int ip6rd[3];
+};
+
+struct sit_net {
+  struct netdevice *fb_tunnel_dev;
+};
+
+void ipip6_tunnel_clone_6rd (struct netdevice *dev, struct sit_net *sitn)
+{
+  struct ip_tunnel *t = dev->priv;
+  if (t->dev == sitn->fb_tunnel_dev)
+    return;
+
+  struct ip_tunnel *t0 = sitn->fb_tunnel_dev->priv;
+  memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd));
+}
+
+void sit_init_net (struct sit_net *sitn, struct netdevice *fb_tunnel_dev)
+{
+  sitn->fb_tunnel_dev = fb_tunnel_dev;
+  ipip6_tunnel_clone_6rd (sitn->fb_tunnel_dev, sitn);
+}
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-14.c b/gcc/testsuite/gcc.dg/Wrestrict-14.c
new file mode 100644 (file)
index 0000000..b919fa6
--- /dev/null
@@ -0,0 +1,221 @@
+/* PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping
+   memcpy in an inline function
+   Verify that calls to built-in functions are diagnosed when the pointer
+   arguments to their restrict-qualified parameters are the same (the absence
+   of the false positives reported in PR 83456 is tested in Wrestrict-12.c.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wrestrict -Wno-stringop-truncation" }  */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memcpy (void* restrict, const void* restrict, size_t);
+extern void* mempcpy (void* restrict, const void* restrict, size_t);
+extern char* stpncpy (char* restrict, const char* restrict, size_t);
+extern char* stpcpy (char* restrict, const char* restrict);
+extern char* strncat (char* restrict, const char* restrict, size_t);
+extern char* strcat (char* restrict, const char* restrict);
+extern char* strncpy (char* restrict, const char* restrict, size_t);
+extern char* strcpy (char* restrict, const char* restrict);
+
+struct S
+{
+  char a[4];
+  char *p;
+} s;
+
+void sink (void*);
+
+void test_memcpy (char *p, struct S *q, size_t n)
+{
+  /* The behavior of memcpy() is undefined only when when copying takes
+     place between overlapping objects.  Since a call with a size of zero
+     does nothing, it should not be diagnosed.  */
+  memcpy (p, p, 0);
+  sink (p);
+
+  memcpy (p, p, 1);               /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  memcpy (p, p, n);               /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  memcpy (q->a, q->a, 0);
+  sink (q);
+
+  memcpy (q->p, q->p, 1);         /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  memcpy (&q->a[0], q->a, n);     /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */
+  sink (q);
+
+  memcpy (q, q->a, n);            /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */
+  sink (q);
+}
+
+void test_mempcpy (char *p, struct S *q, size_t n)
+{
+  mempcpy (p, p, 0);
+  sink (p);
+
+  mempcpy (p, p, 1);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  mempcpy (p, p, n);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  mempcpy (q->a, q->a, 0);
+  sink (q);
+
+  mempcpy (q->p, q->p, 1);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  mempcpy (&q->a[0], q->a, n);    /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */
+  sink (q);
+
+  mempcpy (q, q->a, n);           /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */
+  sink (q);
+}
+
+void test_strncat (char *p, struct S *q, size_t n)
+{
+  strncat (p, p, 0);
+  sink (p);
+
+  strncat (p, p, 1);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strncat (p, p, n);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strncat (q->a, q->a, n);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncat (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncat (q->a, &q->a[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncat (q->p, &q->p[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
+
+void test_strcat (char *p, struct S *q, size_t n)
+{
+  strcat (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcat (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcat (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcat (q->a, q->a);            /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcat (&q->a[0], &q->a[0]);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcat (q->a, &q->a[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcat (q->p, &q->p[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
+
+void test_stpncpy (char *p, struct S *q, size_t n)
+{
+  stpncpy (p, p, 0);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpncpy (p, p, 1);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpncpy (p, p, n);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpncpy (q->a, q->a, n);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpncpy (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpncpy (q->a, &q->a[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpncpy (q->p, &q->p[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
+
+void test_stpcpy (char *p, struct S *q, size_t n)
+{
+  stpcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  stpcpy (q->a, q->a);            /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpcpy (&q->a[0], &q->a[0]);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpcpy (q->a, &q->a[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  stpcpy (q->p, &q->p[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
+
+void test_strncpy (char *p, struct S *q, size_t n)
+{
+  strncpy (p, p, 0);
+  sink (p);
+
+  strncpy (p, p, 1);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strncpy (p, p, n);              /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strncpy (q->a, q->a, n);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncpy (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncpy (q->a, &q->a[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strncpy (q->p, &q->p[0], n);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
+
+void test_strcpy (char *p, struct S *q, size_t n)
+{
+  strcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcpy (p, p);                  /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (p);
+
+  strcpy (q->a, q->a);            /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcpy (&q->a[0], &q->a[0]);    /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcpy (q->a, &q->a[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+
+  strcpy (q->p, &q->p[0]);        /* { dg-warning "\\\[-Wrestrict]" } */
+  sink (q);
+}
index 72f6a17cd322ca387d56ed4f58e1e6241bc2b52a..33004b6870d29594985b47ca40e3fcb21bdb3050 100644 (file)
@@ -1801,6 +1801,8 @@ bool
 maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
 {
   gimple *stmt = gsi_stmt (gsi);
+  if (gimple_no_warning_p (stmt))
+    return false;
 
   wide_int cntrange[2];