diff options
author | Zefram <zefram@fysh.org> | 2017-11-16 11:01:34 +0000 |
---|---|---|
committer | Zefram <zefram@fysh.org> | 2017-11-16 11:09:39 +0000 |
commit | dd6661605fe0a54c602f2e55f875acfdcd330b79 (patch) | |
tree | 3e52a1e0129ee815b200f1fc2907a6569c2e80bf /lib | |
parent | 647672aaa908fc8ab61664986252c70fb04f3498 (diff) | |
download | perl-dd6661605fe0a54c602f2e55f875acfdcd330b79.tar.gz |
deparse trailing-colon barewords carefully
A bareword ending in "::" has one "::" suffix stripped upon parsing,
so when deparsing a glob name ending in "::" as a bareword it needs
another "::" added. But this only applies to barewords, not to glob
names that follow sigils, so the deparser needs to distinguish between
contexts for glob names in some places where it previously did not.
Fixes [perl #113716].
This change supersedes the recent change about deparsing glob names in
the CORE stash. Those glob names are now handled by suffixing "::",
and this suffix is only added in bareword contexts, making the handling
of the two unusual cases identical.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/B/Deparse.pm | 18 | ||||
-rw-r--r-- | lib/B/Deparse.t | 48 |
2 files changed, 59 insertions, 7 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 00e31d31d9..cc439ae182 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -1778,7 +1778,6 @@ sub gv_name { { $stash = ""; } else { - $stash = "::$stash" if $stash eq "CORE"; $stash = $stash . "::"; } if (!$raw and $name =~ /^(\^..|{)/) { @@ -1794,7 +1793,7 @@ sub gv_name { sub stash_variable { my ($self, $prefix, $name, $cx) = @_; - return "$prefix$name" if $name =~ /::/; + return $prefix.$self->maybe_qualify($prefix, $name) if $name =~ /::/; unless ($prefix eq '$' || $prefix eq '@' || $prefix eq '&' || #' $prefix eq '%' || $prefix eq '$#') { @@ -1870,11 +1869,16 @@ sub stash_variable_name { sub maybe_qualify { my ($self,$prefix,$name) = @_; my $v = ($prefix eq '$#' ? '@' : $prefix) . $name; - return $name if !$prefix || $name =~ /::/; + if ($prefix eq "") { + $name .= "::" if $name =~ /(?:\ACORE::[^:]*|::)\z/; + return $name; + } + return $name if $name =~ /::/; return $self->{'curstash'}.'::'. $name if $name =~ /^(?!\d)\w/ # alphabetic && $v !~ /^\$[ab]\z/ # not $a or $b + && $v =~ /\A[\$\@\%]/ # scalar, array, or hash && !$globalnames{$name} # not a global name && $self->{hints} & $strict_bits{vars} # strict vars && !$self->lex_in_scope($v,1) # no "our" @@ -4052,7 +4056,7 @@ sub pp_gv { my $self = shift; my($op, $cx) = @_; my $gv = $self->gv_or_padgv($op); - return $self->gv_name($gv); + return $self->maybe_qualify("", $self->gv_name($gv)); } sub pp_aelemfast_lex { @@ -4089,7 +4093,8 @@ sub rv2x { } my $kid = $op->first; if ($kid->name eq "gv") { - return $self->stash_variable($type, $self->deparse($kid, 0), $cx); + return $self->stash_variable($type, + $self->gv_name($self->gv_or_padgv($kid)), $cx); } elsif (is_scalar $kid) { my $str = $self->deparse($kid, 0); if ($str =~ /^\$([^\w\d])\z/) { @@ -4572,6 +4577,7 @@ sub pp_gelem { my $scope = is_scope($glob); $glob = $self->deparse($glob, 0); $part = $self->deparse($part, 1); + $glob =~ s/::\z// unless $scope; return "*" . ($scope ? "{$glob}" : $glob) . "{$part}"; } @@ -4877,7 +4883,7 @@ sub pp_entersub { $proto = $cv->PV if $cv->FLAGS & SVf_POK; } $simple = 1; # only calls of named functions can be prototyped - $kid = $self->deparse($kid, 24); + $kid = $self->maybe_qualify("&", $self->gv_name($gv)); my $fq; # Fully qualify any sub name that conflicts with a lexical. if ($self->lex_in_scope("&$kid") diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t index 63a4a083a5..27d1b3a2c2 100644 --- a/lib/B/Deparse.t +++ b/lib/B/Deparse.t @@ -2858,4 +2858,50 @@ $str = 'foo'; $str =~ tr/\cA//; #### # CORE::foo special case in bareword parsing -print ::CORE::foo $a; +print $CORE::foo, $CORE::foo::bar; +print @CORE::foo, @CORE::foo::bar; +print %CORE::foo, %CORE::foo::bar; +print $CORE::foo{'a'}, $CORE::foo::bar{'a'}; +print &CORE::foo, &CORE::foo::bar; +print &CORE::foo(), &CORE::foo::bar(); +print *CORE::foo, *CORE::foo::bar; +print stat CORE::foo::, stat CORE::foo::bar; +print CORE::foo:: 1; +print CORE::foo::bar 2; +#### +# trailing colons on glob names +no strict 'vars'; +$Foo::::baz = 1; +print $foo, $foo::, $foo::::; +print @foo, @foo::, @foo::::; +print %foo, %foo::, %foo::::; +print $foo{'a'}, $foo::{'a'}, $foo::::{'a'}; +print &foo, &foo::, &foo::::; +print &foo(), &foo::(), &foo::::(); +print *foo, *foo::, *foo::::; +print stat Foo, stat Foo::::; +print Foo 1; +print Foo:::: 2; +#### +# trailing colons mixed with CORE +no strict 'vars'; +print $CORE, $CORE::, $CORE::::; +print @CORE, @CORE::, @CORE::::; +print %CORE, %CORE::, %CORE::::; +print $CORE{'a'}, $CORE::{'a'}, $CORE::::{'a'}; +print &CORE, &CORE::, &CORE::::; +print &CORE(), &CORE::(), &CORE::::(); +print *CORE, *CORE::, *CORE::::; +print stat CORE, stat CORE::::; +print CORE 1; +print CORE:::: 2; +print $CORE::foo, $CORE::foo::, $CORE::foo::::; +print @CORE::foo, @CORE::foo::, @CORE::foo::::; +print %CORE::foo, %CORE::foo::, %CORE::foo::::; +print $CORE::foo{'a'}, $CORE::foo::{'a'}, $CORE::foo::::{'a'}; +print &CORE::foo, &CORE::foo::, &CORE::foo::::; +print &CORE::foo(), &CORE::foo::(), &CORE::foo::::(); +print *CORE::foo, *CORE::foo::, *CORE::foo::::; +print stat CORE::foo::, stat CORE::foo::::; +print CORE::foo:: 1; +print CORE::foo:::: 2; |