xref: /openbsd-src/gnu/usr.bin/perl/t/op/multideref.t (revision b46d8ef224b95de1dddcd1f01c1ab482f0ab3778)
1b8851fccSafresh1#!./perl
2b8851fccSafresh1#
3b8851fccSafresh1# test OP_MULTIDEREF.
4b8851fccSafresh1#
5b8851fccSafresh1# This optimising op is used when one or more array or hash aggregate
6b8851fccSafresh1# lookups / derefs are performed, and where each key/index is a simple
7b8851fccSafresh1# constant or scalar var; e.g.
8b8851fccSafresh1#
9b8851fccSafresh1#       $r->{foo}[0]{$k}[$i]
10b8851fccSafresh1
11b8851fccSafresh1
12b8851fccSafresh1BEGIN {
13b8851fccSafresh1    chdir 't';
14b8851fccSafresh1    require './test.pl';
15b8851fccSafresh1    set_up_inc("../lib");
16b8851fccSafresh1}
17b8851fccSafresh1
18b8851fccSafresh1use warnings;
19b8851fccSafresh1use strict;
20b8851fccSafresh1
21*b46d8ef2Safresh1plan 65;
22b8851fccSafresh1
23b8851fccSafresh1
24b8851fccSafresh1# check that strict refs hint is handled
25b8851fccSafresh1
26b8851fccSafresh1{
27b8851fccSafresh1    package strict_refs;
28b8851fccSafresh1
29b8851fccSafresh1    our %foo;
30b8851fccSafresh1    my @a = ('foo');
31b8851fccSafresh1    eval {
32b8851fccSafresh1        $a[0]{k} = 7;
33b8851fccSafresh1    };
34b8851fccSafresh1    ::like($@, qr/Can't use string/, "strict refs");
35b8851fccSafresh1    ::ok(!exists $foo{k}, "strict refs, not exist");
36b8851fccSafresh1
37b8851fccSafresh1    no strict 'refs';
38b8851fccSafresh1
39b8851fccSafresh1    $a[0]{k} = 13;
40b8851fccSafresh1    ::is($foo{k}, 13, "no strict refs, exist");
41b8851fccSafresh1}
42b8851fccSafresh1
43b8851fccSafresh1# check the basics of multilevel lookups
44b8851fccSafresh1
45b8851fccSafresh1{
46b8851fccSafresh1    package basic;
47b8851fccSafresh1
48b8851fccSafresh1    # build up the multi-level structure piecemeal to try and avoid
49b8851fccSafresh1    # relying on what we're testing
50b8851fccSafresh1
51b8851fccSafresh1    my @a;
52b8851fccSafresh1    my $r = \@a;
53b8851fccSafresh1    my $rh = {};
54b8851fccSafresh1    my $ra = [];
55b8851fccSafresh1    my %h = qw(a 1 b 2 c 3 d 4 e 5 f 6);
56b8851fccSafresh1    push @a, 66, 77, 'abc', $rh;
57b8851fccSafresh1    %$rh = (foo => $ra, bar => 'BAR');
58b8851fccSafresh1    push @$ra, 'def', \%h;
59b8851fccSafresh1
60b8851fccSafresh1    our ($i1, $i2,  $k1,  $k2)  = (3, 1, 'foo', 'c');
61b8851fccSafresh1    my ($li1, $li2, $lk1, $lk2) = (3, 1, 'foo', 'c');
62b8851fccSafresh1    my $z = 0;
63b8851fccSafresh1
64b8851fccSafresh1    # fetch
65b8851fccSafresh1
66b8851fccSafresh1    ::is($a[3]{foo}[1]{c}, 3,             'fetch: const indices');
67b8851fccSafresh1    ::is($a[$i1]{$k1}[$i2]{$k2}, 3,       'fetch: pkg indices');
68b8851fccSafresh1    ::is($r->[$i1]{$k1}[$i2]{$k2}, 3,     'fetch: deref pkg indices');
69b8851fccSafresh1    ::is($a[$li1]{$lk1}[$li2]{$lk2}, 3,   'fetch: lexical indices');
70b8851fccSafresh1    ::is($r->[$li1]{$lk1}[$li2]{$lk2}, 3, 'fetch: deref lexical indices');
71b8851fccSafresh1    ::is(($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2}, 3,
72b8851fccSafresh1                            'fetch: general expression and index');
73b8851fccSafresh1
74b8851fccSafresh1
75b8851fccSafresh1    # store
76b8851fccSafresh1
77b8851fccSafresh1    ::is($a[3]{foo}[1]{c} = 5, 5,             'store: const indices');
78b8851fccSafresh1    ::is($a[3]{foo}[1]{c}, 5,                 'store: const indices 2');
79b8851fccSafresh1    ::is($a[$i1]{$k1}[$i2]{$k2} = 7, 7,       'store: pkg indices');
80b8851fccSafresh1    ::is($a[$i1]{$k1}[$i2]{$k2}, 7,           'store: pkg indices 2');
81b8851fccSafresh1    ::is($r->[$i1]{$k1}[$i2]{$k2} = 9, 9,     'store: deref pkg indices');
82b8851fccSafresh1    ::is($r->[$i1]{$k1}[$i2]{$k2}, 9,         'store: deref pkg indices 2');
83b8851fccSafresh1    ::is($a[$li1]{$lk1}[$li2]{$lk2} = 11, 11, 'store: lexical indices');
84b8851fccSafresh1    ::is($a[$li1]{$lk1}[$li2]{$lk2}, 11,      'store: lexical indices 2');
85b8851fccSafresh1    ::is($r->[$li1]{$lk1}[$li2]{$lk2} = 13, 13, 'store: deref lexical indices');
86b8851fccSafresh1    ::is($r->[$li1]{$lk1}[$li2]{$lk2}, 13,    'store: deref lexical indices 2');
87b8851fccSafresh1    ::is(($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2} = 15, 15,
88b8851fccSafresh1                            'store: general expression and index');
89b8851fccSafresh1    ::is(($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2}, 15,
90b8851fccSafresh1                            'store: general expression and index 2');
91b8851fccSafresh1
92b8851fccSafresh1
93b8851fccSafresh1    # local
94b8851fccSafresh1
95b8851fccSafresh1    {
96b8851fccSafresh1        ::is(local $a[3]{foo}[1]{c} = 19, 19,     'local const indices');
97b8851fccSafresh1        ::is($a[3]{foo}[1]{c}, 19,                'local const indices 2');
98b8851fccSafresh1    }
99b8851fccSafresh1    ::is($a[3]{foo}[1]{c}, 15,          'local const indices 3');
100b8851fccSafresh1    {
101b8851fccSafresh1        ::is(local $a[$i1]{$k1}[$i2]{$k2} = 21, 21,     'local pkg indices');
102b8851fccSafresh1        ::is($a[$i1]{$k1}[$i2]{$k2}, 21,          'local pkg indices 2');
103b8851fccSafresh1    }
104b8851fccSafresh1    ::is($a[$i1]{$k1}[$i2]{$k2}, 15,     'local pkg indices 3');
105b8851fccSafresh1    {
106b8851fccSafresh1        ::is(local $a[$li1]{$lk1}[$li2]{$lk2} = 23, 23, 'local lexical indices');
107b8851fccSafresh1        ::is($a[$li1]{$lk1}[$li2]{$lk2}, 23,      'local lexical indices 2');
108b8851fccSafresh1    }
109b8851fccSafresh1    ::is($a[$li1]{$lk1}[$li2]{$lk2}, 15, 'local lexical indices 3');
110b8851fccSafresh1    {
111b8851fccSafresh1        ::is(local+($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2} = 25, 25,
112b8851fccSafresh1                                                            'local general');
113b8851fccSafresh1        ::is(($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2}, 25,      'local general 2');
114b8851fccSafresh1    }
115b8851fccSafresh1    ::is(($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2}, 15, 'local general 3');
116b8851fccSafresh1
117b8851fccSafresh1
118b8851fccSafresh1    # exists
119b8851fccSafresh1
120b8851fccSafresh1    ::ok(exists $a[3]{foo}[1]{c},           'exists: const indices');
121b8851fccSafresh1    ::ok(exists $a[$i1]{$k1}[$i2]{$k2},     'exists: pkg indices');
122b8851fccSafresh1    ::ok(exists $r->[$i1]{$k1}[$i2]{$k2},   'exists: deref pkg indices');
123b8851fccSafresh1    ::ok(exists $a[$li1]{$lk1}[$li2]{$lk2}, 'exists: lexical indices');
124b8851fccSafresh1    ::ok(exists $r->[$li1]{$lk1}[$li2]{$lk2}, 'exists: deref lexical indices');
125b8851fccSafresh1    ::ok(exists +($r//0)->[$li1]{$lk1}[$li2+$z]{$lk2}, 'exists: general');
126b8851fccSafresh1
127b8851fccSafresh1    # delete
128b8851fccSafresh1
129b8851fccSafresh1    our $k3 = 'a';
130b8851fccSafresh1    my $lk4 = 'b';
131b8851fccSafresh1    ::is(delete $a[3]{foo}[1]{c}, 15,          'delete: const indices');
132b8851fccSafresh1    ::is(delete $a[$i1]{$k1}[$i2]{$k3}, 1,     'delete: pkg indices');
133b8851fccSafresh1    ::is(delete $r->[$i1]{$k1}[$i2]{d}, 4,     'delete: deref pkg indices');
134b8851fccSafresh1    ::is(delete $a[$li1]{$lk1}[$li2]{$lk4}, 2, 'delete: lexical indices');
135b8851fccSafresh1    ::is(delete $r->[$li1]{$lk1}[$li2]{e}, 5,  'delete: deref lexical indices');
136b8851fccSafresh1    ::is(delete +($r//0)->[$li1]{$lk1}[$li2+$z]{f}, 6,  'delete: general');
137b8851fccSafresh1
138b8851fccSafresh1    # !exists
139b8851fccSafresh1
140b8851fccSafresh1    ::ok(!exists $a[3]{foo}[1]{c},            '!exists: const indices');
141b8851fccSafresh1    ::ok(!exists $a[$i1]{$k1}[$i2]{$k3},      '!exists: pkg indices');
142b8851fccSafresh1    ::ok(!exists $r->[$i1]{$k1}[$i2]{$k3},    '!exists: deref pkg indices');
143b8851fccSafresh1    ::ok(!exists $a[$li1]{$lk1}[$li2]{$lk4},  '!exists: lexical indices');
144b8851fccSafresh1    ::ok(!exists $r->[$li1]{$lk1}[$li2]{$lk4},'!exists: deref lexical indices');
145b8851fccSafresh1    ::ok(!exists +($r//0)->[$li1]{$lk1}[$li2+$z]{$lk4},'!exists: general');
146b8851fccSafresh1}
147b8851fccSafresh1
148b8851fccSafresh1
149b8851fccSafresh1# weird "constant" keys
150b8851fccSafresh1
151b8851fccSafresh1{
152b8851fccSafresh1    use constant my_undef => undef;
153b8851fccSafresh1    use constant my_ref   => [];
154b8851fccSafresh1    no warnings 'uninitialized';
155b8851fccSafresh1    my %h1;
156b8851fccSafresh1    $h1{+my_undef} = 1;
157b8851fccSafresh1    is(join(':', keys %h1), '', "+my_undef");
158b8851fccSafresh1    my %h2;
159b8851fccSafresh1    $h2{+my_ref} = 1;
160b8851fccSafresh1    like(join(':', keys %h2), qr/x/, "+my_ref");
161b8851fccSafresh1}
162b8851fccSafresh1
163b8851fccSafresh1
164b8851fccSafresh1
165b8851fccSafresh1{
166b8851fccSafresh1    # test that multideref is marked OA_DANGEROUS, i.e. its one of the ops
167b8851fccSafresh1    # that should set the OPpASSIGN_COMMON flag in list assignments
168b8851fccSafresh1
169b8851fccSafresh1    my $x = {};
170b8851fccSafresh1    $x->{a} = [ 1 ];
171b8851fccSafresh1    $x->{b} = [ 2 ];
172b8851fccSafresh1    ($x->{a}, $x->{b}) = ($x->{b}, $x->{a});
173b8851fccSafresh1    is($x->{a}[0], 2, "OA_DANGEROUS a");
174b8851fccSafresh1    is($x->{b}[0], 1, "OA_DANGEROUS b");
175b8851fccSafresh1}
176b8851fccSafresh1
177b8851fccSafresh1# defer
178b8851fccSafresh1
179b8851fccSafresh1
180b8851fccSafresh1sub defer {}
181b8851fccSafresh1
182b8851fccSafresh1{
183b8851fccSafresh1    my %h;
184b8851fccSafresh1    $h{foo} = {};
185b8851fccSafresh1    defer($h{foo}{bar});
186b8851fccSafresh1    ok(!exists $h{foo}{bar}, "defer");
187b8851fccSafresh1}
188b8851fccSafresh1
189b8851fccSafresh1# RT #123609
190b8851fccSafresh1# don't evaluate a const array index unless it's really a const array
191b8851fccSafresh1# index
192b8851fccSafresh1
193b8851fccSafresh1{
194b8851fccSafresh1    my $warn = '';
195b8851fccSafresh1    local $SIG{__WARN__} = sub { $warn .= $_[0] };
196b8851fccSafresh1    ok(
197b8851fccSafresh1        eval q{
198b8851fccSafresh1            my @a = (1);
199b8851fccSafresh1            my $arg = 0;
200b8851fccSafresh1            my $x = $a[ 'foo' eq $arg ? 1 : 0 ];
201b8851fccSafresh1            1;
202b8851fccSafresh1        },
203b8851fccSafresh1        "#123609: eval"
204b8851fccSafresh1    )
205b8851fccSafresh1        or diag("eval gave: $@");
206b8851fccSafresh1    is($warn, "", "#123609: warn");
207b8851fccSafresh1}
2085759b3d2Safresh1
2095759b3d2Safresh1# RT #130727
2105759b3d2Safresh1# a [ah]elem op can be both OPpLVAL_INTRO and OPpDEREF. It may not make
2115759b3d2Safresh1# much sense, but it shouldn't fail an assert.
2125759b3d2Safresh1
2135759b3d2Safresh1{
2145759b3d2Safresh1    my @x;
2155759b3d2Safresh1    eval { @{local $x[0][0]} = 1; };
2165759b3d2Safresh1    like $@, qr/Can't use an undefined value as an ARRAY reference/,
2175759b3d2Safresh1                    "RT #130727 error";
2185759b3d2Safresh1    ok !defined $x[0][0],"RT #130727 array not autovivified";
2195759b3d2Safresh1
2205759b3d2Safresh1    eval { @{1, local $x[0][0]} = 1; };
2215759b3d2Safresh1    like $@, qr/Can't use an undefined value as an ARRAY reference/,
2225759b3d2Safresh1                    "RT #130727 part 2: error";
2235759b3d2Safresh1    ok !defined $x[0][0],"RT #130727 part 2: array not autovivified";
2245759b3d2Safresh1
2255759b3d2Safresh1}
2265759b3d2Safresh1
2275759b3d2Safresh1# RT #131627: assertion failure on OPf_PAREN on OP_GV
2285759b3d2Safresh1{
2295759b3d2Safresh1    my @x = (10..12);
2305759b3d2Safresh1    our $rt131627 = 1;
2315759b3d2Safresh1
2325759b3d2Safresh1    no strict qw(refs vars);
2335759b3d2Safresh1    is $x[qw(rt131627)->$*], 11, 'RT #131627: $a[qw(var)->$*]';
2345759b3d2Safresh1}
2355759b3d2Safresh1
236*b46d8ef2Safresh1# this used to leak - run the code for ASan to spot any problems
237*b46d8ef2Safresh1{
238*b46d8ef2Safresh1    package Foo;
239*b46d8ef2Safresh1    our %FIELDS = ();
240*b46d8ef2Safresh1    my Foo $f;
241*b46d8ef2Safresh1    eval q{ my $x = $f->{c}; };
242*b46d8ef2Safresh1    ::pass("S_maybe_multideref() shouldn't leak on croak");
243*b46d8ef2Safresh1}
244*b46d8ef2Safresh1
245*b46d8ef2Safresh1fresh_perl_is('0for%{scalar local$0[0]}', '', {},
246*b46d8ef2Safresh1              "RT #134045 assertion on the OP_SCALAR");
247