From 9409dfc27d08f377e81741fdfb6f90d4ed657576 Mon Sep 17 00:00:00 2001 From: Richard Leach Date: Thu, 23 Apr 2026 20:10:28 +0000 Subject: [PATCH] pp_unstack - set PL_curcop for better condition line number accuracy Diagnostic messages triggered by the contents of a loop condition have tended to show inaccurate line numbers, as the COP in effect usually pertains to a statement inside the loop body. Sometimes deep inside the loop body. This long-standing example would warn about `Use of uninitialized value $c in numeric eq (==) at - line 10.`, when the correct location is line 5: ``` use warnings; my $c; my $d = 1; while ($c == 0 && $d) { # a # few # blank # lines undef $d; } ``` This commit tweaks `pp_unstack` to set `PL_curcop` to the last valid COP prior to loop entry, which is usually going to have a line number closer to where the loop condition exists in the source code. --- pp_hot.c | 5 +++++ t/lib/warnings/9uninit | 6 +++--- t/run/switches.t | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pp_hot.c b/pp_hot.c index 72243263de70..7dd315917aba 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -529,6 +529,11 @@ PP(pp_unstack) if (!(PL_op->op_flags & OPf_SPECIAL)) { assert(CxTYPE(cx) == CXt_BLOCK || CxTYPE_is_LOOP(cx)); CX_LEAVE_SCOPE(cx); + /* PL_curcop points somewhere inside this loop body. + * Unless it is reset, any warnings, errors, or caller() + * lookups inside the loop condition will display a + * misleading line number. */ + PL_curcop = cx->blk_oldcop; } return NORMAL; } diff --git a/t/lib/warnings/9uninit b/t/lib/warnings/9uninit index db888044f3dd..dff37bf47547 100644 --- a/t/lib/warnings/9uninit +++ b/t/lib/warnings/9uninit @@ -1464,7 +1464,7 @@ EXPECT Use of uninitialized value $undef in numeric eq (==) at - line 4. Use of uninitialized value $undef in numeric eq (==) at - line 5. ######## -# TODO long standing bug - conditions of while loops +# NAME conditions of while loops use warnings; my $c; @@ -1480,7 +1480,7 @@ EXPECT Use of uninitialized value $c in numeric eq (==) at - line 5. Use of uninitialized value $c in numeric eq (==) at - line 5. ######## -# TODO long standing bug - conditions of until loops +# NAME conditions of until loops use warnings; my $c; @@ -1496,7 +1496,7 @@ EXPECT Use of uninitialized value $c in numeric eq (==) at - line 5. Use of uninitialized value $c in numeric eq (==) at - line 5. ######## -# TODO long standing bug - conditions of for loops +# NAME conditions of for loops use warnings; my $c; diff --git a/t/run/switches.t b/t/run/switches.t index 7ba641a8157d..000c8cb98766 100644 --- a/t/run/switches.t +++ b/t/run/switches.t @@ -692,7 +692,7 @@ while (<>) { print "ok\n"; CODE $code =~ s/tmpinplace/$tmpinplace/; - fresh_perl_like($code, qr/^Cannot complete in-place edit of \Q$tmpinplace\E\/foo: .* - line 5, <> line \d+\./, { }, + fresh_perl_like($code, qr/^Cannot complete in-place edit of \Q$tmpinplace\E\/foo: .* - line 3, <> line \d+\./, { }, "chdir while in-place editing (no at-functions)"); }