eof had the same bug as tell. Here is the commit message from
8dc99089, which fixed tell:
----------------------------------------------------------------------
Stop tell($glob_copy) from clearing PL_last_in_gv
This bug is a side effect of rv2gv’s starting to return an incoercible
mortal copy of a coercible glob in 5.14:
$ perl5.12.4 -le 'open FH, "t/test.pl"; $fh=*FH; tell $fh; print tell'
0
$ perl5.14.0 -le 'open FH, "t/test.pl"; $fh=*FH; tell $fh; print tell'
-1
In the first case, tell without arguments is returning the position of
the filehandle.
In the second case, tell with an explicit argument that happens to
be a coercible glob (tell has an implicit rv2gv, so tell $fh is actu-
ally tell *$fh) sets PL_last_in_gv to a mortal copy thereof, which is
freed at the end of the statement, setting PL_last_in_gv to null. So
there is no ‘last used’ handle by the time we get to the tell without
arguments.
This commit adds a new rv2gv flag that tells it not to copy the glob.
By doing it unconditionally on the kidop, this allows tell(*$fh) to
work the same way.
Let’s hope nobody does tell(*{*$fh}), which will unset PL_last_in_gv
because the inner * returns a mortal copy.
This whole area is really icky. PL_last_in_gv should be refcounted,
but that would cause handles to leak out of scope, breaking programs
that rely on the auto-closing ‘feature’.
PERL_ARGS_ASSERT_CK_EOF;
if (o->op_flags & OPf_KIDS) {
+ OP *kid;
if (cLISTOPo->op_first->op_type == OP_STUB) {
OP * const newop
= newUNOP(o->op_type, OPf_SPECIAL, newGVOP(OP_GV, 0, PL_argvgv));
#endif
o = newop;
}
- return ck_fun(o);
+ o = ck_fun(o);
+ kid = cLISTOPo->op_first;
+ if (kid->op_type == OP_RV2GV)
+ kid->op_private |= OPpALLOW_FAKE;
}
return o;
}
require './test.pl';
}
-print "1..31\n";
+print "1..33\n";
$TST = 'TST';
tell *$fh;
$not = "not " x! (tell == 0);
print "${not}ok 31 - argless tell after tell *\$coercible\n";
+eof $fh;
+$not = "not " x! (tell == 0);
+print "${not}ok 32 - argless tell after eof \$coercible\n";
+eof *$fh;
+$not = "not " x! (tell == 0);
+print "${not}ok 33 - argless tell after eof *\$coercible\n";