diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/gimple-ssa-sprintf.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-2.c | 24 |
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"} } */ |