Description of problem: gcc produces an incorrect warning message $ gcc -v Using built-in specs. Target: s390x-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,java,f95 --enable-java-awt=gtk --host=s390x-redhat-linux Thread model: posix gcc version 4.0.0 20050320 (Red Hat 4.0.0-0.35) $ cat atest.c #include <stdio.h> int main() { long long len = 1; fprintf(stderr, "len = %d\n", len); return 0; } $ gcc -Wall atest.c atest.c: In function 'main': atest.c:7: warning: format '%d' expects type 'int', but argument 3 has type 'long long int' -- that's the expected result, but watch this: $ gcc -Wall -Wp,-D_FORTIFY_SOURCE=2 -O atest.c atest.c: In function 'main': atest.c:7: warning: format '%d' expects type 'int', but argument 4 has type 'long long int' Why is the argument number now off by one? Version-Release number of selected component (if applicable): gcc-4.0.0-0.35 How reproducible: 100% on this arch, have not tried others Steps to Reproduce: 1. 2. 3. Actual results: Expected results: Additional info: In itself this is not much more than cosmetic, but I wonder if it is a symptom of a bug that could have more serious consequences.
This is a consequence of __fprintf_chk being actually called rather than fprintf. And __fprintf_chk has one additional argument, before the format string. As *printf are stdarg functions, the extra argument simply must go before the ... arguments.
I don't think I believe that explanation, because the bogus message depends on whether -O is present.
Of course it depends on -O*, because -D_FORTIFY_SOURCE={1,2} is only in affect with -O1 and higher. The way it is implemented, it can't work for non-optimized code.