PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call with a nonstrin...
authorMartin Sebor <msebor@redhat.com>
Tue, 22 May 2018 19:37:48 +0000 (19:37 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 22 May 2018 19:37:48 +0000 (13:37 -0600)
gcc/ChangeLog:

PR middle-end/85359
* builtins.c (expand_builtin_strcpy): Call maybe_warn_nonstring_arg
only when expasion succeeds.
(expand_builtin_strcmp): Same.
(expand_builtin_strncmp): Same.

gcc/testsuite/ChangeLog:

PR middle-end/85359
* gcc.dg/attr-nonstring.c: New test.

From-SVN: r260550

gcc/ChangeLog
gcc/builtins.c
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/attr-nonstring.c [new file with mode: 0644]

index e665b03e1e1c3920fec4609b24aee4f08aff4188..79a5e374d5a88acc846b07587e16a3521549da7b 100644 (file)
 
        * config/aarch64/aarch64.md (*ashift<mode>_extv_bfiz): New pattern.
 
+2018-05-22  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/85359
+       * builtins.c (expand_builtin_strcpy): Call maybe_warn_nonstring_arg
+       only when expasion succeeds.
+       (expand_builtin_strcmp): Same.
+       (expand_builtin_strncmp): Same.
+
 2018-05-22  Martin Sebor  <msebor@redhat.com>
 
        * calls.c (maybe_warn_nonstring_arg): Fix a typo in a comment.
index 9a2bf8c7d3861387f55af171b5e9552e376c67c6..841c1ef4da798de64897b8b7c2d3f2db50ad3a7a 100644 (file)
@@ -3783,7 +3783,17 @@ expand_builtin_strcpy (tree exp, rtx target)
                    src, destsize);
     }
 
-  return expand_builtin_strcpy_args (dest, src, target);
+  if (rtx ret = expand_builtin_strcpy_args (dest, src, target))
+    {
+      /* 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);
+      return ret;
+    }
+
+  return NULL_RTX;
 }
 
 /* Helper function to do the actual work for expand_builtin_strcpy.  The
@@ -4576,14 +4586,14 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
        }
     }
 
-  /* 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.  */
+      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)
@@ -4680,14 +4690,14 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
                                         arg2_rtx, TREE_TYPE (len), arg3_rtx,
                                         MIN (arg1_align, arg2_align));
 
-  /* 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.  */
+      maybe_warn_nonstring_arg (fndecl, exp);
+
       /* Return the value in the proper mode for this function.  */
       mode = TYPE_MODE (TREE_TYPE (exp));
       if (GET_MODE (result) == mode)
index 9d8b96f34ad6afb943900a4769d71322c3983c04..35bcff7c6e579b0e890187756daa03f20fef69d9 100644 (file)
@@ -1671,7 +1671,10 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
   /* Determine the range of the bound argument (if specified).  */
   tree bndrng[2] = { NULL_TREE, NULL_TREE };
   if (bound)
-    get_size_range (bound, bndrng);
+    {
+      STRIP_NOPS (bound);
+      get_size_range (bound, bndrng);
+    }
 
   if (*lenrng)
     {
index 2e5bb3f0fb13bce6eb762d955bc0c1a2252375a8..bd1007f761e0358ec9ef0be51a1f157706dcc7bd 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-22  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/85359
+       * gcc.dg/attr-nonstring.c: New test.
+
 2018-05-22  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/85345
diff --git a/gcc/testsuite/gcc.dg/attr-nonstring.c b/gcc/testsuite/gcc.dg/attr-nonstring.c
new file mode 100644 (file)
index 0000000..46f5c0d
--- /dev/null
@@ -0,0 +1,123 @@
+/* PR middle-end/85359 - duplicate -Wstringop-overflow for a strcmp call
+   with a nonstring pointer
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__       size_t;
+typedef __builtin_va_list   va_list;
+
+int printf (const char*, ...);
+int puts (const char*);
+int puts_unlocked (const char*);
+int sprintf (char*, const char*, ...);
+int snprintf (char*, size_t, const char*, ...);
+int vsprintf (char*, const char*, va_list);
+int vsnprintf (char*, size_t, const char*, va_list);
+
+int strcmp (const char*, const char*);
+int strncmp (const char*, const char*, size_t);
+
+char* stpcpy (char*, const char*);
+char* stpncpy (char*, const char*, size_t);
+
+char* strcat (char*, const char*);
+char* strncat (char*, const char*, size_t);
+
+char* strcpy (char*, const char*);
+char* strncpy (char*, const char*, size_t);
+
+char* strchr (const char*, int);
+char* strrchr (const char*, int);
+char* strstr (const char*, const char*);
+char* strdup (const char*);
+size_t strlen (const char*);
+size_t strnlen (const char*, size_t);
+char* strndup (const char*, size_t);
+
+#define NONSTRING __attribute__ ((nonstring))
+
+extern char ns5[5] 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=]" "strcmp" } */
+}
+
+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=]" "strcmp" } */
+}
+
+int strncmp_nonstring_1 (const char *s)
+{
+  return strncmp (s, ns5, sizeof ns5 + 1);  /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */
+}
+
+int strncmp_nonstring_2 (const char *s)
+{
+  return strncmp (ns5, s, sizeof ns5 + 1);  /* { dg-regexp "\[^\n\r\]+: warning: .strncmp. argument 1 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncmp" } */
+}
+
+char* stpcpy_nonstring (char *d, NONSTRING const char *s)
+{
+  return stpcpy (d, s);  /* { dg-regexp "\[^\n\r\]+: warning: .stpcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "stpcpy" } */
+}
+
+char* stpncpy_nonstring (char *d)
+{
+  return stpncpy (d, ns5, sizeof ns5 + 1);  /* { dg-regexp "\[^\n\r\]+: warning: .stpncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "stpncpy" } */
+}
+
+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=]" "strchr" } */
+}
+
+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=]" "strrchr" } */
+}
+
+char* strcpy_nonstring (char *d, NONSTRING const char *s)
+{
+  return strcpy (d, s);  /* { dg-regexp "\[^\n\r\]+: warning: .strcpy. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strcpy" } */
+}
+
+char* strncpy_nonstring (char *d)
+{
+  return strncpy (d, ns5, sizeof ns5 + 1);  /* { dg-regexp "\[^\n\r\]+: warning: .strncpy. argument 2 declared attribute .nonstring. \[^\n\r\]+ \\\[-Wstringop-overflow=]" "strncpy" } */
+}
+
+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=]" "strstr" } */
+}
+
+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=]" "strstr" } */
+}
+
+char* stdup_nonstring (NONSTRING const char *s)
+{
+  return strdup (s);  /* { dg-regexp "\[^\n\r\]+: warning: .strdup. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strdup" } */
+}
+
+size_t strlen_nonstring (NONSTRING const char *s)
+{
+  return strlen (s);  /* { dg-regexp "\[^\n\r\]+: warning: .strlen. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "strlen" } */
+}
+
+int printf_nonstring (NONSTRING const char *s)
+{
+  return printf (s);  /* { dg-regexp "\[^\n\r\]+: warning: .printf. argument 1 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "printf" } */
+}
+
+int sprintf_nonstring_2 (char *d, NONSTRING const char *s)
+{
+  return sprintf (d, s);  /* { dg-regexp "\[^\n\r\]+: warning: .sprintf. argument 2 declared attribute .nonstring. \\\[-Wstringop-overflow=]" "sprintf" } */
+}