1b39c5158Smillert#!./perl -w 2850e2753Smillert 3b39c5158Smillert# Uncomment this for testing, but don't leave it in for "production", as 4b39c5158Smillert# we've not yet verified that use works. 5b39c5158Smillert# use strict; 6850e2753Smillert 7*9f11ffb7Safresh1print "1..35\n"; 8b39c5158Smillertmy $test = 0; 9850e2753Smillert 10850e2753Smillert# Historically constant folding was performed by evaluating the ops, and if 11850e2753Smillert# they threw an exception compilation failed. This was seen as buggy, because 12850e2753Smillert# even illegal constants in unreachable code would cause failure. So now 13850e2753Smillert# illegal expressions are reported at runtime, if the expression is reached, 14850e2753Smillert# making constant folding consistent with many other languages, and purely an 15850e2753Smillert# optimisation rather than a behaviour change. 16850e2753Smillert 17850e2753Smillert 18b39c5158Smillertsub failed { 19b39c5158Smillert my ($got, $expected, $name) = @_; 20b39c5158Smillert 21b39c5158Smillert print "not ok $test - $name\n"; 22b39c5158Smillert my @caller = caller(1); 23b39c5158Smillert print "# Failed test at $caller[1] line $caller[2]\n"; 24b39c5158Smillert if (defined $got) { 25b39c5158Smillert print "# Got '$got'\n"; 26b39c5158Smillert } else { 27b39c5158Smillert print "# Got undef\n"; 28b39c5158Smillert } 29b39c5158Smillert print "# Expected $expected\n"; 30b39c5158Smillert return; 31b39c5158Smillert} 32b39c5158Smillert 33b39c5158Smillertsub like { 34b39c5158Smillert my ($got, $pattern, $name) = @_; 35b39c5158Smillert $test = $test + 1; 36b39c5158Smillert if (defined $got && $got =~ $pattern) { 37b39c5158Smillert print "ok $test - $name\n"; 38b39c5158Smillert # Principle of least surprise - maintain the expected interface, even 39b39c5158Smillert # though we aren't using it here (yet). 40b39c5158Smillert return 1; 41b39c5158Smillert } 42b39c5158Smillert failed($got, $pattern, $name); 43b39c5158Smillert} 44b39c5158Smillert 45b39c5158Smillertsub is { 46b39c5158Smillert my ($got, $expect, $name) = @_; 47b39c5158Smillert $test = $test + 1; 48b39c5158Smillert if (defined $got && $got eq $expect) { 49b39c5158Smillert print "ok $test - $name\n"; 50b39c5158Smillert return 1; 51b39c5158Smillert } 52b39c5158Smillert failed($got, "'$expect'", $name); 53b39c5158Smillert} 54b39c5158Smillert 55898184e3Ssthensub ok { 56898184e3Ssthen my ($got, $name) = @_; 57898184e3Ssthen $test = $test + 1; 58898184e3Ssthen if ($got) { 59898184e3Ssthen print "ok $test - $name\n"; 60898184e3Ssthen return 1; 61898184e3Ssthen } 62898184e3Ssthen failed($got, "a true value", $name); 63898184e3Ssthen} 64898184e3Ssthen 65850e2753Smillertmy $a; 66850e2753Smillert$a = eval '$b = 0/0 if 0; 3'; 67b39c5158Smillertis ($a, 3, 'constants in conditionals don\'t affect constant folding'); 68b39c5158Smillertis ($@, '', 'no error'); 69850e2753Smillert 70850e2753Smillertmy $b = 0; 71850e2753Smillert$a = eval 'if ($b) {return sqrt -3} 3'; 72b39c5158Smillertis ($a, 3, 'variables in conditionals don\'t affect constant folding'); 73b39c5158Smillertis ($@, '', 'no error'); 74850e2753Smillert 75850e2753Smillert$a = eval q{ 76850e2753Smillert $b = eval q{if ($b) {return log 0} 4}; 77b39c5158Smillert is ($b, 4, 'inner eval folds constant'); 78b39c5158Smillert is ($@, '', 'no error'); 79850e2753Smillert 5; 80850e2753Smillert}; 81b39c5158Smillertis ($a, 5, 'outer eval folds constant'); 82b39c5158Smillertis ($@, '', 'no error'); 83850e2753Smillert 84850e2753Smillert# warn and die hooks should be disabled during constant folding 85850e2753Smillert 86850e2753Smillert{ 87850e2753Smillert my $c = 0; 88850e2753Smillert local $SIG{__WARN__} = sub { $c++ }; 89850e2753Smillert local $SIG{__DIE__} = sub { $c+= 2 }; 90850e2753Smillert eval q{ 91850e2753Smillert is($c, 0, "premature warn/die: $c"); 92850e2753Smillert my $x = "a"+5; 93850e2753Smillert is($c, 1, "missing warn hook"); 94850e2753Smillert is($x, 5, "a+5"); 95850e2753Smillert $c = 0; 96850e2753Smillert $x = 1/0; 97850e2753Smillert }; 98850e2753Smillert like ($@, qr/division/, "eval caught division"); 99850e2753Smillert is($c, 2, "missing die hook"); 100850e2753Smillert} 101898184e3Ssthen 102898184e3Ssthen# [perl #20444] Constant folding should not change the meaning of match 103898184e3Ssthen# operators. 104898184e3Ssthen{ 105898184e3Ssthen local *_; 106898184e3Ssthen $_="foo"; my $jing = 1; 107898184e3Ssthen ok scalar $jing =~ (1 ? /foo/ : /bar/), 108898184e3Ssthen 'lone m// is not bound via =~ after ? : folding'; 109898184e3Ssthen ok scalar $jing =~ (0 || /foo/), 110898184e3Ssthen 'lone m// is not bound via =~ after || folding'; 111898184e3Ssthen ok scalar $jing =~ (1 ? s/foo/foo/ : /bar/), 112898184e3Ssthen 'lone s/// is not bound via =~ after ? : folding'; 113898184e3Ssthen ok scalar $jing =~ (0 || s/foo/foo/), 114898184e3Ssthen 'lone s/// is not bound via =~ after || folding'; 115898184e3Ssthen $jing = 3; 116898184e3Ssthen ok scalar $jing =~ (1 ? y/fo// : /bar/), 117898184e3Ssthen 'lone y/// is not bound via =~ after ? : folding'; 118898184e3Ssthen ok scalar $jing =~ (0 || y/fo//), 119898184e3Ssthen 'lone y/// is not bound via =~ after || folding'; 120898184e3Ssthen} 12191f110e0Safresh1 12291f110e0Safresh1# [perl #78064] or print 12391f110e0Safresh1package other { # hide the "ok" sub 12491f110e0Safresh1 BEGIN { $^W = 0 } 12591f110e0Safresh1 print 0 ? not_ok : ok; 12691f110e0Safresh1 print " ", ++$test, " - print followed by const ? BEAR : BEAR\n"; 12791f110e0Safresh1 print 1 ? ok : not_ok; 12891f110e0Safresh1 print " ", ++$test, " - print followed by const ? BEAR : BEAR (again)\n"; 12991f110e0Safresh1 print 1 && ok; 13091f110e0Safresh1 print " ", ++$test, " - print followed by const && BEAR\n"; 13191f110e0Safresh1 print 0 || ok; 13291f110e0Safresh1 print " ", ++$test, " - print followed by const || URSINE\n"; 13391f110e0Safresh1 BEGIN { $^W = 1 } 13491f110e0Safresh1} 13591f110e0Safresh1 13691f110e0Safresh1# or stat 13791f110e0Safresh1print "not " unless stat(1 ? INSTALL : 0) eq stat("INSTALL"); 13891f110e0Safresh1print "ok ", ++$test, " - stat(const ? word : ....)\n"; 13991f110e0Safresh1# in case we are in t/ 14091f110e0Safresh1print "not " unless stat(1 ? TEST : 0) eq stat("TEST"); 14191f110e0Safresh1print "ok ", ++$test, " - stat(const ? word : ....)\n"; 14291f110e0Safresh1 14391f110e0Safresh1# or truncate 14491f110e0Safresh1my $n = "for_fold_dot_t$$"; 14591f110e0Safresh1open F, ">$n" or die "open: $!"; 14691f110e0Safresh1print F "bralh blah blah \n"; 14791f110e0Safresh1close F or die "close $!"; 14891f110e0Safresh1eval "truncate 1 ? $n : 0, 0;"; 14991f110e0Safresh1print "not " unless -z $n; 15091f110e0Safresh1print "ok ", ++$test, " - truncate(const ? word : ...)\n"; 15191f110e0Safresh1unlink $n; 1526fb12b70Safresh1 1536fb12b70Safresh1# Constant folding should not change the mutability of returned values. 1546fb12b70Safresh1for(1+2) { 1556fb12b70Safresh1 eval { $_++ }; 1566fb12b70Safresh1 print "not " unless $_ eq 4; 1576fb12b70Safresh1 print "ok ", ++$test, 1586fb12b70Safresh1 " - 1+2 returns mutable value, just like \$a+\$b", 1596fb12b70Safresh1 "\n"; 1606fb12b70Safresh1} 1616fb12b70Safresh1 1626fb12b70Safresh1# [perl #119055] 1636fb12b70Safresh1# We hide the implementation detail that qq "foo" is implemented using 1646fb12b70Safresh1# constant folding. 1656fb12b70Safresh1eval { ${\"hello\n"}++ }; 1666fb12b70Safresh1print "not " unless $@ =~ "Modification of a read-only value attempted at"; 1676fb12b70Safresh1print "ok ", ++$test, " - qq with no vars is a constant\n"; 1686fb12b70Safresh1 1696fb12b70Safresh1# [perl #119501] 1706fb12b70Safresh1my @values; 1716fb12b70Safresh1for (1,2) { for (\(1+3)) { push @values, $$_; $$_++ } } 1726fb12b70Safresh1is "@values", "4 4", 1736fb12b70Safresh1 '\1+3 folding making modification affect future retvals'; 174b8851fccSafresh1 175b8851fccSafresh1{ 176b8851fccSafresh1 BEGIN { $^W = 0; $::{u} = \undef } 177b8851fccSafresh1 my $w; 178b8851fccSafresh1 local $SIG{__WARN__} = sub { ++$w }; 179b8851fccSafresh1 () = 1 + u; 180b8851fccSafresh1 is $w, 1, '1+undef_constant is not folded outside warninsg scope'; 181b8851fccSafresh1 BEGIN { $^W = 1 } 182b8851fccSafresh1} 183*9f11ffb7Safresh1 184*9f11ffb7Safresh1$a = eval 'my @z; @z = 0..~0 if 0; 3'; 185*9f11ffb7Safresh1is ($a, 3, "list constant folding doesn't signal compile-time error"); 186*9f11ffb7Safresh1is ($@, '', 'no error'); 187*9f11ffb7Safresh1 188*9f11ffb7Safresh1$b = 0; 189*9f11ffb7Safresh1$a = eval 'my @z; @z = 0..~0 if $b; 3'; 190*9f11ffb7Safresh1is ($a, 3, "list constant folding doesn't signal compile-time error"); 191*9f11ffb7Safresh1is ($@, '', 'no error'); 192*9f11ffb7Safresh1 193*9f11ffb7Safresh1$a = eval 'local $SIG{__WARN__} = sub {}; join("", ":".."~", "z")'; 194*9f11ffb7Safresh1is ($a, ":z", "aborted list constant folding still executable"); 195