Hi! Even when we know the exact return value of a snprintf call with 0 length (i.e. one that doesn't write anything into a buffer), there can be %n directives in the format string that have side-effects that shouldn't be discarded.
The following patch avoids the replacement of the snprintf call with just the constant if there is any %n directive. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-01-02 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/78965 * gimple-ssa-sprintf.c (pass_sprintf_length::compute_format_length): Change first argument from const call_info & to call_info &. For %n set info.nowrite to false. * gcc.dg/pr78965.c: New test. --- gcc/gimple-ssa-sprintf.c.jj 2017-01-01 12:45:35.000000000 +0100 +++ gcc/gimple-ssa-sprintf.c 2017-01-02 12:09:29.902945255 +0100 @@ -131,7 +131,7 @@ public: void handle_gimple_call (gimple_stmt_iterator*); struct call_info; - bool compute_format_length (const call_info &, format_result *); + bool compute_format_length (call_info &, format_result *); }; bool @@ -2357,7 +2357,7 @@ add_bytes (const pass_sprintf_length::ca that caused the processing to be terminated early). */ bool -pass_sprintf_length::compute_format_length (const call_info &info, +pass_sprintf_length::compute_format_length (call_info &info, format_result *res) { /* The variadic argument counter. */ @@ -2624,6 +2624,9 @@ pass_sprintf_length::compute_format_leng return false; case 'n': + /* %n has side-effects even when nothing is actually printed to + any buffer. */ + info.nowrite = false; break; case 'c': --- gcc/testsuite/gcc.dg/pr78965.c.jj 2017-01-02 12:12:15.959803429 +0100 +++ gcc/testsuite/gcc.dg/pr78965.c 2017-01-02 12:11:06.000000000 +0100 @@ -0,0 +1,14 @@ +/* PR tree-optimization/78965 */ +/* { dg-do run { target c99_runtime } } */ +/* { dg-options "-O2" } */ +/* { dg-add-options c99_runtime } */ + +int +main () +{ + int a = 5, b = 6; + int c = __builtin_snprintf (0, 0, "a%nb%nc", &a, &b); + if (a + b + c != 6) + __builtin_abort (); + return 0; +} Jakub