diff options
author | David Mitchell <davem@iabyn.com> | 2018-03-19 20:35:26 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2018-03-20 07:59:26 +0000 |
commit | bce0f2262f9f42124c415b34c7f34af0e4466ff7 (patch) | |
tree | 4df1ac21ab863add7d53bd24ea2f6f7089abc333 /lib | |
parent | 4fc9437af9c4c388b6902d9bd9e4b25a4a56ab31 (diff) | |
download | perl-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.pm | 13 |
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; |