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