The attached patch makes a small tweak to avoid issuing a duplicate warning for calls to strcmp with a nonstring argument. The most onerous part of this was figuring out how to test for the absence of duplicate warnings. The "hack" I used (dg-regexp) is in place until a more straightforward solution becomes available. (David Malcolm has something planned for GCC 9.)
Martin
PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call with a nonstring pointer gcc/ChangeLog: PR middle-end/85359 * builtins.c (expand_builtin_strcmp): Take care to avoid issuing a duplicate warning. gcc/testsuite/ChangeLog: PR middle-end/85359 * gcc.dg/attr-nonstring.c: New test. Index: gcc/builtins.c =================================================================== --- gcc/builtins.c (revision 259298) +++ gcc/builtins.c (working copy) @@ -4570,14 +4570,15 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED } } - /* Check to see if the argument was declared attribute nonstring - and if so, issue a warning since at this point it's not known - to be nul-terminated. */ tree fndecl = get_callee_fndecl (exp); - maybe_warn_nonstring_arg (fndecl, exp); - if (result) { + /* Check to see if the argument was declared attribute nonstring + and if so, issue a warning since at this point it's not known + to be nul-terminated. Avoid doing this when RESULT is false + and let expand_call() do it. */ + maybe_warn_nonstring_arg (fndecl, exp); + /* Return the value in the proper mode for this function. */ machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) Index: gcc/testsuite/gcc.dg/attr-nonstring.c =================================================================== --- gcc/testsuite/gcc.dg/attr-nonstring.c (nonexistent) +++ gcc/testsuite/gcc.dg/attr-nonstring.c (working copy) @@ -0,0 +1,58 @@ +/* PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call + with a nonstring pointer + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +extern char* strchr (const char*, int); +extern char* strrchr (const char*, int); +extern char* stpcpy (char*, const char*); +extern char* strcpy (char*, const char*); +extern int strcmp (const char*, const char*); +extern char* strstr (const char*, const char*); + +#define NONSTRING __attribute__ ((nonstring)) + +int strcmp_nonstring_1 (NONSTRING const char *a, const char *b) +{ + /* dg-warning matches one or more instances of the warning so it's + no good on its own. Use dg-regexp instead to verify that just + one instance of the warning is issued. See gcc.dg/pr64223-1 + for a different approach. */ + return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +int strcmp_nonstring_2 (const char *a, NONSTRING const char *b) +{ + return strcmp (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcmp. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + + +char* stpcpy_nonstring (char *a, NONSTRING const char *b) +{ + return stpcpy (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +char* strchr_nonstring (NONSTRING const char *s, int c) +{ + return strchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +char* strrchr_nonstring (NONSTRING const char *s, int c) +{ + return strrchr (s, c); /* { dg-regexp "\[^\n\r\]+: warning: .strrchr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +char* strcpy_nonstring (char *a, NONSTRING const char *b) +{ + return strcpy (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +char* strstr_nonstring_1 (NONSTRING const char *a, const char *b) +{ + return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +} + +char* strstr_nonstring_2 (const char *a, NONSTRING const char *b) +{ + return strstr (a, b); /* { dg-regexp "\[^\n\r\]+: warning: .strstr. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" } */ +}