4 # Original written by Ulrich Pfeifer on 2 Jan 1997.
5 # Greatly extended by Tom Phoenix <rootbeer@teleport.com> on 28 Jan 1997.
7 # Run with -debug for debugging output.
15 require './test.pl'; # for runperl()
20 print $ok ? "ok $test\n" : "not ok $test\n";
21 printf "# Failed at line %d\n", (caller)[2] unless $ok;
26 sub foo { $i = shift if @_; $i }
33 # closure: lexical outside sub
34 my $foo = sub {$i = shift if @_; $i };
35 my $bar = sub {$i = shift if @_; $i };
39 # did the lexical change?
40 test { foo == 3 and $i == 3};
41 # did the second closure notice?
44 # closure: lexical inside sub
47 sub { $i = shift if @_; $i }
62 sub {$i = shift if @_; $i };
65 sub {$i = shift if @_; $i };
77 test {&$foo(11)-1 == &$bar()};
82 $foo[$_] = sub {$i = shift if @_; $i };
100 &{$foo[2]}() == 2 and
101 &{$foo[3]}() == 1 and
107 for (qw(0 1 2 3 4)) {
109 $foo[$_] = sub {$i = shift if @_; $i };
116 &{$foo[0]}() == 0 and
117 &{$foo[1]}() == 1 and
118 &{$foo[2]}() == 2 and
119 &{$foo[3]}() == 3 and
128 &{$foo[0]}() == 4 and
129 &{$foo[1]}() == 3 and
130 &{$foo[2]}() == 2 and
131 &{$foo[3]}() == 1 and
135 # test if closures get created in optimized for loops
138 for my $n ('A'..'E') {
139 $foo{$n} = sub { $n eq $_[0] };
151 $foo[$n] = sub { $n == $_[0] };
164 # no intervening reference to $n here
189 # Additional tests by Tom Phoenix <rootbeer@teleport.com>.
195 my($debugging, %expected, $inner_type, $where_declared, $within);
196 my($nc_attempt, $call_outer, $call_inner, $undef_outer);
197 my($code, $inner_sub_test, $expected, $line, $errors, $output);
198 my(@inners, $sub_test, $pid);
199 $debugging = 1 if defined($ARGV[0]) and $ARGV[0] eq '-debug';
201 # The expected values for these tests
203 'global_scalar' => 1001,
204 'global_array' => 2101,
205 'global_hash' => 3004,
209 'sub_scalar' => 7001,
215 # Our innermost sub is either named or anonymous
216 for $inner_type (qw!named anon!) {
217 # And it may be declared at filescope, within a named
218 # sub, or within an anon sub
219 for $where_declared (qw!filescope in_named in_anon!) {
220 # And that, in turn, may be within a foreach loop,
221 # a naked block, or another named sub
222 for $within (qw!foreach naked other_sub!) {
224 my $test = curr_test();
225 # Here are a number of variables which show what's
226 # going on, in a way.
227 $nc_attempt = 0+ # Named closure attempted
228 ( ($inner_type eq 'named') ||
229 ($within eq 'other_sub') ) ;
230 $call_inner = 0+ # Need to call &inner
231 ( ($inner_type eq 'anon') &&
232 ($within eq 'other_sub') ) ;
233 $call_outer = 0+ # Need to call &outer or &$outer
234 ( ($inner_type eq 'anon') &&
235 ($within ne 'other_sub') ) ;
236 $undef_outer = 0+ # $outer is created but unused
237 ( ($where_declared eq 'in_anon') &&
238 (not $call_outer) ) ;
240 $code = "# This is a test script built by t/op/closure.t\n\n";
242 print <<"DEBUG_INFO" if $debugging;
243 # inner_type: $inner_type
244 # where_declared: $where_declared
246 # nc_attempt: $nc_attempt
247 # call_inner: $call_inner
248 # call_outer: $call_outer
249 # undef_outer: $undef_outer
252 $code .= <<"END_MARK_ONE";
254 BEGIN { \$SIG{__WARN__} = sub {
258 $code .= <<"END_MARK_TWO" if $nc_attempt;
259 return if index(\$msg, 'will not stay shared') != -1;
260 return if index(\$msg, 'is not available') != -1;
263 $code .= <<"END_MARK_THREE"; # Backwhack a lot!
264 print "not ok: got unexpected warning \$msg\\n";
270 # some of the variables which the closure will access
271 \$global_scalar = 1000;
272 \@global_array = (2000, 2100, 2200, 2300);
273 %global_hash = 3000..3009;
275 my \$fs_scalar = 4000;
276 my \@fs_array = (5000, 5100, 5200, 5300);
277 my %fs_hash = 6000..6009;
281 if ($where_declared eq 'filescope') {
283 } elsif ($where_declared eq 'in_named') {
286 my $sub_scalar = 7000;
287 my @sub_array = (8000, 8100, 8200, 8300);
288 my %sub_hash = 9000..9009;
291 } elsif ($where_declared eq 'in_anon') {
294 my $sub_scalar = 7000;
295 my @sub_array = (8000, 8100, 8200, 8300);
296 my %sub_hash = 9000..9009;
300 die "What was $where_declared?"
303 if ($within eq 'foreach') {
305 my \$foreach = 12000;
306 my \@list = (10000, 10010);
307 foreach \$foreach (\@list) {
309 } elsif ($within eq 'naked') {
310 $code .= " { # naked block\n" # }
311 } elsif ($within eq 'other_sub') {
312 $code .= " sub inner_sub {\n" # }
314 die "What was $within?"
318 @inners = ( qw!global_scalar global_array global_hash! ,
319 qw!fs_scalar fs_array fs_hash! );
320 push @inners, 'foreach' if $within eq 'foreach';
321 if ($where_declared ne 'filescope') {
322 push @inners, qw!sub_scalar sub_array sub_hash!;
324 for $inner_sub_test (@inners) {
326 if ($inner_type eq 'named') {
327 $code .= " sub named_$sub_test "
328 } elsif ($inner_type eq 'anon') {
329 $code .= " \$anon_$sub_test = sub "
331 die "What was $inner_type?"
334 # Now to write the body of the test sub
335 if ($inner_sub_test eq 'global_scalar') {
336 $code .= '{ ++$global_scalar }'
337 } elsif ($inner_sub_test eq 'fs_scalar') {
338 $code .= '{ ++$fs_scalar }'
339 } elsif ($inner_sub_test eq 'sub_scalar') {
340 $code .= '{ ++$sub_scalar }'
341 } elsif ($inner_sub_test eq 'global_array') {
342 $code .= '{ ++$global_array[1] }'
343 } elsif ($inner_sub_test eq 'fs_array') {
344 $code .= '{ ++$fs_array[1] }'
345 } elsif ($inner_sub_test eq 'sub_array') {
346 $code .= '{ ++$sub_array[1] }'
347 } elsif ($inner_sub_test eq 'global_hash') {
348 $code .= '{ ++$global_hash{3002} }'
349 } elsif ($inner_sub_test eq 'fs_hash') {
350 $code .= '{ ++$fs_hash{6002} }'
351 } elsif ($inner_sub_test eq 'sub_hash') {
352 $code .= '{ ++$sub_hash{9002} }'
353 } elsif ($inner_sub_test eq 'foreach') {
354 $code .= '{ ++$foreach }'
356 die "What was $inner_sub_test?"
360 if ($inner_type eq 'anon') {
364 $sub_test++; # sub name sequence number
366 } # End of foreach $inner_sub_test
368 # Close up $within block # {
371 # Close up $where_declared block
372 if ($where_declared eq 'in_named') { # {
374 } elsif ($where_declared eq 'in_anon') { # {
378 # We may need to do something with the sub we just made...
379 $code .= "undef \$outer;\n" if $undef_outer;
380 $code .= "&inner_sub;\n" if $call_inner;
382 if ($where_declared eq 'in_named') {
383 $code .= "&outer;\n\n";
384 } elsif ($where_declared eq 'in_anon') {
385 $code .= "&\$outer;\n\n"
389 # Now, we can actually prep to run the tests.
390 for $inner_sub_test (@inners) {
391 $expected = $expected{$inner_sub_test} or
392 die "expected $inner_sub_test missing";
394 # Named closures won't access the expected vars
396 substr($inner_sub_test, 0, 4) eq "sub_" ) {
400 # If you make a sub within a foreach loop,
401 # what happens if it tries to access the
402 # foreach index variable? If it's a named
403 # sub, it gets the var from "outside" the loop,
404 # but if it's anon, it gets the value to which
405 # the index variable is aliased.
407 # Of course, if the value was set only
408 # within another sub which was never called,
409 # the value has not been set yet.
411 if ($inner_sub_test eq 'foreach') {
412 if ($inner_type eq 'named') {
413 if ($call_outer || ($where_declared eq 'filescope')) {
422 my $desc = "$inner_type $where_declared $within $inner_sub_test";
423 if ($inner_type eq 'anon') {
424 $code .= "is(&\$anon_$test, $expected, '$desc');\n"
426 $code .= "is(&named_$test, $expected, '$desc');\n"
431 if ($Config{d_fork} and $^O ne 'VMS' and $^O ne 'MSWin32' and $^O ne 'NetWare') {
432 # Fork off a new perl to run the tests.
433 # (This is so we can catch spurious warnings.)
434 $| = 1; print ""; $| = 0; # flush output before forking
435 pipe READ, WRITE or die "Can't make pipe: $!";
436 pipe READ2, WRITE2 or die "Can't make second pipe: $!";
437 die "Can't fork: $!" unless defined($pid = open PERL, "|-");
439 # Child process here. We're going to send errors back
440 # through the extra pipe.
443 open STDOUT, ">&WRITE" or die "Can't redirect STDOUT: $!";
444 open STDERR, ">&WRITE2" or die "Can't redirect STDERR: $!";
445 exec which_perl(), '-w', '-'
446 or die "Can't exec perl: $!";
448 # Parent process here.
454 $output = join '', <READ>;
455 $errors = join '', <READ2>; }
460 # No fork(). Do it the hard way.
461 my $cmdfile = tempfile();
462 my $errfile = tempfile();
463 open CMD, ">$cmdfile"; print CMD $code; close CMD;
464 my $cmd = which_perl();
465 $cmd .= " -w $cmdfile 2>$errfile";
466 if ($^O eq 'VMS' or $^O eq 'MSWin32' or $^O eq 'NetWare') {
467 # Use pipe instead of system so we don't inherit STD* from
468 # this process, and then foul our pipe back to parent by
469 # redirecting output in the child.
470 open PERL,"$cmd |" or die "Can't open pipe: $!\n";
471 { local $/; $output = join '', <PERL> }
474 my $outfile = tempfile();
475 system "$cmd >$outfile";
476 { local $/; open IN, $outfile; $output = <IN>; close IN }
479 printf "not ok: exited with error code %04X\n", $?;
482 { local $/; open IN, $errfile; $errors = <IN>; close IN }
486 print STDERR $errors;
487 # This has the side effect of alerting *our* test.pl to the state of
488 # what has just been passed to STDOUT, so that if anything there has
489 # failed, our test.pl will print a diagnostic and exit uncleanly.
490 unlike($output, qr/not ok/, 'All good');
491 is($errors, '', 'STDERR is silent');
492 if ($debugging && ($errors || $? || ($output =~ /not ok/))) {
494 for $line (split '\n', $code) {
495 printf "%3d: %s\n", ++$lnum, $line;
498 is($?, 0, 'exited cleanly') or diag(sprintf "Error code $? = 0x%X", $?);
499 print '#', "-" x 30, "\n" if $debugging;
501 } # End of foreach $within
502 } # End of foreach $where_declared
503 } # End of foreach $inner_type
507 # The following dumps core with perl <= 5.8.0 (bugid 9535) ...
508 BEGIN { $vanishing_pad = sub { eval $_[0] } }
510 is($vanishing_pad->('$some_var'), 123, 'RT #9535');
512 # ... and here's another coredump variant - this time we explicitly
513 # delete the sub rather than using a BEGIN ...
515 sub deleteme { $a = sub { eval '$newvar' } }
517 *deleteme = sub {}; # delete the sub
518 $newvar = 123; # realloc the SV of the freed CV
519 is($a->(), 123, 'RT #9535');
521 # ... and a further coredump variant - the fixup of the anon sub's
522 # CvOUTSIDE pointer when the middle eval is freed, wasn't good enough to
523 # survive the outer eval also being freed.
531 @a = ('\1\1\1\1\1\1\1') x 100; # realloc recently-freed CVs
532 is($a->(), 123, 'RT #9535');
534 # this coredumped on <= 5.8.0 because evaling the closure caused
535 # an SvFAKE to be added to the outer anon's pad, which was then grown.
539 $x = eval 'sub { $outer }';
546 # [perl #17605] found that an empty block called in scalar context
547 # can lead to stack corruption
551 is($x, 'fbar', 'RT #17605');
555 # SvFAKE lexicals should be visible thoughout a function.
556 # On <= 5.8.0, the third test failed, eg bugid #18286
561 is(sub {eval'$x'}->(), 1, 'RT #18286');
562 { $x; is(sub {eval'$x'}->(), 1, 'RT #18286'); }
563 is(sub {eval'$x'}->(), 1, 'RT #18286');
571 sub tmp { sub { eval '$x' } }
575 "undefining a sub shouldn't alter visibility of outer lexicals");
578 # handy class: $x = Watch->new(\$foo,'bar')
579 # causes 'bar' to be appended to $foo when $x is destroyed
580 sub Watch::new { bless [ $_[1], $_[2] ], $_[0] }
581 sub Watch::DESTROY { ${$_[0][0]} .= $_[0][1] }
584 # nested anon subs (and associated lexicals) not freed early enough
587 my $x = Watch->new($_[0], '2');
597 is($watch, '12', 'RT #1028');
601 # obj not freed early enough
604 my $obj = Watch->new($_[0], '2');
605 sub { sub { $obj } };
610 is($watch, 12, 'RT #10085');
613 # bugid 16302 - named subs didn't capture lexicals on behalf of inner subs
619 is($x, 1, 'RT #16302');
625 # The presence of an eval should turn cloneless anon subs into clonable
626 # subs - otherwise the CvOUTSIDE of that sub may be wrong
631 $a{$x} = sub { $x=$x; sub { eval '$x' } };
633 is($a{7}->()->() + $a{11}->()->(), 18);
637 # bugid #23265 - this used to coredump during destruction of PL_maincv
640 fresh_perl_is(<< '__EOF__', "yxx\n", {stderr => 1}, 'RT #23265');
642 sub {$_[0]->(@_)} -> (
645 ? $_[0]->($_[0], $_[1] - 1) . sub {"x"}->()
656 # bugid #24914 = used to coredump restoring PL_comppad in the
657 # savestack, due to the early freeing of the anon closure
659 fresh_perl_is('sub d {die} my $f; $f = sub {my $x=1; $f = 0; d}; eval{$f->()}; print qq(ok\n)',
660 "ok\n", {stderr => 1}, 'RT #24914');
664 # After newsub is redefined outside the BEGIN, its CvOUTSIDE should point
665 # to main rather than BEGIN, and BEGIN should be freed.
669 sub X::DESTROY { $flag = 1 }
672 BEGIN {$x = \&newsub }
692 "don't copy a stale lexical; crate a fresh undef one instead");
695 # [perl #63540] Don’t treat sub { if(){.....}; "constant" } as a constant
699 *baz = sub() { if($x){ () = "tralala"; blonk() }; 0 }
702 my $blonk_was_called;
703 *blonk = sub { ++$blonk_was_called };
705 is($ret, 0, 'RT #63540');
706 is($blonk_was_called, 1, 'RT #63540');