PR middle-end/79496 - call to snprintf with zero size eliminated with -Wformat-trunca...
authorMartin Sebor <msebor@redhat.com>
Tue, 14 Feb 2017 04:38:54 +0000 (04:38 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 14 Feb 2017 04:38:54 +0000 (21:38 -0700)
gcc/ChangeLog:

PR middle-end/79496
* gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call): Avoid
clearing info.nowrite flag when snprintf size argument is a range.

gcc/testsuite/ChangeLog:

PR middle-end/79496
* gcc.dg/tree-ssa/builtin-snprintf-2.c: New test.

From-SVN: r245415

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

index b6be5d8..2561d53 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-13  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/79496
+       * gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call): Avoid
+       clearing info.nowrite flag when snprintf size argument is a range.
+
 2017-02-13  Jakub Jelinek  <jakub@redhat.com>
 
        * cprop.c (cprop_jump): Add missing space in string literal.
index e6cc31d..b2db8b8 100644 (file)
@@ -3443,6 +3443,10 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
 
   info.format = gimple_call_arg (info.callstmt, idx_format);
 
+  /* True when the destination size is constant as opposed to the lower
+     or upper bound of a range.  */
+  bool dstsize_cst_p = true;
+
   if (idx_dstsize == HOST_WIDE_INT_M1U)
     {
       /* For non-bounded functions like sprintf, determine the size
@@ -3483,8 +3487,8 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
       else if (TREE_CODE (size) == SSA_NAME)
        {
          /* Try to determine the range of values of the argument
-            and use the greater of the two at -Wformat-level 1 and
-            the smaller of them at level 2.  */
+            and use the greater of the two at level 1 and the smaller
+            of them at level 2.  */
          wide_int min, max;
          enum value_range_type range_type
            = get_range_info (size, &min, &max);
@@ -3495,6 +3499,11 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
                   ? wi::fits_uhwi_p (max) ? max.to_uhwi () : max.to_shwi ()
                   : wi::fits_uhwi_p (min) ? min.to_uhwi () : min.to_shwi ());
            }
+
+         /* The destination size is not constant.  If the function is
+            bounded (e.g., snprintf) a lower bound of zero doesn't
+            necessarily imply it can be eliminated.  */
+         dstsize_cst_p = false;
        }
     }
 
@@ -3511,7 +3520,7 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
         without actually producing any.  Pretend the size is
         unlimited in this case.  */
       info.objsize = HOST_WIDE_INT_MAX;
-      info.nowrite = true;
+      info.nowrite = dstsize_cst_p;
     }
   else
     {
index c92cff7..a3f66e7 100644 (file)
@@ -1,3 +1,8 @@
+2017-02-13  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/79496
+       * gcc.dg/tree-ssa/builtin-snprintf-2.c: New test.
+
 2017-02-13  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/79341
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c
new file mode 100644 (file)
index 0000000..a192aee
--- /dev/null
@@ -0,0 +1,24 @@
+/* PR middle-end/79496 - call to snprintf with non-zero size eliminated
+   with -Wformat-truncation=2
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wformat-truncation=2 -fprintf-return-value -fdump-tree-optimized" } */
+
+char d[2];
+
+int test_cst (unsigned n)
+{
+  if (1 < n)
+    n = 0;
+
+  return __builtin_snprintf (d, n, "%d", 1);
+}
+
+int test_var (char *d, unsigned n)
+{
+  if (2 < n)
+    n = 0;
+
+  return __builtin_snprintf (d, n, "%i", 1);
+}
+
+/* { dg-final { scan-tree-dump-times "snprintf" 2 "optimized"} } */