mirror of
https://github.com/Perl/perl5.git
synced 2026-01-26 08:38:23 +00:00
Perl decides on whether DB::sub is called for a sub called based on the OPpENTERSUB_DB flag in the entersub op for that call. At compilation time ck_subr sets if PL_curstash (the current compilation stash) is not equal to PL_dbstash (%DB::), which is fine. When calling an overload sub amagic_call() synthesizes an entersub OP and sets OPpENTERSUB_DB based on the same condition, but PL_curstash isn't set to the stash of the currently executing code, but is still set to the last stash code was compiled in (as modified by scope restoration). This means the flag was (perhaps nearly) always set, so the debugger would call &DB::sub even though the overload was occurring in package DB. Fix this by testing against CopSTASH(PL_curcop) instead, which other runtime stash checks also do, eg. pp_caller, doeval_compile. Fixes #24001
174 lines
3.4 KiB
Perl
174 lines
3.4 KiB
Perl
#!./perl
|
|
|
|
# intended for testing language mechanisms that debuggers use not for
|
|
# testing the debugger itself
|
|
|
|
BEGIN {
|
|
chdir 't' if -d 't';
|
|
require "./test.pl";
|
|
set_up_inc( qw(. ../lib) );
|
|
}
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
SKIP:
|
|
{
|
|
skip_if_miniperl("need XS", 1);
|
|
# github 23151
|
|
# trivial debugger
|
|
local $ENV{PERL5DB} = 'sub DB::DB {}';
|
|
# eval code trimmed from code generated by Sub::Quote
|
|
fresh_perl_is(<<'CODE', <<'EXPECT',
|
|
use B qw(SVf_IOK);
|
|
|
|
sub _do_eval {
|
|
eval $_[0] or die $!;
|
|
}
|
|
|
|
_do_eval(<<'EVAL');
|
|
{
|
|
sub table {
|
|
}
|
|
}
|
|
1;
|
|
EVAL
|
|
|
|
# look for lines that don't have an IV set
|
|
my ($f) = grep /\(eval/, keys %::;
|
|
my $x = $::{$f};
|
|
my $lineno = 0;
|
|
for my $l (@$x) {
|
|
if ($l) {
|
|
my $b = B::svref_2object(\$l);
|
|
if (!($b->FLAGS & SVf_IOK)) {
|
|
print "No IV for $f line $lineno: $l\n";
|
|
last
|
|
}
|
|
}
|
|
++$lineno;
|
|
}
|
|
|
|
print "Done\n";
|
|
CODE
|
|
Done
|
|
EXPECT
|
|
{
|
|
switches => [ '-d' ],
|
|
stderr => 1,
|
|
},
|
|
"saved lines all have an IV"
|
|
);
|
|
}
|
|
|
|
SKIP:
|
|
{
|
|
# Historically lines were stored as PVMG, but we don't need
|
|
# magic on these lines.
|
|
#
|
|
# This checks that none of these lines get upgraded, ie. that
|
|
# we don't need them to be PVMG
|
|
#
|
|
# If this test fails perhaps we do need to make them PVMG
|
|
# and toke.c:S_update_debugger_info and pp_ctl.c:S_save_lines
|
|
# can be switched back to using SVt_PVMG and this test
|
|
# removed.
|
|
#
|
|
# See https://github.com/Perl/perl5/pull/23171#issuecomment-2780007725
|
|
skip_if_miniperl("need B");
|
|
local $ENV{PERL5DB} = 'sub DB::DB {}';
|
|
fresh_perl_is(<<'CODE', <<'EXPECT',
|
|
use B;
|
|
|
|
sub _do_eval {
|
|
eval $_[0] or die $!;
|
|
}
|
|
|
|
_do_eval(<<'EVAL');
|
|
|
|
sub some_code {
|
|
print "Hello";
|
|
}
|
|
|
|
1;
|
|
EVAL
|
|
|
|
# check if any lines have been upgraded from PVIV
|
|
my @files = grep /^_</, keys %::;
|
|
for my $f (@files) {
|
|
my $lineno = 0;
|
|
|
|
for my $l (@{$f}) {
|
|
if ($l) {
|
|
my $b = B::svref_2object(\$l);
|
|
if (ref $b ne "B::PVIV") {
|
|
print "Not PVIV for $f:$lineno: $l\n";
|
|
last
|
|
}
|
|
}
|
|
++$lineno;
|
|
}
|
|
}
|
|
print "Done\n";
|
|
CODE
|
|
Done
|
|
EXPECT
|
|
{
|
|
switches => [ '-d' ],
|
|
stderr => 1,
|
|
},
|
|
"saved lines are all PVIV"
|
|
);
|
|
}
|
|
|
|
{
|
|
# GH 24001
|
|
local $ENV{PERL5DB} = 'sub DB::DB {}';
|
|
fresh_perl_is(<<'CODE', "OK\n",
|
|
package DB;
|
|
sub DB::sub {
|
|
# avoid deep recursion
|
|
die "Fail" if $DB::sub =~ /^version::/;
|
|
# trigger overloading call from package DB
|
|
my $v = "$^V";
|
|
print $v ne "" ? "OK\n" : ""
|
|
}
|
|
package main;
|
|
sub f {
|
|
}
|
|
f();
|
|
CODE
|
|
{
|
|
switches => [ '-d' ],
|
|
},
|
|
"overloading call from DB doesn't break into DB::sub");
|
|
}
|
|
{
|
|
local $ENV{PERL5DB} = 'sub DB::DB {}';
|
|
# make sure we don't break the expected break
|
|
fresh_perl_is(<<'CODE', "OK\n",
|
|
package DB;
|
|
sub DB::sub {
|
|
our @count;
|
|
if ($DB::sub eq 'version::(""') {
|
|
print "OK\n";
|
|
exit;
|
|
}
|
|
push @count, $DB::sub;
|
|
die "Fail @count\n" if @count > 10;
|
|
&$DB::sub;
|
|
}
|
|
package main;
|
|
sub f {
|
|
my $v = "$^V";
|
|
}
|
|
f();
|
|
CODE
|
|
{
|
|
switches => [ '-d' ],
|
|
},
|
|
"overloading call from non-DB does break into DB::sub");
|
|
}
|
|
|
|
done_testing();
|