'#line directive in #ifdef block
How is the C processor/compiler supposed to handle code like this:
/*1:*/
#line 3 "line.w"
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("Before #ifdef: line %d of %s\n",__LINE__,__FILE__);
#ifdef STAT
printf("Inside #ifdef before section: line %d of %s\n",__LINE__,__FILE__);
/*2:*/
#line 19 "line.w"
printf("Inside section: line %d of %s\n",__LINE__,__FILE__);
/*:2*/
#line 12 "line.w"
printf("Inside #ifdef after section: line %d of %s\n",__LINE__,__FILE__);
#endif
printf("After #ifdef: line %d of %s\n",__LINE__,__FILE__);
return EXIT_SUCCESS;
}
/*:1*/
C file line.c was created from CWEB file line.w by ctangle. Note the two #line directives inside the #ifdef ... #endif block.
When I run gcc -E line.c -o line-noSTAT.i and gcc -E -DSTAT line.c -o line-STAT.i, the two expanded *.i files differ in their output in the final printf after the #endif:
4d3
< # 31 "<command-line>"
6c5
< # 32 "<command-line>" 2
---
> # 1 "<command-line>" 2
1827,1828c1826,1835
< # 22 "line.w"
< printf("After #ifdef: line %d of %s\n",22,"line.w");
---
>
> printf("Inside #ifdef before section: line %d of %s\n",11,"line.w");
> # 19 "line.w"
>
> printf("Inside section: line %d of %s\n",20,"line.w");
> # 12 "line.w"
>
> printf("Inside #ifdef after section: line %d of %s\n",13,"line.w");
>
> printf("After #ifdef: line %d of %s\n",15,"line.w");
1830c1837
< # 23 "line.w" 3 4
---
> # 16 "line.w" 3 4
1832c1839
< # 23 "line.w"
---
> # 16 "line.w"
and the compiled program deviates, too:
$ gcc line.c
$ ./a.out
Before #ifdef: line 9 of line.w
After #ifdef: line 22 of line.w
$ gcc -DSTAT line.c
$ ./a.out
Before #ifdef: line 9 of line.w
Inside #ifdef before section: line 11 of line.w
Inside section: line 20 of line.w
Inside #ifdef after section: line 13 of line.w
After #ifdef: line 15 of line.w
Note the significant difference in the After #ifdef output.
AFAIKS, the incorrect After #ifdef: line 22 of line.w comes from the fact that the compiler/preprocessor picks the twenty-second line from line.c, not the fifteenth line from line.w.
This MWE was created with
$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
but I have been informed that the MS Visual Studio debugger also has problems with similar (production) code. Also Apple clang version 13.0.0 (clang-1300.0.29.30) produces these differing outcomes.
Shouldn't all code between #ifdef STAT and #endif be eliminated when STAT is not defined?
Solution 1:[1]
The C preprocessor – i.e., any variant, hence the consistent behaviour across systems – in fact eliminates the two #line statements in the #ifdef block, if STAT is undefined.
Starting from the first #line 3 "line.w" it continues through line.c, skips all of the #ifdef block, and catches the final printf in the twenty-second line of the C source file, which had been reset to "line.w" at the very beginning.
Duh, this appears to be a deficiency in CWEB's ctangle, which should add a correct #line statement after the #endif.
An intermediate manual way to keep the line numbers in sync is:
- Add
#line __LINE__after#endifin the CWEB codeline.w - Replace the concrete line number with
perl -pi -e "s/#line __LINE__/#line $./" line.w - Convert CWEB to C with
ctangle line - Compile C code with/out
-DSTAT
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
