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=]" } */
+}

Reply via email to