https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83448
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Cleaned up testcase for testsuite: char *a; int b; void foo () { for (;;) { if (b < 0) foo (); __builtin_snprintf (a, b, "%*s", b, ""); } } The check certainly doesn't match the comment, if *dir.beg != '%', that doesn't mean there were no formatting directives and only if there weren't any % characters the length of the destination buffer has any correspondence to the location in the format string (and even then, what about \n, \t, \123 and the like, does the care handling code handle those?). So, it makes sense for: void foo (char *a) { __builtin_snprintf (a, 5, "abcdef"); } Here: pr83448-2.c: In function ‘foo’: pr83448-2.c:4:35: warning: ‘abcdef’ directive output truncated writing 6 bytes into a region of size 5 [-Wformat-truncation=] __builtin_snprintf (a, 5, "abcdef"); ~~~~~^ is nicer than: pr83448-2.c: In function ‘foo’: pr83448-2.c:4:30: warning: ‘abcdef’ directive output truncated writing 6 bytes into a region of size 5 [-Wformat-truncation=] __builtin_snprintf (a, 5, "abcdef"); ^~~~~~ that we'd emit without those hunks discussed here. So IMHO instead of removing those we should guard them properly. void bar (char *a) { __builtin_snprintf (a, 7, "abc\n\123 ef"); } also puts caret below f, so it seems \n and \123 is handled right.