https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106039
Bug ID: 106039 Summary: Inconsistent error reporting for printf() when format string is a macro Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: jonathan.leffler at gmail dot com Target Milestone: --- Created attachment 53176 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53176&action=edit Preprocessed output The problem is inconsistent error (warning) reporting from GCC (home-built versions 8.2.0, 9.3.0, 10.3.0, 11.2.0, 12.1.0 tested on RHEL 7.4) with respect to the location of the problem. (The test case is reduced from 5600 lines and 43 headers to 26 lines with two headers. The code is thoroughly anonymized.) There is no doubt that the errors reported are correct on a 64-bit system; the problem is in the way that the location of the error is reported. The errors reported by GCC 12.1.0 (errors because of -Werror) are shown below. Other versions produce essentially the same output, though the error formatting in 8.2.0 is somewhat different. The first error correctly lists the line causing the problem (line 18) as expected and desired. The other errors do not list the line causing the problem properly. The problem is surprisingly sensitive to the format string defined by the macro and the arguments provided to the printf() call. Some of the variations which 'fix' the error reporting are mentioned in the comments in the source. Reordering the printf() statements doesn't alter which printf() statements have the inconsistent error reporting. If the format string is placed directly in the printf() statement, the line is reported correctly. Neither the optimization level (-O) nor the debugging options (-g) seem to alter the behaviour. Using -Wall enables the relevant option; using -Werror ensures that rerunning 'make' attempts to rebuild the object file. The standard specified does not seem to alter the behaviour (in either -std=cXX or -std=gnuXX formats). Adding the -save-temps option to the compilation command line (to generate the .i file as requested in the 'Reporting Bugs' page) completely alters the error messages generated, giving the correct line numbers but odd-ball highlighting of what's wrong. ---- $ gcc -std=c99 -Werror -Wall -c gcc-bug.c gcc-bug.c: In function ‘print_lock’: gcc-bug.c:4:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long int’ [-Werror=format=] 4 | #define PRT_BR_HDR "%-16x\n" | ^~~~~~~~~ gcc-bug.c:18:12: note: in expansion of macro ‘PRT_BR_HDR’ 18 | printf(PRT_BR_HDR, (intptr_t) val1); | ^~~~~~~~~~ gcc-bug.c:4:28: note: format string is defined here 4 | #define PRT_BR_HDR "%-16x\n" | ~~~~^ | | | unsigned int | %-16lx gcc-bug.c:5:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘long int’ [-Werror=format=] 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:5:23: note: in definition of macro ‘PRT_BR_LN1’ 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:5:34: note: format string is defined here 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ~~~~^ | | | unsigned int | %-16lx gcc-bug.c:5:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 4 has type ‘long int’ [-Werror=format=] 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:5:23: note: in definition of macro ‘PRT_BR_LN1’ 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:5:40: note: format string is defined here 5 | #define PRT_BR_LN1 "%-21s %-16x %-16x %-18s %-18s\n" | ~~~~^ | | | unsigned int | %-16lx gcc-bug.c:6:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 4 has type ‘long int’ [-Werror=format=] 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:6:23: note: in definition of macro ‘PRT_BR_LN2’ 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:6:39: note: format string is defined here 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ~~~~^ | | | unsigned int | %-16lx gcc-bug.c:6:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 5 has type ‘long int’ [-Werror=format=] 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:6:23: note: in definition of macro ‘PRT_BR_LN2’ 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:6:45: note: format string is defined here 6 | #define PRT_BR_LN2 "%-12s %-8s %-16x %-16x %-18s %-18s\n" | ~~~~^ | | | unsigned int | %-16lx gcc-bug.c:7:23: error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 5 has type ‘long int’ [-Werror=format=] 7 | #define PRT_BR_LN3 "%-12s %-8s %-16s %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:7:23: note: in definition of macro ‘PRT_BR_LN3’ 7 | #define PRT_BR_LN3 "%-12s %-8s %-16s %-16x %-18s %-18s\n" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcc-bug.c:7:45: note: format string is defined here 7 | #define PRT_BR_LN3 "%-12s %-8s %-16s %-16x %-18s %-18s\n" | ~~~~^ | | | unsigned int | %-16lx cc1: all warnings being treated as errors $