https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86274
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P3 |P2 Target Milestone|--- |7.4 --- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> --- So after gimplification I see __s = __builtin_alloca (__n); __builtin_va_start (&__args, 0); __len = __convf (__s, __n, __fmt, &__args); __builtin_va_end (&__args); std::allocator<char>::allocator (&D.109301); try { try { _1 = (sizetype) __len; _2 = __s + _1; std::__cxx11::basic_string<char>::basic_string<char*> (<retval>, __s, _2, &D.109301); return <retval>; } finally { std::allocator<char>::~allocator (&D.109301); } which after SSA rewrite looks like std::__cxx11::basic_string<char>::basic_string<char*> (_16(D), __s_7, _2, &D.109301); So we're rewriting <retval> into SSA which is expected, <retval> is DECL_BY_REFERENCE. So that is a red herring. I suppose the new printf code simply doesn't handle default-defs that come in as DECL_BY_REFERENCE RESULT_DECL. Note what the pass causes is simply treating _3 = vsnprintf (__s_2, 328, "%f", &__args); as not returning zero and thus eliding a == 0 check. For some reason it says _3 is [8, 322] though but obviously 'NaN' prints as 3 characters only... So, martin? Reduced testcase: volatile double x; int main() { char *s = __builtin_alloca (220); x = __builtin_nan("nan"); if (__builtin_snprintf (s, 220, "%f", x) != 3) __builtin_abort (); return 0; }