PR middle-end/78461 - [7 Regression] ICE: in operator+=
authorMartin Sebor <msebor@redhat.com>
Wed, 23 Nov 2016 16:44:16 +0000 (16:44 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Wed, 23 Nov 2016 16:44:16 +0000 (09:44 -0700)
gcc/testsuite/ChangeLog:

PR middle-end/78461
* gcc.dg/tree-ssa/builtin-sprintf-4.c: New test.
* gcc.dg/tree-ssa/builtin-sprintf-warn-2.c: Adjust warning text.

gcc/ChangeLog:

PR middle-end/78461
* gimple-ssa-sprintf.c (format_string): Correct the maxima and
set the minimum number of bytes for an unknown string to zero.

From-SVN: r242769

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

index f082b0a..98678e2 100644 (file)
@@ -1,3 +1,9 @@
+2016-11-23  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/78461
+       * gimple-ssa-sprintf.c (format_string): Correct the maxima and
+       set the minimum number of bytes for an unknown string to zero.
+
 2016-11-23  Martin Jambor  <mjambor@suse.cz>
            Martin Liska  <mliska@suse.cz>
 
index 3138ad3..ead8b0e 100644 (file)
@@ -1533,18 +1533,15 @@ format_string (const conversion_spec &spec, tree arg)
   fmtresult res;
 
   /* The maximum number of bytes for an unknown wide character argument
-     to a "%lc" directive adjusted for precision but not field width.  */
+     to a "%lc" directive adjusted for precision but not field width.
+     6 is the longest UTF-8 sequence for a single wide character.  */
   const unsigned HOST_WIDE_INT max_bytes_for_unknown_wc
-    = (1 == warn_format_length ? 0 <= prec ? prec : 0
-       : 2 == warn_format_length ? 0 <= prec ? prec : 1
-       : 0 <= prec ? prec : 6 /* Longest UTF-8 sequence.  */);
+    = (0 <= prec ? prec : 1 < warn_format_length ? 6 : 1);
 
   /* The maximum number of bytes for an unknown string argument to either
      a "%s" or "%ls" directive adjusted for precision but not field width.  */
   const unsigned HOST_WIDE_INT max_bytes_for_unknown_str
-    = (1 == warn_format_length ? 0 <= prec ? prec : 0
-       : 2 == warn_format_length ? 0 <= prec ? prec : 1
-       : HOST_WIDE_INT_MAX);
+    = (0 <= prec ? prec : 1 < warn_format_length);
 
   /* The result is bounded unless overriddden for a non-constant string
      of an unknown length.  */
@@ -1648,7 +1645,7 @@ format_string (const conversion_spec &spec, tree arg)
          if (0 <= prec)
            {
              if (slen.range.min >= target_int_max ())
-               slen.range.min = max_bytes_for_unknown_str;
+               slen.range.min = 0;
              else if ((unsigned)prec < slen.range.min)
                slen.range.min = prec;
 
index 6abbd3b..d5055da 100644 (file)
@@ -1,3 +1,9 @@
+2016-11-23  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/78461
+       * gcc.dg/tree-ssa/builtin-sprintf-4.c: New test.
+       * gcc.dg/tree-ssa/builtin-sprintf-warn-2.c: Adjust warning text.
+
 2016-11-23  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/71450
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-4.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-4.c
new file mode 100644 (file)
index 0000000..4244874
--- /dev/null
@@ -0,0 +1,69 @@
+/* PR middle-end/78461 - [7 Regression] ICE: in operator+=, at
+   gimple-ssa-sprintf.c:214
+   Disable warnings to exercise code paths through the pass that may
+   not be exercised when the -Wformat-length option is in effect.  */
+/* { dg-compile }
+   { dg-options "-O2 -fdump-tree-optimized -w" } */
+
+
+#define CAT(s, n)   s ## n
+#define FAIL(line)  CAT (failure_on_line_, line)
+
+/* Emit a call to a function named failure_on_line_NNN when EXPR is false.  */
+#define ASSERT(expr)                           \
+  do {                                         \
+    extern void FAIL (__LINE__)(void);         \
+    if (!(expr)) FAIL (__LINE__)();            \
+  } while (0)
+
+#define KEEP(line)  CAT (keep_call_on_line_, line)
+
+/* Emit a call to a function named keep_call_on_line_NNN when EXPR is true.
+   Used to verify that the expression need not be the only one that holds.  */
+#define ASSERT_MAYBE(expr)                     \
+  do {                                         \
+    extern void KEEP (__LINE__)(void);         \
+    if (expr) KEEP (__LINE__)();               \
+  } while (0)
+
+int f0 (const char *s)
+{
+  int n = __builtin_snprintf (0, 0, "%.*s%08x", 1, s, 1);
+
+  ASSERT (7 < n && n < 10);
+
+  ASSERT_MAYBE (8 == n);
+  ASSERT_MAYBE (9 == n);
+
+  return n;
+}
+
+char buf[64];
+
+int f1 (const char *s)
+{
+  int n = __builtin_snprintf (buf, 64, "%.*s%08x", 1, s, 1);
+
+  ASSERT (7 < n && n < 10);
+
+  ASSERT_MAYBE (8 == n);
+  ASSERT_MAYBE (9 == n);
+
+  return n;
+}
+
+int f2 (const char *s)
+{
+  int n = __builtin_snprintf (0, 0, "%.*s", 2, s);
+
+  ASSERT (0 <= n && n <= 2);
+
+  ASSERT_MAYBE (0 == n);
+  ASSERT_MAYBE (1 == n);
+  ASSERT_MAYBE (2 == n);
+
+  return n;
+}
+
+/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized"} }
+   { dg-final { scan-tree-dump-times "keep_call_on_line" 7 "optimized"} } */
index e19768e..3b57c0e 100644 (file)
@@ -93,10 +93,10 @@ void test_s_nonconst (const char *s, const wchar_t *ws, struct Arrays *a)
   T (1, "%s",   s);             /* { dg-warning "nul past the end" "sprintf transformed into strcpy" { xfail *-*-* } } */
   T (1, "%1s",  s);             /* { dg-warning "nul past the end" } */
   T (1, "%.0s", s);
-  T (1, "%.1s", s);             /* { dg-warning "writing a terminating nul" } */
+  T (1, "%.1s", s);             /* { dg-warning "may write a terminating nul" } */
 
   T (1, "%.0ls",  ws);
-  T (1, "%.1ls",  ws);          /* { dg-warning "writing a terminating nul" } */
+  T (1, "%.1ls",  ws);          /* { dg-warning "may write a terminating nul" } */
   T (1, "%ls",    ws);          /* { dg-warning "writing a terminating nul" } */
 
   /* Verify that the size of the array is used in lieu of its length.