PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building glibc ...
authorMartin Sebor <msebor@redhat.com>
Tue, 27 Aug 2019 23:31:44 +0000 (23:31 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 27 Aug 2019 23:31:44 +0000 (17:31 -0600)
gcc/ChangeLog:

PR tree-optimization/91567
* gimple-ssa-sprintf.c (get_string_length): Handle more forms of lengths
of unknown strings.
* vr-values.c (vr_values::extract_range_basic): Set strlen upper bound
to PTRDIFF_MAX - 2.

gcc/testsuite/ChangeLog:

PR tree-optimization/91567
* gcc.dg/tree-ssa/builtin-snprintf-6.c: Xfail a subset of assertions
on targets other than x86_64 to work around PR 83543.
* gcc.dg/tree-ssa/builtin-sprintf-warn-22.c: New test.

From-SVN: r274976

gcc/ChangeLog
gcc/gimple-ssa-sprintf.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-6.c
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c [new file with mode: 0644]
gcc/vr-values.c

index 1d9d6cf0ff29a2e09a3c3269664f626fe616060c..1213e958bb8a2d0b3bda43c7c4bbf99c87e85230 100644 (file)
@@ -1,3 +1,11 @@
+2019-08-27  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/91567
+       * gimple-ssa-sprintf.c (get_string_length): Handle more forms of lengths
+       of unknown strings.
+       * vr-values.c (vr_values::extract_range_basic): Set strlen upper bound
+       to PTRDIFF_MAX - 2.
+
 2019-08-27  Jeff Law  <law@redhat.com>
 
        * tree-ssa-strlen.c (printf_strlen_execute): Initialize
index 6a39a71900a05d264b7e854e4243cd3b88df89ec..b11d7989d5e866cd8cb8f62d41c95657bc91ad79 100644 (file)
@@ -1994,10 +1994,21 @@ get_string_length (tree str, unsigned eltsize, const vr_values *vr)
      or it's SIZE_MAX otherwise.  */
 
   /* Return the default result when nothing is known about the string.  */
-  if (lendata.maxbound
-      && integer_all_onesp (lendata.maxbound)
-      && integer_all_onesp (lendata.maxlen))
-    return fmtresult ();
+  if (lendata.maxbound)
+    {
+      if (integer_all_onesp (lendata.maxbound)
+         && integer_all_onesp (lendata.maxlen))
+       return fmtresult ();
+
+      if (!tree_fits_uhwi_p (lendata.maxbound)
+         || !tree_fits_uhwi_p (lendata.maxlen))
+       return fmtresult ();
+
+      unsigned HOST_WIDE_INT lenmax = tree_to_uhwi (max_object_size ()) - 2;
+      if (lenmax <= tree_to_uhwi (lendata.maxbound)
+         && lenmax <= tree_to_uhwi (lendata.maxlen))
+       return fmtresult ();
+    }
 
   HOST_WIDE_INT min
     = (tree_fits_uhwi_p (lendata.minlen)
index 2560faf85262192687a654a04e615eaa12504cbd..cd6fb7fc8f6a4a633da73008e6842edbb190d1f4 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-27  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/91567
+       * gcc.dg/tree-ssa/builtin-snprintf-6.c: Xfail a subset of assertions
+       on targets other than x86_64 to work around PR 83543.
+       * gcc.dg/tree-ssa/builtin-sprintf-warn-22.c: New test.
+
 2019-08-27  Jeff Law  <law@redhat.com>
 
        * gcc.c-torture/compile/20190827-1.c: New test.
index 0d9b27505ec4648f39dee39aa727350b8c6d9b0e..df0e6b7d19c89f96f30c909487b502ccf0202746 100644 (file)
@@ -65,6 +65,10 @@ void test_assign_init_list (void)
   T (5, ARGS ({ 1, 2, 3, 4, 5, 6, 0 }), "s=%.*s", 3, &a[2]);
 }
 
+#if __x86_64__
+
+/* Enabled only on x86_64 to work around PR 83543.  */
+
 #undef T
 #define T(expect, init, fmt, ...)                      \
   do {                                                 \
@@ -87,6 +91,9 @@ void test_assign_aggregate (void)
   T (5, "123456", "s=%.*s", 3, &s.a[2]);
 }
 
+/* { dg-final { scan-tree-dump-times "Function test_assign_aggregate" 1 "optimized" { xfail { { ! x86_64-*-* } || { ilp32 } } } } } */
+
+#endif   /* x86_64 */
 
 #undef T
 #define T(expect, init, fmt, ...)                      \
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-22.c
new file mode 100644 (file)
index 0000000..6fd1bca
--- /dev/null
@@ -0,0 +1,58 @@
+/* PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building
+   glibc (32-bit only)
+   { dg-do compile }
+   { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern int sprintf (char*, const char*, ...);
+extern size_t strlen (const char*);
+
+void f (char *);
+
+void g (char *s1, char *s2)
+{
+  char b[1025];
+  size_t n = __builtin_strlen (s1), d = __builtin_strlen (s2);
+  if (n + d + 1 >= 1025)
+    return;
+
+  sprintf (b, "%s.%s", s1, s2);     // { dg-bogus "\\\[-Wformat-overflow" }
+
+  f (b);
+}
+
+/* Extracted from gcc/c-cppbuiltin.c.  */
+
+void cpp_define (char*);
+
+static void
+builtin_define_type_minmax (const char *min_macro, const char *max_macro,
+                           void *type)
+{
+  extern const char *suffix;
+  char *buf;
+
+  if (type)
+    {
+      buf = (char *) __builtin_alloca (__builtin_strlen (min_macro) + 2
+                                      + __builtin_strlen (suffix) + 1);
+      sprintf (buf, "%s=0%s", min_macro, suffix);      // { dg-bogus "\\\[-Wformat-overflow" }
+    }
+  else
+    {
+      buf = (char *) __builtin_alloca (__builtin_strlen (min_macro) + 3
+                                      + __builtin_strlen (max_macro) + 6);
+      sprintf (buf, "%s=(-%s - 1)", min_macro, max_macro);  // { dg-bogus "\\\[-Wformat-overflow" }
+    }
+
+  cpp_define (buf);
+}
+
+void
+c_cpp_builtins (void *type)
+{
+
+  builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__", type);
+  builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", type);
+}
index 96c764c987be96f71f5b4369d85e77f461130582..256cae73ebb88abf9b0bd00fe355405185cac627 100644 (file)
@@ -1319,7 +1319,12 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
                tree max = vrp_val_max (ptrdiff_type_node);
                wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
                tree range_min = build_zero_cst (type);
-               tree range_max = wide_int_to_tree (type, wmax - 1);
+               /* To account for the terminating NUL, the maximum length
+                  is one less than the maximum array size, which in turn
+                  is one  less than PTRDIFF_MAX (or SIZE_MAX where it's
+                  smaller than the former type).
+                  FIXME: Use max_object_size() - 1 here.  */
+               tree range_max = wide_int_to_tree (type, wmax - 2);
                vr->set (VR_RANGE, range_min, range_max);
                return;
              }