From 8a990ffafaaa18981c6e91d4ed88f05ed74c5f3f Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 23 Jan 2020 11:37:02 +0100 Subject: [PATCH] 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. --- gcc/c-family/ChangeLog | 6 +++++ gcc/c-family/c-common.c | 22 ++++++++++++++-- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/Wrestrict-20.c | 41 +++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-20.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 89a66bd4f84..0b9c604956a 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2020-01-23 Martin Sebor + + PR c/84919 + * c-common.c (check_function_arguments): Avoid overlap checking + of sprintf functions. + 2020-01-22 Jason Merrill PR testsuite/93391 - PR 40752 test fails with unsigned plain char. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 774e29be104..7e2dfb3ebe1 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d23b3d1fb26..22c172f299b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-01-23 Martin Sebor + + PR c/84919 + * gcc.dg/Wrestrict-20.c: New test. + 2020-01-23 Richard Sandiford * 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 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); +} -- 2.30.2