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.
This commit is contained in:
Martin Sebor 2020-01-23 11:37:02 +01:00
parent 0ed442a40f
commit 8a990ffafa
4 changed files with 72 additions and 2 deletions

View 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.

View 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;
}

View 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.

View File

@ -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);
}