diff options
author | Martin Sebor <msebor@redhat.com> | 2020-01-23 11:37:02 +0100 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-01-23 11:37:02 +0100 |
commit | 8a990ffafaaa18981c6e91d4ed88f05ed74c5f3f (patch) | |
tree | 6f5fb53b4e87c5473a3c80a390e87440b1074396 | |
parent | 0ed442a40f912b09297359ee3675c819c073208f (diff) | |
download | gcc-8a990ffafaaa18981c6e91d4ed88f05ed74c5f3f.zip gcc-8a990ffafaaa18981c6e91d4ed88f05ed74c5f3f.tar.gz gcc-8a990ffafaaa18981c6e91d4ed88f05ed74c5f3f.tar.bz2 |
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.
-rw-r--r-- | gcc/c-family/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wrestrict-20.c | 41 |
4 files changed, 72 insertions, 2 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 89a66bd..0b9c604 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -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. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 774e29b..7e2dfb3 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 d23b3d1..22c172f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..9826e7f --- /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); +} |