This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
make do "a\0b" fail silently instead of throwing (RT #129928)
[perl5.git] / t / op / coresubs.t
CommitLineData
7fa5bd9b
FC
1#!./perl
2
bfce6a3e
FC
3# This script tests the inlining and prototype of CORE:: subs. Any generic
4# tests that are not specific to &foo-style calls should go in this
5# file, too.
7fa5bd9b
FC
6
7BEGIN {
8 chdir 't' if -d 't';
1ae3d757 9 require "./test.pl";
624c42e2 10 set_up_inc(qw(. ../lib));
47ac839d 11 skip_all_without_dynamic_extension('B');
7fa5bd9b
FC
12 $^P |= 0x100;
13}
7fa5bd9b 14
26cacb72 15use B;
7fa5bd9b 16
6c871ae8
FC
17my %unsupported = map +($_=>1), qw (
18 __DATA__ __END__ AUTOLOAD BEGIN UNITCHECK CORE DESTROY END INIT CHECK and
d51f8b19 19 cmp default do dump else elsif eq eval for foreach
498a02d8 20 format ge given goto grep gt if last le local lt m map my ne next
919ad5f7 21 no or our package print printf q qq qr qw qx redo require
46bef06f 22 return s say sort state sub tr unless until use
6c871ae8
FC
23 when while x xor y
24);
47ac839d
FC
25my %args_for = (
26 dbmopen => '%1,$2,$3',
a69823cd
FC
27 (dbmclose => '%1',
28 keys =>
29 values =>
30 each =>)[0,1,2,1,3,1,4,1],
eb31eb35 31 delete => '$1[2]',
d51f8b19 32 exists => '$1[2]',
a69823cd
FC
33 (push => '@1',
34 pop =>
35 shift =>
36 unshift =>
37 splice =>)[0,1,2,1,3,1,4,1,5,1],
46e00a91 38);
1efec5ed
FC
39my %desc = (
40 pos => 'match position',
41);
46e00a91 42
47ac839d
FC
43use File::Spec::Functions;
44my $keywords_file = catfile(updir,'regen','keywords.pl');
45open my $kh, $keywords_file
46 or die "$0 cannot open $keywords_file: $!";
47while(<$kh>) {
48 if (m?__END__?..${\0} and /^[+-]/) {
49 chomp(my $word = $');
6c871ae8 50 if($unsupported{$word}) {
47ac839d 51 $tests ++;
9da346da 52 ok !defined &{"CORE::$word"}, "no CORE::$word";
46e00a91 53 }
47ac839d 54 else {
5e33e2aa 55 $tests += 2;
9da346da
FC
56
57 ok defined &{"CORE::$word"}, "defined &{'CORE::$word'}";
47ac839d
FC
58
59 my $proto = prototype "CORE::$word";
60 *{"my$word"} = \&{"CORE::$word"};
61 is prototype \&{"my$word"}, $proto, "prototype of &CORE::$word";
62
63 CORE::state $protochar = qr/([^\\]|\\(?:[^[]|\[[^]]+\]))/;
64 my $numargs =
d51f8b19 65 $word eq 'delete' || $word eq 'exists' ? 1 :
eb31eb35 66 (() = $proto =~ s/;.*//r =~ /\G$protochar/g);
47ac839d 67
5e33e2aa 68 inlinable_ok($word, $args_for{$word} || join ",", map "\$$_", 1..$numargs);
47ac839d
FC
69
70 # High-precedence tests
71 my $hpcode;
72 if (!$proto && defined $proto) { # nullary
73 $hpcode = "sub { () = my$word + 1 }";
46e00a91 74 }
47ac839d
FC
75 elsif ($proto =~ /^;?$protochar\z/) { # unary
76 $hpcode = "sub { () = my$word "
77 . ($args_for{$word}||'$a') . ' > $b'
78 .'}';
79 }
80 if ($hpcode) {
81 $tests ++;
c4c61c60
FC
82 # __FILE__ won’t fold with warnings on, and then we get
83 # ‘(eval 21)’ vs ‘(eval 22)’.
84 no warnings 'numeric';
26cacb72
FC
85 $core = op_list(eval $hpcode =~ s/my/CORE::/r or die);
86 $my = op_list(eval $hpcode or die);
47ac839d 87 is $my, $core, "precedence of CORE::$word without parens";
46e00a91 88 }
93f0bc49 89
47ac839d
FC
90 next if ($proto =~ /\@/);
91 # These ops currently accept any number of args, despite their
92 # prototypes, if they have any:
919ad5f7
FC
93 next if $word =~ /^(?:chom?p|exec|keys|each|not
94 |(?:prototyp|read(?:lin|pip))e
7d789282 95 |reset|system|values|l?stat)|evalbytes/x;
bf0571fd 96
bccb6c7b 97 $tests ++;
47ac839d
FC
98 $code =
99 "sub { () = (my$word("
100 . (
101 $args_for{$word}
102 ? $args_for{$word}.',$7'
103 : join ",", map "\$$_", 1..$numargs+5+(
104 $proto =~ /;/
105 ? () = $' =~ /\G$protochar/g
106 : 0
107 )
108 )
109 . "))}";
110 eval $code;
1efec5ed
FC
111 my $desc = $desc{$word} || $word;
112 like $@, qr/^Too many arguments for $desc/,
47ac839d
FC
113 "inlined CORE::$word with too many args"
114 or warn $code;
115
bccb6c7b
FC
116 }
117 }
118}
7fa5bd9b 119
26cacb72
FC
120sub B::OP::pushname { push @op_names, shift->name }
121
122sub op_list {
123 local @op_names;
124 B::walkoptree(B::svref_2object($_[0])->ROOT, 'pushname');
125 return "@op_names";
126}
127
5e33e2aa
AC
128sub inlinable_ok {
129 my ($word, $args, $desc_suffix) = @_;
130 $tests += 2;
131
132 $desc_suffix //= '';
133
134 for ([with => "($args)"], [without => " $args"]) {
135 my ($preposition, $full_args) = @$_;
136 my $core_code =
137 "#line 1 This-line-makes-__FILE__-easier-to-test.
138 sub { () = (CORE::$word$full_args) }";
139 my $my_code = $core_code =~ s/CORE::$word/my$word/r;
26cacb72
FC
140 my $core = op_list(eval $core_code or die);
141 my $my = op_list(eval $my_code or die);
5e33e2aa
AC
142 is $my, $core, "inlinability of CORE::$word $preposition parens $desc_suffix";
143 }
144}
145
309aab3a
FC
146$tests++;
147# This subroutine is outside the warnings scope:
148sub foo { goto &CORE::abs }
149use warnings;
150$SIG{__WARN__} = sub { like shift, qr\^Use of uninitialized\ };
151foo(undef);
152
0f8d4b5e
FC
153$tests+=2;
154is runperl(prog => 'print CORE->lc, qq-\n-'), "core\n",
155 'methods calls autovivify coresubs';
156is runperl(prog => '@ISA=CORE; print main->uc, qq-\n-'), "MAIN\n",
157 'inherted method calls autovivify coresubs';
158
83d52ea4 159{ # RT #117607
83d52ea4
TC
160 $tests++;
161 like runperl(prog => '$foo/; \&CORE::lc', stderr => 1),
162 qr/^syntax error/, "RT #117607: \\&CORE::foo doesn't crash in error context";
163}
164
7e68c38b
FC
165$tests++;
166ok eval { *CORE::exit = \42 },
167 '[rt.cpan.org #74289] *CORE::foo is not accidentally made read-only';
168
66c742d5
AC
169inlinable_ok($_, '$_{k}', 'on hash')
170 for qw<delete exists>;
171
5811c07e
FC
172@UNIVERSAL::ISA = CORE;
173is "just another "->ucfirst . "perl hacker,\n"->ucfirst,
174 "Just another Perl hacker,\n", 'coresubs do not return TARG';
175++$tests;
176
ab157fa5 177done_testing $tests;
7fa5bd9b 178
47ac839d 179CORE::__END__