PR target/77676 - powerpc64 and powerpc64le stage2 bootstrap fail
authorMartin Sebor <msebor@redhat.com>
Thu, 22 Sep 2016 21:28:07 +0000 (21:28 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Thu, 22 Sep 2016 21:28:07 +0000 (15:28 -0600)
gcc/testsuite/ChangeLog:

PR target/77676
* gcc.dg/tree-ssa/builtin-sprintf-1.c: Define and use wint_t.
* gcc.dg/tree-ssa/builtin-sprintf-2.c: Fix typo.
* gcc.dg/tree-ssa/builtin-sprintf-3.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-5.c: New test.

gcc/ChangeLog:

PR target/77676
* gimple-ssa-sprintf.c (target_int_min, target_int_max): Use
HOST_BITS_PER_WIDE_INT, make a static local variable auto.
(target_int_min): Correct computation.
(format_integer): Use long long as the argument for the ll length
modifier.
(format_floating): Use target_int_max().
(get_string_length): Same.
(format_string): Avoid setting the bounded flag for strings
of unknown length.
(try_substitute_return_value): Avoid setting range info when
the result isn't bounded.
* varasm.c (assemble_name): Increase buffer size.

From-SVN: r240383

gcc/ChangeLog
gcc/gimple-ssa-sprintf.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-1.c
gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-5.c [new file with mode: 0644]
gcc/varasm.c

index 2fbe852ab54c30641a5c3e4770b920260bf4e75c..5d993020d80c5c062be2d2a7460fec7d2649c3cf 100644 (file)
@@ -1,3 +1,19 @@
+2016-09-22  Martin Sebor  <msebor@redhat.com>
+
+       PR target/77676
+       * gimple-ssa-sprintf.c (target_int_min, target_int_max): Use
+       HOST_BITS_PER_WIDE_INT, make a static local variable auto.
+       (target_int_min): Correct computation.
+       (format_integer): Use long long as the argument for the ll length
+       modifier.
+       (format_floating): Use target_int_max().
+       (get_string_length): Same.
+       (format_string): Avoid setting the bounded flag for strings
+       of unknown length.
+       (try_substitute_return_value): Avoid setting range info when
+       the result isn't bounded.
+       * varasm.c (assemble_name): Increase buffer size.
+
 2016-09-22  Andre Vieira  <andre.simoesdiasvieira@arm.com>
            Terry Guo  <terry.guo@arm.com>
 
index 5ababe2f2aa2d69e3f5d2b037a7eee4780eb1689..2e15149cda0ede6a436970fa891fb4fd136b2658 100644 (file)
@@ -210,9 +210,9 @@ struct format_result
 static HOST_WIDE_INT
 target_int_min ()
 {
-  static const unsigned HOST_WIDE_INT int_min
-    = 1LLU << (sizeof int_min * CHAR_BIT
-              - TYPE_PRECISION (integer_type_node) + 1);
+  const unsigned HOST_WIDE_INT int_min
+    = HOST_WIDE_INT_M1U << (TYPE_PRECISION (integer_type_node) - 1);
+
   return int_min;
 }
 
@@ -221,8 +221,8 @@ target_int_min ()
 static unsigned HOST_WIDE_INT
 target_int_max ()
 {
-  static const unsigned HOST_WIDE_INT int_max
-    = HOST_WIDE_INT_M1U >> (sizeof int_max * CHAR_BIT
+  const unsigned HOST_WIDE_INT int_max
+    = HOST_WIDE_INT_M1U >> (HOST_BITS_PER_WIDE_INT
                            - TYPE_PRECISION (integer_type_node) + 1);
   return int_max;
 }
@@ -851,7 +851,9 @@ format_integer (const conversion_spec &spec, tree arg)
 
     case FMT_LEN_L:
     case FMT_LEN_ll:
-      dirtype = sign ? long_integer_type_node : long_unsigned_type_node;
+      dirtype = (sign
+                ? long_long_integer_type_node
+                : long_long_unsigned_type_node);
       break;
 
     case FMT_LEN_z:
@@ -1366,7 +1368,7 @@ format_floating (const conversion_spec &spec, tree arg)
          *minmax[i] = mpfr_snprintf (NULL, 0, fmtstr, mpfrval);
        }
 
-      res.bounded = res.range.min < HOST_WIDE_INT_MAX;
+      res.bounded = res.range.min < target_int_max ();
       return res;
     }
 
