summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2018-03-19 20:35:26 +0000
committerDavid Mitchell <davem@iabyn.com>2018-03-20 07:59:26 +0000
commitbce0f2262f9f42124c415b34c7f34af0e4466ff7 (patch)
tree4df1ac21ab863add7d53bd24ea2f6f7089abc333 /lib
parent4fc9437af9c4c388b6902d9bd9e4b25a4a56ab31 (diff)
downloadperl-bce0f2262f9f42124c415b34c7f34af0e4466ff7.tar.gz
Deparse -l: set correct line num at end of sub
A sub declaration like sub f { ...} will be deparsed under -l as #line 1 "foo" sub f { #line 1 "foo" .... } which means that the closing '}' of the sub is incorrectly seen as being on the next line. This matters when a glob is created based on a sub being compiled: the glob's gp_line field is set to the line containing the '}'. This was causing some tests in ext/B/t/xref.t to fail under ./TEST -deparse This commit causes an extra #line directive to be emitted: #line 1 "foo" sub f { #line 1 "foo" .... #line 1 "foo" <=== NEW } Whether xref.t failed depended on another factor. The optimisation which created the GV for a just-compiled sub as an RV to a CV rather than a GV to CV, causes the later-vifified GV (upgraded from an RV) to instead have a gp_line corresponding to the first cop in the sub's body. Arguably this difference (gp_line being set to the line number of first line of the sub rather than the last line) is a bug, but it's not obvious how to fix it, and I don't address it here. However, the optimisation originally only applied to GVs in the main stash; it was later extended to all stashes but then reverted again, in the sequence of commits v5.27.4-66-g6881372 v5.27.4-127-g6eed25e v5.27.5-321-gd964025 v5.27.8-149-g1e2cfe1 which caused xref.t to pass, then fail again.
Diffstat (limited to 'lib')
-rw-r--r--lib/B/Deparse.pm13
1 files changed, 12 insertions, 1 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index d3ab507be2..8fedf81c15 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -1355,7 +1355,18 @@ Carp::confess("SPECIAL in deparse_sub") if $cv->isa("B::SPECIAL");
else {
$body = $self->deparse($root->first, 0);
}
- $body = "{\n\t$body\n\b}";
+
+ my $l = '';
+ if ($self->{'linenums'}) {
+ # a glob's gp_line is set from the line containing a
+ # sub's closing '}' if the CV is the first use of the GV.
+ # So make sure the linenum is set correctly for '}'
+ my $gv = $cv->GV;
+ my $line = $gv->LINE;
+ my $file = $gv->FILE;
+ $l = "\f#line $line \"$file\"\n";
+ }
+ $body = "{\n\t$body\n$l\b}";
}
else {
my $sv = $cv->const_sv;