PR c/84919 - bogus -Wrestrict on sprintf %p with destination as argument
authorMartin Sebor <msebor@redhat.com>
Thu, 23 Jan 2020 10:37:02 +0000 (11:37 +0100)
committerMartin Sebor <msebor@redhat.com>
Thu, 23 Jan 2020 10:37:02 +0000 (11:37 +0100)
gcc/c-family/ChangeLog:

PR c/84919
* c-common.c (check_function_arguments): Avoid overlap checking
of sprintf functions.

gcc/testsuite/ChangeLog:

PR c/84919
* gcc.dg/Wrestrict-20.c: New test.

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wrestrict-20.c [new file with mode: 0644]

index 89a66bd4f8486c3e42738a0ef5c6b2132e868921..0b9c604956a4ba340c6a653349dff1c66674475e 100644 (file)
@@ -1,3 +1,9 @@
+2020-01-23  Martin Sebor  <msebor@redhat.com>
+
+       PR c/84919
+       * c-common.c (check_function_arguments): Avoid overlap checking
+       of sprintf functions.
+
 2020-01-22  Jason Merrill  <jason@redhat.com>
 
        PR testsuite/93391 - PR 40752 test fails with unsigned plain char.
index 774e29be1041a08743a166308bcb0047b031af05..7e2dfb3ebe1590f5ef679381f16c49e09249d205 100644 (file)
@@ -5729,8 +5729,26 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
   if (warn_format)
     check_function_sentinel (fntype, nargs, argarray);
 
-  if (warn_restrict)
-    warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
+  if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+    {
+      switch (DECL_FUNCTION_CODE (fndecl))
+       {
+       case BUILT_IN_SPRINTF:
+       case BUILT_IN_SPRINTF_CHK:
+       case BUILT_IN_SNPRINTF:
+       case BUILT_IN_SNPRINTF_CHK:
+         /* Let the sprintf pass handle these.  */
+         return warned_p;
+
+       default:
+         break;
+       }
+    }
+
+  /* check_function_restrict sets the DECL_READ_P for arguments
+     so it must be called unconditionally.  */
+  warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
+
   return warned_p;
 }
 
index d23b3d1fb261b9c7cca7b054823ebdce2ec94c64..22c172f299bb95c063d74347007db7c9c072ff5c 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-23  Martin Sebor  <msebor@redhat.com>
+
+       PR c/84919
+       * gcc.dg/Wrestrict-20.c: New test.
+
 2020-01-23  Richard Sandiford  <richard.sandiford@arm.com>
 
        * g++.target/aarch64/sve/acle/general-c++/whilele_1.C: Skip for ILP32.
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-20.c b/gcc/testsuite/gcc.dg/Wrestrict-20.c
new file mode 100644 (file)
index 0000000..9826e7f
--- /dev/null
@@ -0,0 +1,41 @@
+/* PR c/84919 - bogus -Wrestrict on sprintf %p with destination as argument
+   { dg-do compile }
+   -O2 isn't strictly necessary but setting also verifies that the sprintf/
+   strlen pass doesn't warn with non-constant arguments.
+   { dg-options "-O2 -Wall" } */
+
+extern int sprintf (char* restrict, const char* restrict, ...);
+extern int snprintf (char* restrict, __SIZE_TYPE__, const char* restrict, ...);
+
+char a[32];
+
+void test_warn (char *p)
+{
+  a[0] = 0;
+  sprintf (a, "a=%s", a);     /* { dg-warning "-Wrestrict" } */
+
+  p = a;
+  char *q = p + 1;
+  sprintf (p, "a=%s", q);     /* { dg-warning "-Wrestrict" } */
+}
+
+void test_nowarn_front_end (char *d)
+{
+  sprintf (d, "%p", d);
+  snprintf (d, 32, "%p", d);
+
+  sprintf (a, "p=%p", a);
+  snprintf (a, sizeof a, "%p", a);
+}
+
+void test_nowarn_sprintf_pass (char *d)
+{
+  char *q = d;
+  
+  sprintf (d, "p=%p", q);
+  snprintf (d, 32, "p=%p", q);
+
+  q = a;
+  sprintf (a, "a=%p", q);
+  snprintf (a, sizeof a, "a=%p", q);
+}