This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
new perldelta
[perl5.git] / t / op / undef.t
CommitLineData
a687059c
LW
1#!./perl
2
e03bd546
JH
3BEGIN {
4 chdir 't' if -d 't';
48f8bad9 5 require './test.pl';
624c42e2 6 set_up_inc('../lib');
e03bd546
JH
7}
8
48f8bad9 9use strict;
a687059c 10
83461ff8 11my (@ary, %ary, %hash);
48f8bad9 12
22d01053 13plan 88;
48f8bad9
NC
14
15ok !defined($a);
a687059c
LW
16
17$a = 1+1;
48f8bad9 18ok defined($a);
a687059c
LW
19
20undef $a;
48f8bad9 21ok !defined($a);
a687059c
LW
22
23$a = "hi";
48f8bad9 24ok defined($a);
a687059c
LW
25
26$a = $b;
48f8bad9 27ok !defined($a);
a687059c
LW
28
29@ary = ("1arg");
30$a = pop(@ary);
48f8bad9 31ok defined($a);
a687059c 32$a = pop(@ary);
48f8bad9 33ok !defined($a);
a687059c
LW
34
35@ary = ("1arg");
36$a = shift(@ary);
48f8bad9 37ok defined($a);
a687059c 38$a = shift(@ary);
48f8bad9 39ok !defined($a);
a687059c
LW
40
41$ary{'foo'} = 'hi';
48f8bad9
NC
42ok defined($ary{'foo'});
43ok !defined($ary{'bar'});
a687059c 44undef $ary{'foo'};
48f8bad9 45ok !defined($ary{'foo'});
a687059c 46
48f8bad9 47sub foo { pass; 1 }
a687059c 48
48f8bad9 49&foo || fail;
a687059c 50
48f8bad9 51ok defined &foo;
a687059c 52undef &foo;
48f8bad9 53ok !defined(&foo);
a3f914c5
GS
54
55eval { undef $1 };
48f8bad9 56like $@, qr/^Modification of a read/;
a3f914c5
GS
57
58eval { $1 = undef };
48f8bad9 59like $@, qr/^Modification of a read/;
a3f914c5 60
659eaf73 61{
3d387947
JH
62 # [perl #17753] segfault when undef'ing unquoted string constant
63 eval 'undef tcp';
48f8bad9 64 like $@, qr/^Can't modify constant item/;
3d387947 65}
2f86008e
DM
66
67# bugid 3096
68# undefing a hash may free objects with destructors that then try to
3b37eb24
DM
69# modify the hash. Ensure that the hash remains consistent
70
71{
72 my (%hash, %mirror);
73
74 my $iters = 5;
75
76 for (1..$iters) {
77 $hash{"k$_"} = bless ["k$_"], 'X';
78 $mirror{"k$_"} = "k$_";
79 }
80
81
82 my $c = $iters;
83 my $events;
84
85 sub X::DESTROY {
86 my $key = $_[0][0];
87 $events .= 'D';
88 note("----- DELETE($key) ------");
89 delete $mirror{$key};
90
91 is join('-', sort keys %hash), join('-', sort keys %mirror),
92 "$key: keys";
93 is join('-', sort map $_->[0], values %hash),
94 join('-', sort values %mirror), "$key: values";
95
96 # don't know exactly what we'll get from the iterator, but
97 # it must be a sensible value
98 my ($k, $v) = each %hash;
99 ok defined $k ? exists($mirror{$k}) : (keys(%mirror) == 0),
100 "$key: each 1";
101
102 is delete $hash{$key}, undef, "$key: delete";
103 ($k, $v) = each %hash;
104 ok defined $k ? exists($mirror{$k}) : (keys(%mirror) <= 1),
105 "$key: each 2";
106
107 $c++;
108 if ($c <= $iters * 2) {
109 $hash{"k$c"} = bless ["k$c"], 'X';
110 $mirror{"k$c"} = "k$c";
111 }
112 $events .= 'E';
113 }
114
115 each %hash; # set eiter
116 undef %hash;
117
118 is scalar keys %hash, 0, "hash empty at end";
119 is $events, ('DE' x ($iters*2)), "events";
120 my ($k, $v) = each %hash;
121 is $k, undef, 'each undef at end';
2f86008e 122}
6e592b3a 123
d054cdb0
FC
124# part of #105906: inlined undef constant getting copied
125BEGIN { $::{z} = \undef }
126for (z,z) {
127 push @_, \$_;
128}
129is $_[0], $_[1], 'undef constants preserve identity';
130
4dda930b
FC
131# [perl #122556]
132my $messages;
133package Thingie;
134DESTROY { $messages .= 'destroyed ' }
135package main;
136sub body {
137 sub {
138 my $t = bless [], 'Thingie';
139 undef $t;
140 }->(), $messages .= 'after ';
141
142 return;
143}
144body();
145is $messages, 'destroyed after ', 'undef $scalar frees refs immediately';
146
147
6e592b3a
BM
148# this will segfault if it fails
149
150sub PVBM () { 'foo' }
151{ my $dummy = index 'foo', PVBM }
152
153my $pvbm = PVBM;
154undef $pvbm;
48f8bad9 155ok !defined $pvbm;
c74a928a
RL
156
157# Prior to GH#20077 (Add OPpTARGET_MY optimization to OP_UNDEF), any PV
158# allocation was kept with "$x = undef" but freed with "undef $x". That
159# behaviour was carried over and is expected to still be present.
160# (I totally copied most of this block from other t/op/* files.)
161
162SKIP: {
163 skip_without_dynamic_extension("Devel::Peek", 2);
164
165 my $out = runperl(stderr => 1,
166 progs => [ split /\n/, <<'EOS' ]);
167 require Devel::Peek;
168 my $f = q(x) x 40; $f = undef;
169 Devel::Peek::Dump($f);
170 undef $f;
171 Devel::Peek::Dump($f);
172EOS
173
174 my ($space, $first, $second) = split /SV =/, $out;
175 like($first, qr/\bPV = 0x[0-9a-f]+\b/, '$x = undef preserves PV allocation');
176 like($second, qr/\bPV = 0\b$/, 'undef $x frees PV allocation');
177}
178
179# Tests suggested for GH#20077 (Add OPpTARGET_MY optimization to OP_UNDEF)
180# (No failures were observed during development, these are just checking
181# that no failures are introduced down the line.)
182
183{
184 my $y= 1; my @x= ($y= undef);
185 is( defined($x[0]), "", 'lval undef assignment in list context');
186 is( defined($y) , "", 'scalar undef assignment in list context');
187
188 $y= 1; my $z; sub f{$z = shift} f($y=undef);
189 is( defined($y) , "", 'undef assignment in sub args');
190 is( defined($z) , "", 'undef assignment reaches @_');
191
192 ($y,$z)=(1,2); sub f{} f(($y=undef),$z);
193 is( defined($y) , "", 'undef assignment reaches @_');
194 is( $z, 2, 'undef adjacent argument is unchanged');
195}
196
197{
198 my $h= { baz => 1 }; my @k= keys %{($h=undef)||{}};
199 is( defined($h) , "", 'scalar undef assignment in keys');
200 is( scalar @k, 0, 'undef assignment dor anonhash');
201
202 my $y= 1; my @x= \($y= undef);
203 is( defined($y) , "", 'scalar undef assignment before reference');
204 is( scalar @x, 1, 'assignment of one element to array');
205 is( defined($x[0]->$*), "", 'assignment of undef element to array');
206}
22d01053
RL
207
208# GH#20336 - "my $x = undef" pushed &PL_sv_undef onto the stack, but
209# should be pushing $x (i.e. a mutable copy of &PL_sv_undef)
210is( ++(my $x = undef), 1, '"my $x = undef" pushes $x onto the stack' );