https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78969
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |aldyh at gcc dot gnu.org --- Comment #12 from Martin Sebor <msebor at gcc dot gnu.org> --- Thanks for the test case. Here's a slightly reduced version of it: $ cat pr78969.c && gcc -O2 -S -Wall pr78969.c void f (int, ...); char d[4]; void g (unsigned i) { if (i >= 1000 && i < 10000) __builtin_snprintf (d, 4, "%3d", i / 10); // bogus -Wformat-truncation else f (i / 10 % 10); } pr78969.c: In function ‘g’: pr78969.c:8:32: warning: ‘%3d’ directive output may be truncated writing between 3 and 9 bytes into a region of size 4 [-Wformat-truncation=] __builtin_snprintf (d, 4, "%3d", i / 10); // bogus -Wformat-truncation ^~~ pr78969.c:8:31: note: directive argument in the range [0, 429496729] __builtin_snprintf (d, 4, "%3d", i / 10); // bogus -Wformat-truncation ^~~~~ pr78969.c:8:5: note: ‘__builtin_snprintf’ output between 4 and 10 bytes into a destination of size 4 __builtin_snprintf (d, 4, "%3d", i / 10); // bogus -Wformat-truncation ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It does look like the false positive is due to the same underlying limitation (the range not being reflected accurately outside the VRP pass). GCC 7 doesn't warn but GCC 8 does. That's because in GCC 7 the result of the get_range_info() function is VR_VARYING for the argument while in GCC 8 it reports a VR_RANGE of [0, 429496729]. So ironically, the false positive is a side-effect of the improvement in GCC 8's range tracking. There is work underway to improve the accuracy of the range information even further that should reduce the rate of these kinds of false positives. That being said, a few comments: 1) The problem doesn't affect just -Wstringop-truncation but other warnings as well, including -Wformat-overflow. The latter warning, especially, has proven to be useful enough despite this limitation that removing either from -Wall doesn't seem a like good solution. 2) The philosophy behind -Wstringop-truncation is based on the assumption that snprintf() is being called because truncation is possible, and that most programs aren't prepared to handle it correctly. In the test case, since truncation isn't possible, calling snprintf() is unnecessary (and sprintf() would be sufficient -- though calling sprintf with a fixed-size buffer just big enough for the output would also cause a false positive). Otherwise, if truncation were possible, the expectation is that the caller should detect it by testing the return value from the function and taking some action (e.g., by aborting). Until the range improvements I mention above are made, I suggest to assume that snprintf can truncate and handle the truncation somehow. In comparison to the runtime cost of the snprintf call, the overhead of checking the return value and aborting is negligible.