https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85949
--- Comment #7 from Martin Sebor <msebor at gcc dot gnu.org> --- There are two kinds of warnings for printf-type functions: -Wformat implemented in the front-ends, and -Wformat-overflow/truncation implemented in the middle-end. The former detects mostly just type-based errors and doesn't depend on optimization, while the latter detects errors that depend on control and data flow analyses exposed by optimization (buffer overflow, truncation, null pointers, and some uses of unterminated character arrays as %s arguments). Some bugs that are in the intersection of the two are not detected by either. The test case in attachment 45435 is of the latter kind: it depends on data flow analysis. With optimization enabled it can detect the bug in the second call to str_fmt(), but only if the call uses the arguments (or is not known not to use it). The extra argument in the first call to str_fmt() is not detected -- it's in the third class of problems: the front-end doesn't see the value of the format string and the middle-end doesn't check for extra arguments. Ideally, there would be just one implementation of all format warnings that did all kinds of checking, but merging the two existing implementations would be a lot of effort. Short of that, we could look into moving (or duplicating) some of the same front-end checks into the middle-end in cases where it's important. The trick is to avoid issuing duplicate warnings between the two sets of checks. The caveat with that, though, is that detecting the problems with non-constants only works with optimization. $ cat t.c && gcc -O2 -S -Wall t.c void str_fmt(const char * const format, ...) __attribute__ ((format (printf,1,2))); int main() { const int i = 0; const char * str = "abc"; const char * str2 = "%s"; str_fmt(str, i); str_fmt(str2, i); } t.c: In function ‘main’: t.c:11:5: warning: ‘%s’ directive argument is null [-Wformat-overflow=] 11 | str_fmt(str2, i); | ^~~~~~~~~~~~~~~~