@@ -1420,7 +1422,7 @@ get_string_length (tree str)
       /* Set RES.BOUNDED to true if and only if all strings referenced
         by STR are known to be bounded (though not necessarily by their
         actual length but perhaps by their maximum possible length).  */
-      res.bounded = res.range.max < HOST_WIDE_INT_MAX;
+      res.bounded = res.range.max < target_int_max ();
 
       /* Set RES.CONSTANT to false even though that may be overly
         conservative in rare cases like: 'x ? a : b' where a and
@@ -1471,6 +1473,10 @@ format_string (const conversion_spec &spec, tree arg)
        : 2 == warn_format_length ? 0 <= prec ? prec : 1
        : HOST_WIDE_INT_MAX);
 
+  /* The result is bounded unless overriddden for a non-constant string
+     of an unknown length.  */
+  bool bounded = true;
+
   if (spec.specifier == 'c')
     {
       if (spec.modifier == FMT_LEN_l)
@@ -1550,16 +1556,17 @@ format_string (const conversion_spec &spec, tree arg)
          if (0 <= prec)
            {
              if ((unsigned)prec < slen.range.min
-                 || slen.range.min >= HOST_WIDE_INT_MAX)
+                 || slen.range.min >= target_int_max ())
                slen.range.min = prec;
              if ((unsigned)prec < slen.range.max
-                 || slen.range.max >= HOST_WIDE_INT_MAX)
+                 || slen.range.max >= target_int_max ())
                slen.range.max = prec;
            }
-         else if (slen.range.min >= HOST_WIDE_INT_MAX)
+         else if (slen.range.min >= target_int_max ())
            {
              slen.range.min = max_bytes_for_unknown_str;
              slen.range.max = max_bytes_for_unknown_str;
+             bounded = false;
            }
 
          res.range = slen.range;
@@ -1580,7 +1587,8 @@ format_string (const conversion_spec &spec, tree arg)
     res.range.max = width;
 
   /* Adjust BOUNDED if width happens to make them equal.  */
-  if (res.range.min == res.range.max && res.range.min < HOST_WIDE_INT_MAX)
+  if (res.range.min == res.range.max && res.range.min < target_int_max ()
+      && bounded)
     res.bounded = true;
 
   return res;
