aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtins.c32
-rw-r--r--gcc/calls.c5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/attr-nonstring.c123
5 files changed, 161 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e665b03..79a5e37 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -26,6 +26,14 @@
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.
2018-05-22 Jackson Woodruff <jackson.woodruff@arm.com>
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9a2bf8c..841c1ef 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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)
diff --git a/gcc/calls.c b/gcc/calls.c
index 9d8b96f..35bcff7 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -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)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2e5bb3f..bd1007f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..46f5c0d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-nonstring.c
@@ -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" } */
+}