aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/gimple-ssa-sprintf.c15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c24
4 files changed, 47 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b6be5d8..2561d53 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index e6cc31d..b2db8b8 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -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
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c92cff7..a3f66e7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..a192aee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c
@@ -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"} } */