@@ -2389,6 +2397,7 @@ try_substitute_return_value (gimple_stmt_iterator gsi,
       unsigned HOST_WIDE_INT maxbytes;
 
       if (lhs
+         && res.bounded
          && ((maxbytes = res.number_chars - 1) <= target_int_max ()
              || (res.number_chars_min - 1 <= target_int_max ()
                  && (maxbytes = res.number_chars_max - 1) <= target_int_max ()))
index fff439af964d1f3c11c33e17a41efc6f4b0da138..75e7b3e075dc571bcfc2a677f3904b5a8551f38d 100644 (file)
@@ -1,3 +1,11 @@
+2016-09-22  Martin Sebor  <msebor@redhat.com>
+
+       PR target/77676
+       * gcc.dg/tree-ssa/builtin-sprintf-1.c: Define and use wint_t.
+       * gcc.dg/tree-ssa/builtin-sprintf-2.c: Fix typo.
+       * gcc.dg/tree-ssa/builtin-sprintf-3.c: New test.
+       * gcc.dg/tree-ssa/builtin-sprintf-warn-5.c: New test.
+
 2016-09-22  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.dg/ifcvt-1.c: Compile also for 64-bit i?86-*-* target.
index f7abfd8ba0d7f5bb995cada912086ee52f00bdf3..d6a0e6bd81d7a887c071b71d2038da7e5fba68bf 100644 (file)
@@ -77,7 +77,7 @@ EQL (   4097, sizeof buf8k, "%.4095f",     1.0);
 enum { imax2 = (INT_MAX / 2) * 2 };
 EQL (imax2, -1, "%*c%*c", INT_MAX / 2, 'x', INT_MAX / 2, 'y');
 
-/* Verify that range inforation for calls that overflow the destination
+/* Verify that range information for calls that overflow the destination
    isn't available.  */
 RNG (0,  0,  0, "%hhi", i)
 RNG (0,  0,  1, "%hhi", i)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-3.c
new file mode 100644 (file)
index 0000000..207ee7e
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR bootstrap/77676 - powerpc64 and powerpc64le stage2 bootstrap fail
+   Test case derived from the one submitted in the bug.  It verifies
+   that the sprintf return value (or value range) optimization is not
+   performed for an unknown string.  */
+/* { dg-compile } */
+/* { dg-options "-O2 -Wall -Werror -fdump-tree-optimized -fprintf-return-value" } */
+
+#define INT_MAX   __INT_MAX__
+#define INT_MIN   (-INT_MAX - 1)
+
+extern void string_eq_min_fail ();
+extern void string_eq_max_fail ();
+
+extern void string_lt_0_fail ();
+extern void string_eq_0_fail ();
+extern void string_gt_0_fail ();
+
+void test_string (char *d, const char *s)
+{
+  int n = __builtin_sprintf (d, "%-s", s);
+
+  /* Verify that the return value is NOT assumed NOT to be INT_MIN
+     or INT_MAX.  (This is a white box test based on knowing that
+     the optimization computes its own values of the two constants.)  */
+  if (n == INT_MIN) string_eq_min_fail ();
+  if (n == INT_MAX) string_eq_max_fail ();
+
+  /* The return value could be negative when strlen(s) is in excess
+     of 4095 (the maximum number of bytes a single directive is required
+     to handle).  */
+  if (n < 0) string_lt_0_fail ();
+  if (n == 0) string_eq_0_fail ();
+  if (n > 0) string_gt_0_fail ();
+}
+
+/* { dg-final { scan-tree-dump-times "string_eq_min_fail" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "string_eq_max_fail" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "string_lt_0_fail"   1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "string_eq_0_fail"   1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "string_gt_0_fail"   1 "optimized" } } */
index 7261dbdc4a8c2e0c45194d210eb09b66d4bc76c4..e098be92bb0377414b1f9cacf5e4d2a3398e74ec 100644 (file)
@@ -32,6 +32,8 @@ typedef __SIZE_TYPE__ size_t;
 typedef __WCHAR_TYPE__ wchar_t;
 #endif
 
+typedef __WINT_TYPE__ wint_t;
+
 typedef unsigned char UChar;
 
 const char s0[] = "";
@@ -92,7 +94,7 @@ void test_sprintf_p_const (void)
      format null pointers as 0 or 0x0 and so the following will only be
      diagnosed on the former targets.  */
   T (5, "%p",     (void*)0);
-  /* { dg-warning "nul past the end" "(nil)" { target *-linux-gnu *-*-uclinux } 94 } */
+  /* { dg-warning "nul past the end" "(nil)" { target *-linux-gnu *-*-uclinux } 96 } */
 
   /* The exact output for %p is unspecified by C.  Two formats are known:
      same as %tx (for example AIX) and same as %#tx (for example Solaris).  */
@@ -104,8 +106,8 @@ void test_sprintf_p_const (void)
      as with signed integer conversions (i.e., it prepends a space).  Other
      known implementations ignore it.  */
   T (6, "% p",    (void*)0x234);  /* { dg-warning ". . flag used with .%p." } */
-  /* { dg-warning "nul past the end" "Glibc %p" { target *-linux-gnu } 106 } */
-  /* { dg-warning "nul past the end" "Generic %p" { target *-*-uclinux } 106 } */
+  /* { dg-warning "nul past the end" "Glibc %p" { target *-linux-gnu } 108 } */
+  /* { dg-warning "nul past the end" "Generic %p" { target *-*-uclinux } 108 } */
 }
 
 /* Verify that no warning is issued for calls that write into a flexible
@@ -215,16 +217,16 @@ void test_sprintf_chk_c_const (void)
   /* The following could result in as few as no bytes and in as many as
      MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
      the write cannot be reliably diagnosed.  */
-  T (2, "%lc",  L'1');
-  T (2, "%1lc", L'1');
+  T (2, "%lc",  (wint_t)L'1');
+  T (2, "%1lc", (wint_t)L'1');
   /* Writing some unknown number of bytes into a field two characters wide.  */
-  T (2, "%2lc", L'1');          /* { dg-warning "nul past the end" } */
+  T (2, "%2lc", (wint_t)L'1');          /* { dg-warning "nul past the end" } */
 
-  T (3, "%lc%c",   L'1', '2');
+  T (3, "%lc%c",   (wint_t)L'1', '2');
   /* Here in the best case each argument will format as single character,
      causing the terminating NUL to be written past the end.  */
-  T (3, "%lc%c%c", L'1', '2', '3');   /* { dg-warning "nul past the end" } */
-  T (3, "%lc%lc%c", L'1', L'2', '3'); /* { dg-warning "nul past the end" } */
+  T (3, "%lc%c%c", (wint_t)L'1', '2', '3');   /* { dg-warning "nul past the end" } */
+  T (3, "%lc%lc%c", (wint_t)L'1', (wint_t)L'2', '3'); /* { dg-warning "nul past the end" } */
 }
 
 /* Exercise the "%s" and "%ls" directive with constant arguments.  */
