This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug preprocessor/70518] New: Conditional compilation of #line directives


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];
                 ^~

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]