I have isolated a case where Perl provides a very misleading line number in a warning message. I tested the below in Strawberry Perl 5.16.3.
use strict;
use warnings;
my $choice = 0;
while ($choice == 0){
#This is not numeric
$choice = '5,6,7';
if ($choice eq '-4'){
print "This isn't going to happen\n";
}
}
When you run this, you will get the warning message Argument "5,6,7" isn't numeric in numeric eq (==) at example.pl line 11
. But line 11 corresponds to the line if ($choice eq '-4'){
which cannot possibly cause this warning message because it does not contain a numeric comparison.
It seems what's actually happening is that Perl advances to the next comparison, while ($choice == 0){
, but the line counter used for the warning message does not advance.
What makes this particular case worse is that, since the "bad" comparison is the loop condition, it is actually far away from the provided line. In my (pre-simplification) script, it was hundreds of lines away from the provided line number.
Is this a bug or just an unfortunate limitation of the parser?
It would be expensive to store the location of each operator instance. As a compromise, Perl only tracks the location of statements. It does so by adding a location-setting opcode at the start of every statement. The if
statement is the last statement to be started before $choice == 0
is performed, so the warning is reported as coming from that line.
$ perl -MO=Concise,-exec a.pl
1 <0> enter
2 <;> nextstate(main 3 a.pl:4) v:*,&,{,x*,x&,x$,$
3 <$> const[IV 0] s
4 <0> padsv[$choice:3,12] sRM*/LVINTRO
5 <2> sassign vKS/2
6 <;> nextstate(main 4 a.pl:6) v:*,&,{,x*,x&,x$,$ <--- Location set to line 6
7 <{> enterloop(next->k last->p redo->8) v <--- Start of while loop
l <0> padsv[$choice:3,12] s <--- $choice == 0
m <$> const[IV 0] s
n <2> eq sK/2
o <|> and(other->8) vK/1
8 <;> nextstate(main 6 a.pl:9) v:*,&,x*,x&,x$,$
9 <$> const[PV "5,6,7"] s
a <0> padsv[$choice:3,12] sRM*
b <2> sassign vKS/2
c <;> nextstate(main 6 a.pl:11) v:*,&,x*,x&,x$,$ <--- Location set to line 11
d <0> padsv[$choice:3,12] s <--- Start of if statement
e <$> const[PV "-4"] s
f <2> seq sK/2
g <|> and(other->h) vK/1
h <0> pushmark s
i <$> const[PV "This isn't going to happen\n"] s
j <@> print vK
k <0> unstack v
goto l <--- Jump back to loop expr
p <2> leaveloop vKP/2
q <@> leave[1 ref] vKP/REFC
a.pl syntax OK
This is a known limitation. I don't know why they don't simply put a nextstate
op in the loop expression.
Apparently, starting with Perl 5.008, the interpreter began omitting an opcode that let the interpreter know the current line number.
Using the minimalist script:
while ($choice == 0) {
$choice = '5,6,7';
}
We get this output from Perl 5.6 and B::Concise
:
$ perl506 -MO=Concise badwarnline.pl
f <@> leave[t1] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 badwarnline.pl:1) v ->3
e <2> leaveloop vK/2 ->f
3 <{> enterloop(next->8 last->e redo->4) v ->a
- <1> null vK/1 ->e
d <|> and(other->4) vK/1 ->e
c <2> eq sK/2 ->d
- <1> ex-rv2sv sK/1 ->b
a <$> gvsv(*choice) s ->b
b <$> const(IV 0) s ->c
- <@> lineseq vKP ->-
4 <;> nextstate(main 1 badwarnline.pl:2) v ->5
7 <2> sassign vKS/2 ->8
5 <$> const(PV "5,6,7") s ->6
- <1> ex-rv2sv sKRM*/1 ->7
6 <$> gvsv(*choice) s ->7
8 <0> unstack v ->9
9 <;> nextstate(main 2 badwarnline.pl:1) v ->a
and this output from Perl v5.008:
$ perl508 -MO=Concise badwarnline.pl
e <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 badwarnline.pl:1) v ->3
d <2> leaveloop vK/2 ->e
3 <{> enterloop(next->8 last->d redo->4) v ->9
- <1> null vK/1 ->d
c <|> and(other->4) vK/1 ->d
b <2> eq sK/2 ->c
- <1> ex-rv2sv sK/1 ->a
9 <#> gvsv[*choice] s ->a
a <$> const[IV 0] s ->b
- <@> lineseq vKP ->-
4 <;> nextstate(main 1 badwarnline.pl:2) v ->5
7 <2> sassign vKS/2 ->8
5 <$> const[PV "5,6,7"] s ->6
- <1> ex-rv2sv sKRM*/1 ->7
6 <#> gvsv[*choice] s ->7
8 <0> unstack v ->9
The main difference between these outputs is the last line produced by 5.006:
9 <;> nextstate(main 2 badwarnline.pl:1) v ->a
which is omitted in the 5.008 output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With