https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70518
Bug ID: 70518 Summary: Conditional compilation of #line directives Product: gcc Version: 4.8.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: preprocessor Assignee: unassigned at gcc dot gnu.org Reporter: elyk03 at gmail dot com Target Milestone: --- Created attachment 38167 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38167&action=edit template file I am generating C code based on a template file. The result has #line directives that switch between the template and the generated code. If any of those #line directives appear within a disabled #if-block, then they are currently being skipped. This leads to weird behavior and misleading error messages. Let me explain my setup. (It's actually from an old fork of Bison.) The template file consists of blocks of text delimited by "$". These blocks are inserted into the generated code, with #line directives before and after. Block 1 contains an #if. Block 2 contains the matching #endif, followed by something that depends on the line number. I've added two examples, one that causes a compile error (for the file:line in the error message), and one that uses __FILE__ and __LINE__. Block 3 is extra padding. Here is main.c (generated) with the first two blocks inserted from the template, and the #if disabled: #include <stdio.h> #define FOO 0 int main(int argc, char *argv[]) { #line 2 "template.c" /* start block 1 */ #if FOO #line 8 "main.c" /* end block 1 */ int foo; int bar; #line 4 "template.c" /* start block 2 */ #endif int oops[-1]; printf("%s:%d\n", __FILE__, __LINE__); #line 15 "main.c" /* end block 2 */ return 0; } Because the #if is disabled, it is interpreting the location of "oops" to be template.c:8 (from "start block 1" plus 6 lines) instead of its actual location at template.c:5 (equal to "start block 2" plus 1 line) And consistent with that, __FILE__ and __LINE__ on the next line are template.c:9 instead of template.c:6. Should #line be processed unconditionally? I know the preprocessor has to keep track of nested #if blocks so that it can find the matching #endif when the block is disabled. This seems like a corner case that I don't know if the C standard ever considers. If so, it may simplify the next part. The bug: Misleading error messages. It opens template.c and prints line 8 from it (assuming this file exists and has at least 8 lines). It's not the offending line; it could be any text: template.c: In function ‘main’: template.c:8:6: error: size of array ‘oops’ is negative /* template.c line 8 */ ^ Also note the "In function ‘main’" message is using template.c instead of the actual file that main appears in (main.c) and that __FILE__ is set to at the start of its definition. Somehow clang prints out the right offending statement but keeps the "template.c:8" text: template.c:8:11: error: 'oops' declared as an array with a negative size int oops[-1]; ^~