From 93860275f3ff2b42784479b360ddbd9da8afe794 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Sat, 9 Nov 2013 21:15:32 -0800 Subject: [PATCH] Fix deparsing of glob(my $x) and CORE::glob A git bisect run like this: $ ../perl.git/Porting/bisect.pl --start=v5.12.0 --end=v5.18.0 -e 'use B::Deparse; die if new B::Deparse->coderef2text(sub{glob my $x}) =~ /. But my local 5.14.4 installation still outputs glob(my $x), so I am not sure which commit is responsible. I suspect it changed multi- ple times. In any case, B::Deparse was expecting the argument to pp_glob always to be a string, which is certainly not guaranteed. This commit also causes CORE::glob to be deparsed correctly. glob is one of those oddities like require that gets only half-overridden by overrides. In this particular case the built-in pp_glob is still used, but takes a different code path depending on whether it was pre- fixed with CORE::. So, while glob is a strong keyword, it needs to be treated as a weak one for deparsing purposes. --- lib/B/Deparse-core.t | 15 +++++---------- lib/B/Deparse.pm | 15 ++++++++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/B/Deparse-core.t b/lib/B/Deparse-core.t index eaa2689..f839e88 100644 --- a/lib/B/Deparse-core.t +++ b/lib/B/Deparse-core.t @@ -36,7 +36,7 @@ BEGIN { use strict; use Test::More; -plan tests => 2063; +plan tests => 2071; use feature (sprintf(":%vd", $^V)); # to avoid relying on the feature # logic to add CORE:: @@ -62,8 +62,6 @@ sub testit { for my $lex (0, 1, 2) { if ($lex) { next if $keyword =~ /local|our|state|my/; - # XXX glob(my $x) incorrectly becomes - next if $keyword eq 'glob'; } my $vars = $lex == 1 ? 'my($a, $b, $c, $d, $e);' . "\n " : ""; @@ -225,13 +223,10 @@ testit exists => 'exists $h{\'foo\'};', 'exists $h{\'foo\'};'; testit exec => 'CORE::exec($foo $bar);'; -# glob($x) gets deparsed as glob("$x"). -# Whether this is correct, I don't know; but I didn't want -# to start messing with the whole glob/readline/<> mess - DAPM. -testit glob => 'glob;', 'glob("$_");'; -testit glob => 'CORE::glob;', 'glob("$_");'; -testit glob => 'glob $a;', 'glob("$a");'; -testit glob => 'CORE::glob $a;', 'glob("$a");'; +testit glob => 'glob;', 'glob($_);'; +testit glob => 'CORE::glob;', 'CORE::glob($_);'; +testit glob => 'glob $a;', 'glob($a);'; +testit glob => 'CORE::glob $a;', 'CORE::glob($a);'; testit grep => 'CORE::grep { $a } $b, $c', 'grep({$a;} $b, $c);'; diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 5ea01cb..3800171 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -1811,7 +1811,6 @@ my %feature_keywords = ( # keywords that are strong and also have a prototype # my %strong_proto_keywords = map { $_ => 1 } qw( - glob pos prototype scalar @@ -2810,13 +2809,19 @@ sub pp_syscall { listop(@_, "syscall") } sub pp_glob { my $self = shift; my($op, $cx) = @_; - my $text = $self->dq($op->first->sibling); # skip pushmark + my $kid = $op->first->sibling; # skip pushmark my $keyword = $op->flags & OPf_SPECIAL ? 'glob' : $self->keyword('glob'); - if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline - or $keyword =~ /^CORE::/ + my $text; + if ($keyword =~ /^CORE::/ + or $kid->name ne 'const' + or ($text = $self->dq($kid)) + =~ /^\$?(\w|::|\`)+$/ # could look like a readline or $text =~ /[<>]/) { - return "$keyword(" . single_delim('qq', '"', $text) . ')'; + $text = $self->deparse($kid); + return $cx >= 5 || $self->{'parens'} + ? "$keyword($text)" + : "$keyword $text"; } else { return '<' . $text . '>'; } -- 2.7.4