@@ -1242,17 +1244,17 @@ void test_snprintf_c_const (void)
   /* The following could result in as few as a single byte and in as many
      as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
      the write cannot be reliably diagnosed.  */
-  T (2, "%lc",  L'1');
-  T (2, "%1lc", L'1');
+  T (2, "%lc",  (wint_t)L'1');
+  T (2, "%1lc", (wint_t)L'1');
   /* Writing at least 1 characted into a field two characters wide.  */
-  T (2, "%2lc", L'1');          /* { dg-warning "output truncated before the last format character" } */
+  T (2, "%2lc", (wint_t)L'1');          /* { dg-warning "output truncated before the last format character" } */
 
-  T (3, "%lc%c",   L'1', '2');
+  T (3, "%lc%c",   (wint_t)'1', '2');
   /* Here in the best case each argument will format as single character,
      causing the output to be truncated just before the terminating NUL
      (i.e., cutting off the '3').  */
-  T (3, "%lc%c%c", L'1', '2', '3');   /* { dg-warning "output truncated" } */
-  T (3, "%lc%lc%c", L'1', L'2', '3'); /* { dg-warning "output truncated" } */
+  T (3, "%lc%c%c", (wint_t)'1', '2', '3');   /* { dg-warning "output truncated" } */
+  T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output truncated" } */
 }
 
 #undef T
@@ -1291,17 +1293,17 @@ void test_snprintf_chk_c_const (void)
   /* The following could result in as few as a single byte and in as many
      as MB_CUR_MAX, but since the MB_CUR_MAX value is a runtime property
      the write cannot be reliably diagnosed.  */
-  T (2, "%lc",  L'1');
-  T (2, "%1lc", L'1');
+  T (2, "%lc",  (wint_t)L'1');
+  T (2, "%1lc", (wint_t)L'1');
   /* Writing at least 1 characted into a field two characters wide.  */
-  T (2, "%2lc", L'1');          /* { dg-warning "output truncated before the last format character" } */
+  T (2, "%2lc", (wint_t)'1');          /* { dg-warning "output truncated before the last format character" } */
 
-  T (3, "%lc%c",   L'1', '2');
+  T (3, "%lc%c",   (wint_t)'1', '2');
   /* Here in the best case each argument will format as single character,
      causing the output to be truncated just before the terminating NUL
      (i.e., cutting off the '3').  */
-  T (3, "%lc%c%c", L'1', '2', '3');   /* { dg-warning "output truncated" } */
-  T (3, "%lc%lc%c", L'1', L'2', '3'); /* { dg-warning "output truncated" } */
+  T (3, "%lc%c%c", (wint_t)'1', '2', '3');   /* { dg-warning "output truncated" } */
+  T (3, "%lc%lc%c", (wint_t)'1', (wint_t)'2', '3'); /* { dg-warning "output truncated" } */
 }
 
 /* Macro to verify that calls to __builtin_vsprintf (i.e., with no size
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-5.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-warn-5.c
new file mode 100644 (file)
index 0000000..f6f60cc
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR bootstrap/77676 - powerpc64 and powerpc64le stage2 bootstrap fail
+   Test case from comment 6 on the bug.  */
+/* { dg-compile } */
+/* { dg-options "-Wall -Werror" } */
+/* { dg-additional-options "-m32" { target { i?86-*-* x86_64-*-* } } } */
+
+struct A
+{
+  const char *a;
+  int b;
+  const char *c;
+};
+
+void bar (char *);
+
+void
+foo (struct A *p)
+{
+  char s[4096];
+  const char *u = p->a;
+  const char *t;
+  while ((t = __builtin_strstr (u, "gcc/")))
+    u = t + 4;
+
+  /* Verfiy the following doesn't emit a warning.  */
+  __builtin_sprintf (s, "%s:%i (%s)", u, p->b, p->c);
+  bar (s);
+}
index 72cba8678709f2568372120523a2db4dabf7130d..4da9e21b69ce8c0251bda6b882dfd999b313b0ff 100644 (file)
@@ -2545,7 +2545,7 @@ assemble_name (FILE *file, const char *name)
 rtx
 assemble_static_space (unsigned HOST_WIDE_INT size)
 {
-  char name[12];
+  char name[16];
   const char *namestring;
   rtx x;