avoid -Wrestrict on sprintf %p with destination as argument (PR 84919)
diff mbox series

Message ID 29df4b53-dfc4-eb1c-3489-97a2dbcdf442@gmail.com
State New
Headers show
Series
  • avoid -Wrestrict on sprintf %p with destination as argument (PR 84919)
Related show

Commit Message

Martin Sebor Jan. 22, 2020, 2:59 p.m. UTC
The early front-end only implementation of -Wrestrict that's still
present in GCC 10 issues a false postive for %p arguments that are
the same as the destination.  Bug 84919 reports an instance of this
false positive in the Linux kernel.

That attached patch suppresses the front-end warning for the sprintf
family of functions, letting the sprintf pass that was in GCC 10
extended to also handle -Wrestrict for these functions, handle
them instead.

Tested on x86_64-linux.

Since this is a regression I'd like to commit the fix to GCC 10.

Martin

Comments

Jeff Law Jan. 22, 2020, 8:35 p.m. UTC | #1
On Wed, 2020-01-22 at 15:59 +0100, Martin Sebor wrote:
> The early front-end only implementation of -Wrestrict that's still
> present in GCC 10 issues a false postive for %p arguments that are
> the same as the destination.  Bug 84919 reports an instance of this
> false positive in the Linux kernel.
> 
> That attached patch suppresses the front-end warning for the sprintf
> family of functions, letting the sprintf pass that was in GCC 10
> extended to also handle -Wrestrict for these functions, handle
> them instead.
> 
> Tested on x86_64-linux.
> 
> Since this is a regression I'd like to commit the fix to GCC 10.
In the BZ your comment indicates that it trips another bogus warning
during bootstrap.  Presumably you already fixed that?  If so, OK.

jeff
Martin Sebor Jan. 22, 2020, 9:03 p.m. UTC | #2
On 1/22/20 9:35 PM, Jeff Law wrote:
> On Wed, 2020-01-22 at 15:59 +0100, Martin Sebor wrote:
>> The early front-end only implementation of -Wrestrict that's still
>> present in GCC 10 issues a false postive for %p arguments that are
>> the same as the destination.  Bug 84919 reports an instance of this
>> false positive in the Linux kernel.
>>
>> That attached patch suppresses the front-end warning for the sprintf
>> family of functions, letting the sprintf pass that was in GCC 10
>> extended to also handle -Wrestrict for these functions, handle
>> them instead.
>>
>> Tested on x86_64-linux.
>>
>> Since this is a regression I'd like to commit the fix to GCC 10.
> In the BZ your comment indicates that it trips another bogus warning
> during bootstrap.  Presumably you already fixed that?  If so, OK.

That was PR 92666, an unrelated C++ bug fixed recently by Jakub.
This time, my bootstrap of this patch went fine.

Martin

Patch
diff mbox series

PR c/84919 - bogus -Wrestrict on sprintf %p with destination as argument

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.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4a7f3a52335..4bb21772c64 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5732,8 +5732,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;
 }
 
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-20.c b/gcc/testsuite/gcc.dg/Wrestrict-20.c
new file mode 100644
index 00000000000..9826e7f4503
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wrestrict-20.c
@@ -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);
+}