XSRETURN_UNDEF;
ST(0) = sv_2mortal(newSVpvn(&on->buf, on->len));
XSRETURN(1);
+
+void
+_constant_sub(SV *sv)
+PROTOTYPE: $
+PPCODE:
+ if (!SvROK(sv))
+ XSRETURN_UNDEF;
+ sv = SvRV(sv);
+ if (SvTYPE(sv) < SVt_PVCV)
+ XSRETURN_UNDEF;
+ ST(0) = sv_2mortal(newSVuv(CvCONST(sv)));
+ XSRETURN(1);
my $pkg = $data->{pkg};
my $fqn = join '::', $pkg, $name;
- no strict 'refs';
- *$fqn = $placeholder unless exists &$fqn;
+ {
+ local $SIG{__WARN__} = sub {
+ CORE::warn(@_) unless $_[0] =~ /^Constant subroutine.*redefined/;
+ } if _constant_sub(do { no strict 'refs'; \&$fqn });
+ no strict 'refs';
+ no warnings 'redefine';
+ *$fqn = $placeholder;
+ }
return;
},
my $fqn = join '::', $pkg, $name;
return {
+ old => _defined_sub($fqn) ? \&$fqn : undef,
proto => prototype($fqn),
};
}
my $pkg = @_ > 0 ? $_[0] : caller;
my $map = _map($pkg);
+ my $fqn = join '::', $pkg, $name;
+
if (defined $map) {
- my $proto = $map->{$name}->{proto};
+ my $tag = $map->{$name};
+
+ my $old = $tag->{old};
+ if (defined $old) {
+ no strict 'refs';
+ no warnings 'redefine';
+ *$fqn = $old;
+ }
+
+ my $proto = $tag->{proto};
if (defined $proto) {
no strict 'refs';
- Scalar::Util::set_prototype(\&{"${pkg}::$name"}, $proto);
+ Scalar::Util::set_prototype(\&$fqn, $proto);
}
delete $map->{$name};
use blib 't/Sub-Op-LexicalSub';
-use Test::More tests => 2 *((4 + 2 * 4) + (2 * 5) + 1);
+use Test::More tests => 2 * ((1 + 2) * 4 + (1 + 1) * 5) + (2 + 2) + 4;
our $call_foo;
sub foo { ok $call_foo, 'the preexistent foo was called' }
our $call_bar;
sub bar () { ok $call_bar, 'the preexistent bar was called' }
+sub X () { 1 }
+
our $called;
{
is prototype('main::foo'), undef, "foo's prototype was preserved";
is prototype('main::bar'), '', "bar's prototype was preserved";
+is prototype('main::X'), '', "X's prototype was preserved";
+ok Sub::Op::_constant_sub(do { no strict "refs"; \&{"main::X"} }),
+ 'X is still a constant';
__DATA__
foo();
&$bar;
----
bar # () #
+####
+is X, 2, 'constant overriding';
+----
+X # 2 # [ ]