commit 41ffdc2a3fa3b9492c0a8d82497602187411babe
parent 90d731b094126c3440a1f938701db2ba86fdc26d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 1 May 2026 17:32:32 -0700
cc/pp: builtin macros emit at original loc to avoid double #line shift
%pp-expand-builtin baked the post-#line file/line into the *loc* of
the synthesized __FILE__/__LINE__/__DATE__/etc. tokens, then the
downstream %pp-relocate (which the dispatcher applies to every emitted
non-IDENT token) added the same line-delta a second time. After
'#line 100', __LINE__ on the next physical line of source produced a
token whose value was 100 (correct) but whose loc-line was 197
(100 + 97 = original-line + 2*delta).
Fix: emit the synthesized token at the IDENT's original loc and let
%pp-relocate apply cur-file / line-delta exactly once. The VALUE for
__FILE__ / __LINE__ already incorporates the post-#line mapping, since
file/line are computed from cur-file and line-delta before being
embedded as the token's value.
Test: tests/cc-pp/53-line-directive-effect.c uses #line 100 "x.c"
and asserts that __LINE__ on the following line reports loc 100 in
"x.c" (was reporting loc 197).
Diffstat:
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/cc/cc.scm b/cc/cc.scm
@@ -1752,19 +1752,22 @@
(bv= name %pp-bv-STDC-VERSION) (bv= name %pp-bv-STDC-HOSTED)))
(define (%pp-expand-builtin name loc state)
+ ;; Emit the token at the ORIGINAL loc; %pp-relocate downstream will
+ ;; apply pps-cur-file / pps-line-delta. Doing the rewrite here too
+ ;; (then letting relocate re-apply it) double-shifts __LINE__'s loc.
+ ;; The VALUE of __LINE__ / __FILE__ already reflects the post-#line
+ ;; mapping because we compute `file`/`line` from cur-file/line-delta.
(let* ((file (or (pps-cur-file state) (loc-file loc)))
- (line (+ (loc-line loc) (pps-line-delta state)))
- (col (loc-col loc))
- (here (%loc file line col)))
+ (line (+ (loc-line loc) (pps-line-delta state))))
(cond
- ((bv= name %pp-bv-FILE) (list (%tok 'STR file here '())))
- ((bv= name %pp-bv-LINE) (list (%tok 'INT line here '())))
- ((bv= name %pp-bv-STDC) (list (%tok 'INT 1 here '())))
- ((bv= name %pp-bv-LISPCC) (list (%tok 'INT 1 here '())))
- ((bv= name %pp-bv-DATE) (list (%tok 'STR %pp-bv-DATE-VALUE here '())))
- ((bv= name %pp-bv-TIME) (list (%tok 'STR %pp-bv-TIME-VALUE here '())))
- ((bv= name %pp-bv-STDC-VERSION) (list (%tok 'INT 199901 here '())))
- ((bv= name %pp-bv-STDC-HOSTED) (list (%tok 'INT 1 here '())))
+ ((bv= name %pp-bv-FILE) (list (%tok 'STR file loc '())))
+ ((bv= name %pp-bv-LINE) (list (%tok 'INT line loc '())))
+ ((bv= name %pp-bv-STDC) (list (%tok 'INT 1 loc '())))
+ ((bv= name %pp-bv-LISPCC) (list (%tok 'INT 1 loc '())))
+ ((bv= name %pp-bv-DATE) (list (%tok 'STR %pp-bv-DATE-VALUE loc '())))
+ ((bv= name %pp-bv-TIME) (list (%tok 'STR %pp-bv-TIME-VALUE loc '())))
+ ((bv= name %pp-bv-STDC-VERSION) (list (%tok 'INT 199901 loc '())))
+ ((bv= name %pp-bv-STDC-HOSTED) (list (%tok 'INT 1 loc '())))
(else (die loc "internal: not a builtin" name)))))
;; --- buf-list: simple reversed-list buffer of toks ---
diff --git a/tests/cc-pp/53-line-directive-effect.c b/tests/cc-pp/53-line-directive-effect.c
@@ -0,0 +1,4 @@
+__LINE__
+#line 100 "x.c"
+__LINE__
+__FILE__
diff --git a/tests/cc-pp/53-line-directive-effect.expected-toks b/tests/cc-pp/53-line-directive-effect.expected-toks
@@ -0,0 +1,4 @@
+(INT 1 "53-line-directive-effect.c" 1 1)
+(INT 100 "x.c" 100 1)
+(STR "x.c" "x.c" 101 1)
+(EOF #f "53-line-directive-effect.c" 5 1)