summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2017-11-16 11:01:34 +0000
committerZefram <zefram@fysh.org>2017-11-16 11:09:39 +0000
commitdd6661605fe0a54c602f2e55f875acfdcd330b79 (patch)
tree3e52a1e0129ee815b200f1fc2907a6569c2e80bf /lib
parent647672aaa908fc8ab61664986252c70fb04f3498 (diff)
downloadperl-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.pm18
-rw-r--r--lib/B/Deparse.t48
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;