Make -l always treat non-bareword arguments as file names
authorFather Chrysostomos <sprout@cpan.org>
Sun, 18 Sep 2011 03:47:26 +0000 (20:47 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 18 Sep 2011 03:47:26 +0000 (20:47 -0700)
Here is some suspicious code in Perl_my_lstat_flags:

     if (SvROK(sv) && isGV_with_GP(SvRV(sv)) && ckWARN(WARN_IO)) {
  Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
  GvENAME((const GV *)SvRV(sv)));
  return (PL_laststatval = -1);
     }

The behaviour differs depending on whether warnings are enabled.

That -1 turns into undef in pp_ftlink.  So we get an undef return
value with warnings on, but a file test on a file name otherwise.

In 5.6.2, -l $foo always treated $foo as a file name.

In 5.8+, if it is a reference (ignoring magic) and the reference
points to a typeglob (ignoring magic) and io warnings are on, it warns
and returns undef.

So the only time that undef return is reached is when a warning has
been emitted, so it’s code that will likely be corrected before it
goes into production.  Hence I think it unlikely that anyone could be
relying on the behaviour of -l \*foo (under warnings).

So this commit restores the 5.6 behaviour for that case.

doio.c
pod/perldelta.pod
t/lib/warnings/doio
t/op/filetest.t

diff --git a/doio.c b/doio.c
index f03db27..e6e9016 100644 (file)
--- a/doio.c
+++ b/doio.c
@@ -1352,11 +1352,6 @@ Perl_my_lstat_flags(pTHX_ const U32 flags)
     PL_statgv = NULL;
     sv = POPs;
     PUTBACK;
-    if (SvROK(sv) && isGV_with_GP(SvRV(sv)) && ckWARN(WARN_IO)) {
-       Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
-               GvENAME((const GV *)SvRV(sv)));
-       return (PL_laststatval = -1);
-    }
     file = SvPV_flags_const_nolen(sv, flags);
     sv_setpv(PL_statname,file);
     PL_laststatval = PerlLIO_lstat(file,&PL_statcache);
index 020965b..178738a 100644 (file)
@@ -846,6 +846,15 @@ work previously; now it does.  It is only permitted when the rightmost
 filetest op has the special "_" handle for its argument and the most
 recent C<stat>/C<lstat> call was an C<lstat>.
 
+=item *
+
+In Perl 5.6, C<-l> followed by anything other than a bareword would treat
+its argument as a file name.  That was changed in 5.8 for glob references
+(C<\*foo>), but not for globs themselves (C<*foo>).  Glob references
+started being treated as file handles, but only if warnings were turned on.
+In other words, it was simply buggy and inconsistent.  Now the 5.6
+behaviour has been restored.
+
 =back
 
 =head1 Known Problems
index 815e8a2..8f6e558 100644 (file)
@@ -159,16 +159,10 @@ Unsuccessful stat on filename containing newline at - line 4.
 # doio.c [Perl_my_stat]
 use warnings 'io';
 -l STDIN;
--l $fh;
-open $fh, $0 or die "# $!";
--l $fh;
 no warnings 'io';
 -l STDIN;
--l $fh;
-close $fh;
 EXPECT
 Use of -l on filehandle STDIN at - line 3.
-Use of -l on filehandle $fh at - line 6.
 ########
 # doio.c [Perl_do_aexec5]
 use warnings 'io' ;
index 3b09c2b..c710305 100644 (file)
@@ -10,7 +10,7 @@ BEGIN {
 }
 
 use Config;
-plan(tests => 33 + 27*14);
+plan(tests => 34 + 27*14);
 
 ok( -d 'op' );
 ok( -f 'TEST' );
@@ -110,6 +110,14 @@ SKIP: {
  `ln -s TEST 1`;
  ok ! -l -e _, 'stacked -l uses previous stat, not previous retval';
  unlink 1;
+
+ # Since we already have our skip block set up, we might as well put this
+ # test here, too:
+ # -l always treats a non-bareword argument as a file name
+ system qw "ln -s TEST", \*foo;
+ local $^W = 1;
+ ok -l \*foo, '-l \*foo is a file name';
+ unlink \*foo;
 }
 
 # test that _ is a bareword after filetest operators