This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug preprocessor/70518] New: Conditional compilation of #line directives
- From: "elyk03 at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sun, 03 Apr 2016 06:05:33 +0000
- Subject: [Bug preprocessor/70518] New: Conditional compilation of #line directives
- Auto-submitted: auto-generated
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];
^~