xref: /openbsd/gnu/usr.bin/perl/t/op/goto.t (revision 3bef86f7)
1#!./perl
2
3# "This IS structured code.  It's just randomly structured."
4
5BEGIN {
6    chdir 't' if -d 't';
7    require "./test.pl";
8    set_up_inc( qw(. ../lib) );
9	require './charset_tools.pl';
10}
11
12use warnings;
13use strict;
14plan tests => 125;
15our $TODO;
16
17my $deprecated = 0;
18local $SIG{__WARN__} = sub { if ($_[0] =~ m/jump into a construct/) { $deprecated++; } else { warn $_[0] } };
19
20our $foo;
21while ($?) {
22    $foo = 1;
23  label1:
24    is($deprecated, 1, "following label1");
25    $deprecated = 0;
26    $foo = 2;
27    goto label2;
28} continue {
29    $foo = 0;
30    goto label4;
31  label3:
32    is($deprecated, 1, "following label3");
33    $deprecated = 0;
34    $foo = 4;
35    goto label4;
36}
37is($deprecated, 0, "after 'while' loop");
38goto label1;
39
40$foo = 3;
41
42label2:
43is($foo, 2, 'escape while loop');
44is($deprecated, 0, "following label2");
45goto label3;
46
47label4:
48is($foo, 4, 'second escape while loop');
49
50my $r = run_perl(prog => 'goto foo;', stderr => 1);
51like($r, qr/label/, 'cant find label');
52
53my $ok = 0;
54sub foo {
55    goto bar;
56    return;
57bar:
58    $ok = 1;
59}
60
61&foo;
62ok($ok, 'goto in sub');
63
64sub bar {
65    my $x = 'bypass';
66    eval "goto $x";
67}
68
69&bar;
70exit;
71
72FINALE:
73is(curr_test(), 20, 'FINALE');
74
75# does goto LABEL handle block contexts correctly?
76# note that this scope-hopping differs from last & next,
77# which always go up-scope strictly.
78my $count = 0;
79my $cond = 1;
80for (1) {
81    if ($cond == 1) {
82	$cond = 0;
83	goto OTHER;
84    }
85    elsif ($cond == 0) {
86      OTHER:
87	$cond = 2;
88	is($count, 0, 'OTHER');
89	$count++;
90	goto THIRD;
91    }
92    else {
93      THIRD:
94	is($count, 1, 'THIRD');
95	$count++;
96    }
97}
98is($count, 2, 'end of loop');
99
100# Does goto work correctly within a for(;;) loop?
101#  (BUG ID 20010309.004 (#5998))
102
103for(my $i=0;!$i++;) {
104  my $x=1;
105  goto label;
106  label: is($x, 1, 'goto inside a for(;;) loop body from inside the body');
107}
108
109# Does goto work correctly going *to* a for(;;) loop?
110#  (make sure it doesn't skip the initializer)
111
112my ($z, $y) = (0);
113FORL1: for ($y=1; $z;) {
114    ok($y, 'goto a for(;;) loop, from outside (does initializer)');
115    goto TEST19}
116($y,$z) = (0, 1);
117goto FORL1;
118
119# Even from within the loop?
120TEST19: $z = 0;
121FORL2: for($y=1; 1;) {
122  if ($z) {
123    ok($y, 'goto a for(;;) loop, from inside (does initializer)');
124    last;
125  }
126  ($y, $z) = (0, 1);
127  goto FORL2;
128}
129
130# Does goto work correctly within a try block?
131#  (BUG ID 20000313.004) - [perl #2359]
132$ok = 0;
133eval {
134  my $variable = 1;
135  goto LABEL20;
136  LABEL20: $ok = 1 if $variable;
137};
138ok($ok, 'works correctly within a try block');
139is($@, "", '...and $@ not set');
140
141# And within an eval-string?
142$ok = 0;
143eval q{
144  my $variable = 1;
145  goto LABEL21;
146  LABEL21: $ok = 1 if $variable;
147};
148ok($ok, 'works correctly within an eval string');
149is($@, "", '...and $@ still not set');
150
151
152# Test that goto works in nested eval-string
153$ok = 0;
154{eval q{
155  eval q{
156    goto LABEL22;
157  };
158  $ok = 0;
159  last;
160
161  LABEL22: $ok = 1;
162};
163$ok = 0 if $@;
164}
165ok($ok, 'works correctly in a nested eval string');
166
167{
168    my $false = 0;
169    my $count;
170
171    $ok = 0;
172    { goto A; A: $ok = 1 } continue { }
173    ok($ok, '#20357 goto inside /{ } continue { }/ loop');
174
175    $ok = 0;
176    { do { goto A; A: $ok = 1 } while $false }
177    ok($ok, '#20154 goto inside /do { } while ()/ loop');
178    $ok = 0;
179    foreach(1) { goto A; A: $ok = 1 } continue { };
180    ok($ok, 'goto inside /foreach () { } continue { }/ loop');
181
182    $ok = 0;
183    sub a {
184	A: { if ($false) { redo A; B: $ok = 1; redo A; } }
185	goto B unless $count++;
186    }
187    is($deprecated, 0, "before calling sub a()");
188    a();
189    ok($ok, '#19061 loop label wiped away by goto');
190    is($deprecated, 1, "after calling sub a()");
191    $deprecated = 0;
192
193    $ok = 0;
194    my $p;
195    for ($p=1;$p && goto A;$p=0) { A: $ok = 1 }
196    ok($ok, 'weird case of goto and for(;;) loop');
197    is($deprecated, 1, "following goto and for(;;) loop");
198    $deprecated = 0;
199}
200
201# bug #9990 - don't prematurely free the CV we're &going to.
202
203sub f1 {
204    my $x;
205    goto sub { $x=0; ok(1,"don't prematurely free CV\n") }
206}
207f1();
208
209# bug #99850, which is similar - freeing the subroutine we are about to
210# go(in)to during a FREETMPS call should not crash perl.
211
212package _99850 {
213    sub reftype{}
214    DESTROY { undef &reftype }
215    eval { sub { my $guard = bless []; goto &reftype }->() };
216}
217like $@, qr/^Goto undefined subroutine &_99850::reftype at /,
218   'goto &foo undefining &foo on sub cleanup';
219
220# When croaking after discovering that the new CV you're about to goto is
221# undef, make sure that the old CV isn't doubly freed.
222
223package Do_undef {
224    my $count;
225
226    # creating a new closure here encourages any prematurely freed
227    # CV to be reallocated
228    sub DESTROY { undef &undef_sub; my $x = sub { $count } }
229
230    sub f {
231        $count++;
232        my $guard = bless []; # trigger DESTROY during goto
233        *undef_sub = sub {};
234        goto &undef_sub
235    }
236
237    for (1..10) {
238        eval { f() };
239    }
240    ::is($count, 10, "goto undef_sub safe");
241}
242
243# make sure that nothing nasty happens if the old CV is freed while
244# goto'ing
245
246package Free_cv {
247    my $results;
248    sub f {
249        no warnings 'redefine';
250        *f = sub {};
251        goto &g;
252    }
253    sub g { $results = "(@_)" }
254
255    f(1,2,3);
256    ::is($results, "(1 2 3)", "Free_cv");
257}
258
259
260# bug #22181 - this used to coredump or make $x undefined, due to
261# erroneous popping of the inner BLOCK context
262
263undef $ok;
264for ($count=0; $count<2; $count++) {
265    my $x = 1;
266    goto LABEL29;
267    LABEL29:
268    $ok = $x;
269}
270is($ok, 1, 'goto in for(;;) with continuation');
271
272# bug #22299 - goto in require doesn't find label
273
274open my $f, ">Op_goto01.pm" or die;
275print $f <<'EOT';
276package goto01;
277goto YYY;
278die;
279YYY: print "OK\n";
2801;
281EOT
282close $f;
283
284$r = runperl(prog => 'BEGIN { unshift @INC, q[.] } use Op_goto01; print qq[DONE\n]');
285is($r, "OK\nDONE\n", "goto within use-d file");
286unlink_all "Op_goto01.pm";
287
288# test for [perl #24108]
289$ok = 1;
290$count = 0;
291sub i_return_a_label {
292    $count++;
293    return "returned_label";
294}
295eval { goto +i_return_a_label; };
296$ok = 0;
297
298returned_label:
299is($count, 1, 'called i_return_a_label');
300ok($ok, 'skipped to returned_label');
301
302# [perl #29708] - goto &foo could leave foo() at depth two with
303# @_ == PL_sv_undef, causing a coredump
304
305
306$r = runperl(
307    prog =>
308	'sub f { return if $d; $d=1; my $a=sub {goto &f}; &$a; f() } f(); print qq(ok\n)',
309    stderr => 1
310    );
311is($r, "ok\n", 'avoid pad without an @_');
312
313goto moretests;
314fail('goto moretests');
315exit;
316
317bypass:
318
319is(curr_test(), 9, 'eval "goto $x"');
320
321# Test autoloading mechanism.
322
323sub two {
324    my ($pack, $file, $line) = caller;	# Should indicate original call stats.
325    is("@_ $pack $file $line", "1 2 3 main $::FILE $::LINE",
326	'autoloading mechanism.');
327}
328
329sub one {
330    eval <<'END';
331    no warnings 'redefine';
332    sub one { pass('sub one'); goto &two; fail('sub one tail'); }
333END
334    goto &one;
335}
336
337$::FILE = __FILE__;
338$::LINE = __LINE__ + 1;
339&one(1,2,3);
340
341{
342    my $wherever = 'NOWHERE';
343    eval { goto $wherever };
344    like($@, qr/Can't find label NOWHERE/, 'goto NOWHERE sets $@');
345}
346
347# see if a modified @_ propagates
348{
349  my $i;
350  package Foo;
351  sub DESTROY	{ my $s = shift; ::is($s->[0], $i, "destroy $i"); }
352  sub show	{ ::is(+@_, 5, "show $i",); }
353  sub start	{ push @_, 1, "foo", {}; goto &show; }
354  for (1..3)	{ $i = $_; start(bless([$_]), 'bar'); }
355}
356
357sub auto {
358    goto &loadit;
359}
360
361sub AUTOLOAD { $ok = 1 if "@_" eq "foo" }
362
363$ok = 0;
364auto("foo");
365ok($ok, 'autoload');
366
367{
368    my $wherever = 'FINALE';
369    goto $wherever;
370}
371fail('goto $wherever');
372
373moretests:
374# test goto duplicated labels.
375{
376    my $z = 0;
377    eval {
378	$z = 0;
379	for (0..1) {
380	  L4: # not outer scope
381	    $z += 10;
382	    last;
383	}
384	goto L4 if $z == 10;
385	last;
386    };
387    like($@, qr/Can't "goto" into the middle of a foreach loop/,
388	    'catch goto middle of foreach');
389
390    $z = 0;
391    # ambiguous label resolution (outer scope means endless loop!)
392  L1:
393    for my $x (0..1) {
394	$z += 10;
395	is($z, 10, 'prefer same scope (loop body) to outer scope (loop entry)');
396	goto L1 unless $x;
397	$z += 10;
398      L1:
399	is($z, 10, 'prefer same scope: second');
400	last;
401    }
402
403    $z = 0;
404  L2:
405    {
406	$z += 10;
407	is($z, 10, 'prefer this scope (block body) to outer scope (block entry)');
408	goto L2 if $z == 10;
409	$z += 10;
410      L2:
411	is($z, 10, 'prefer this scope: second');
412    }
413
414
415    {
416	$z = 0;
417	while (1) {
418	  L3: # not inner scope
419	    $z += 10;
420	    last;
421	}
422	is($z, 10, 'prefer this scope to inner scope');
423	goto L3 if $z == 10;
424	$z += 10;
425      L3: # this scope !
426	is($z, 10, 'prefer this scope to inner scope: second');
427    }
428
429  L4: # not outer scope
430    {
431	$z = 0;
432	while (1) {
433	  L4: # not inner scope
434	    $z += 1;
435	    last;
436	}
437	is($z, 1, 'prefer this scope to inner,outer scopes');
438	goto L4 if $z == 1;
439	$z += 10;
440      L4: # this scope !
441	is($z, 1, 'prefer this scope to inner,outer scopes: second');
442    }
443
444    {
445	my $loop = 0;
446	for my $x (0..1) {
447	  L2: # without this, fails 1 (middle) out of 3 iterations
448	    $z = 0;
449	  L2:
450	    $z += 10;
451	    is($z, 10,
452		"same label, multiple times in same scope (choose 1st) $loop");
453	    goto L2 if $z == 10 and not $loop++;
454	}
455    }
456}
457
458# This bug was introduced in Aug 2010 by commit ac56e7de46621c6f
459# Peephole optimise adjacent pairs of nextstate ops.
460# and fixed in Oct 2014 by commit f5b5c2a37af87535
461# Simplify double-nextstate optimisation
462
463# The bug manifests as a warning
464# Use of "goto" to jump into a construct is deprecated at t/op/goto.t line 442.
465# and $out is undefined. Devel::Peek reveals that the lexical in the pad has
466# been reset to undef. I infer that pp_goto thinks that it's leaving one scope
467# and entering another, but I don't know *why* it thinks that. Whilst this bug
468# has been fixed by Father C, because I don't understand why it happened, I am
469# not confident that other related bugs remain (or have always existed).
470
471sub DEBUG_TIME() {
472    0;
473}
474
475{
476    if (DEBUG_TIME) {
477    }
478
479    {
480        my $out = "";
481        $out .= 'perl rules';
482        goto no_list;
483    no_list:
484        is($out, 'perl rules', '$out has not been erroneously reset to undef');
485    };
486}
487
488is($deprecated, 0, 'no warning was emmitted');
489
490# deep recursion with gotos eventually caused a stack reallocation
491# which messed up buggy internals that didn't expect the stack to move
492
493sub recurse1 {
494    unshift @_, "x";
495    no warnings 'recursion';
496    goto &recurse2;
497}
498sub recurse2 {
499    my $x = shift;
500    $_[0] ? +1 + recurse1($_[0] - 1) : 0
501}
502my $w = 0;
503$SIG{__WARN__} = sub { ++$w };
504is(recurse1(500), 500, 'recursive goto &foo');
505is $w, 0, 'no recursion warnings for "no warnings; goto &sub"';
506delete $SIG{__WARN__};
507
508# [perl #32039] Chained goto &sub drops data too early.
509
510sub a32039 { @_=("foo"); goto &b32039; }
511sub b32039 { goto &c32039; }
512sub c32039 { is($_[0], 'foo', 'chained &goto') }
513a32039();
514
515# [perl #35214] next and redo re-entered the loop with the wrong cop,
516# causing a subsequent goto to crash
517
518{
519    my $r = runperl(
520		stderr => 1,
521		prog =>
522'for ($_=0;$_<3;$_++){A: if($_==1){next} if($_==2){$_++;goto A}}print qq(ok\n)'
523    );
524    is($r, "ok\n", 'next and goto');
525
526    $r = runperl(
527		stderr => 1,
528		prog =>
529'for ($_=0;$_<3;$_++){A: if($_==1){$_++;redo} if($_==2){$_++;goto A}}print qq(ok\n)'
530    );
531    is($r, "ok\n", 'redo and goto');
532}
533
534# goto &foo not allowed in evals
535
536sub null { 1 };
537eval 'goto &null';
538like($@, qr/Can't goto subroutine from an eval-string/, 'eval string');
539eval { goto &null };
540like($@, qr/Can't goto subroutine from an eval-block/, 'eval block');
541
542# goto &foo leaves @_ alone when called from a sub
543sub returnarg { $_[0] };
544is sub {
545    local *_ = ["ick and queasy"];
546    goto &returnarg;
547}->("quick and easy"), "ick and queasy",
548  'goto &foo with *_{ARRAY} replaced';
549my @__ = byte_utf8a_to_utf8n("\xc4\x80");
550sub { local *_ = \@__; goto &utf8::decode }->("no thinking aloud");
551is "@__", chr 256, 'goto &xsub with replaced *_{ARRAY}';
552
553# And goto &foo should leave reified @_ alone
554sub { *__ = \@_;  goto &null } -> ("rough and tubbery");
555is ${*__}[0], 'rough and tubbery', 'goto &foo leaves reified @_ alone';
556
557# goto &xsub when @_ has nonexistent elements
558{
559    no warnings "uninitialized";
560    local @_ = ();
561    $#_++;
562    & {sub { goto &utf8::encode }};
563    is @_, 1, 'num of elems in @_ after goto &xsub with nonexistent $_[0]';
564    is $_[0], "", 'content of nonexistent $_[0] is modified by goto &xsub';
565}
566
567# goto &xsub when @_ itself does not exist
568undef *_;
569eval { & { sub { goto &utf8::encode } } };
570# The main thing we are testing is that it did not crash.  But make sure
571# *_{ARRAY} was untouched, too.
572is *_{ARRAY}, undef, 'goto &xsub when @_ does not exist';
573
574# goto &perlsub when @_ itself does not exist [perl #119949]
575# This was only crashing when the replaced sub call had an argument list.
576# (I.e., &{ sub { goto ... } } did not crash.)
577sub {
578    undef *_;
579    goto sub {
580	is *_{ARRAY}, undef, 'goto &perlsub when @_ does not exist';
581    }
582}->();
583sub {
584    local *_;
585    goto sub {
586	is *_{ARRAY}, undef, 'goto &sub when @_ does not exist (local *_)';
587    }
588}->();
589
590
591# [perl #36521] goto &foo in warn handler could defeat recursion avoider
592
593{
594    my $r = runperl(
595		stderr => 1,
596		prog => 'my $d; my $w = sub { return if $d++; warn q(bar)}; local $SIG{__WARN__} = sub { goto &$w; }; warn q(foo);'
597    );
598    like($r, qr/bar/, "goto &foo in warn");
599}
600
601TODO: {
602    local $TODO = "[perl #43403] goto() from an if to an else doesn't undo local () changes";
603    our $global = "unmodified";
604    if ($global) { # true but not constant-folded
605         local $global = "modified";
606         goto ELSE;
607    } else {
608         ELSE: is($global, "unmodified");
609    }
610}
611
612is($deprecated, 0, "following TODOed test for #43403");
613
614#74290
615{
616    my $x;
617    my $y;
618    F1:++$x and eval 'return if ++$y == 10; goto F1;';
619    is($x, 10,
620       'labels outside evals can be distinguished from the start of the eval');
621}
622
623goto wham_eth;
624die "You can't get here";
625
626wham_eth: 1 if 0;
627ouch_eth: pass('labels persist even if their statement is optimised away');
628
629$foo = "(0)";
630if($foo eq $foo) {
631    goto bungo;
632}
633$foo .= "(9)";
634bungo:
635format CHOLET =
636wellington
637.
638$foo .= "(1)";
639SKIP: {
640    skip_if_miniperl("no dynamic loading on miniperl, so can't load PerlIO::scalar", 1);
641    my $cholet;
642    open(CHOLET, ">", \$cholet);
643    write CHOLET;
644    close CHOLET;
645    $foo .= "(".$cholet.")";
646    is($foo, "(0)(1)(wellington\n)", "label before format decl");
647}
648
649$foo = "(A)";
650if($foo eq $foo) {
651    goto orinoco;
652}
653$foo .= "(X)";
654orinoco:
655sub alderney { return "tobermory"; }
656$foo .= "(B)";
657$foo .= "(".alderney().")";
658is($foo, "(A)(B)(tobermory)", "label before sub decl");
659
660$foo = "[0:".__PACKAGE__."]";
661if($foo eq $foo) {
662    goto bulgaria;
663}
664$foo .= "[9]";
665bulgaria:
666package Tomsk;
667$foo .= "[1:".__PACKAGE__."]";
668$foo .= "[2:".__PACKAGE__."]";
669package main;
670$foo .= "[3:".__PACKAGE__."]";
671is($foo, "[0:main][1:Tomsk][2:Tomsk][3:main]", "label before package decl");
672
673$foo = "[A:".__PACKAGE__."]";
674if($foo eq $foo) {
675    goto adelaide;
676}
677$foo .= "[Z]";
678adelaide:
679package Cairngorm {
680    $foo .= "[B:".__PACKAGE__."]";
681}
682$foo .= "[C:".__PACKAGE__."]";
683is($foo, "[A:main][B:Cairngorm][C:main]", "label before package block");
684
685our $obidos;
686$foo = "{0}";
687if($foo eq $foo) {
688    goto shansi;
689}
690$foo .= "{9}";
691shansi:
692BEGIN { $obidos = "x"; }
693$foo .= "{1$obidos}";
694is($foo, "{0}{1x}", "label before BEGIN block");
695
696$foo = "{A:".(1.5+1.5)."}";
697if($foo eq $foo) {
698    goto stepney;
699}
700$foo .= "{Z}";
701stepney:
702use integer;
703$foo .= "{B:".(1.5+1.5)."}";
704is($foo, "{A:3}{B:2}", "label before use decl");
705
706$foo = "<0>";
707if($foo eq $foo) {
708    goto tom;
709}
710$foo .= "<9>";
711tom: dick: harry:
712$foo .= "<1>";
713$foo .= "<2>";
714is($foo, "<0><1><2>", "first of three stacked labels");
715
716$foo = "<A>";
717if($foo eq $foo) {
718    goto beta;
719}
720$foo .= "<Z>";
721alpha: beta: gamma:
722$foo .= "<B>";
723$foo .= "<C>";
724is($foo, "<A><B><C>", "second of three stacked labels");
725
726$foo = ",0.";
727if($foo eq $foo) {
728    goto gimel;
729}
730$foo .= ",9.";
731alef: bet: gimel:
732$foo .= ",1.";
733$foo .= ",2.";
734is($foo, ",0.,1.,2.", "third of three stacked labels");
735
736# [perl #112316] Wrong behavior regarding labels with same prefix
737sub same_prefix_labels {
738    my $pass;
739    my $first_time = 1;
740    CATCH: {
741        if ( $first_time ) {
742            CATCHLOOP: {
743                if ( !$first_time ) {
744                  return 0;
745                }
746                $first_time--;
747                goto CATCH;
748            }
749        }
750        else {
751            return 1;
752        }
753    }
754}
755
756ok(
757   same_prefix_labels(),
758   "perl 112316: goto and labels with the same prefix doesn't get mixed up"
759);
760
761eval { my $x = ""; goto $x };
762like $@, qr/^goto must have label at /, 'goto $x where $x is empty string';
763eval { goto "" };
764like $@, qr/^goto must have label at /, 'goto ""';
765eval { goto };
766like $@, qr/^goto must have label at /, 'argless goto';
767
768eval { my $x = "\0"; goto $x };
769like $@, qr/^Can't find label \0 at /, 'goto $x where $x begins with \0';
770eval { goto "\0" };
771like $@, qr/^Can't find label \0 at /, 'goto "\0"';
772
773sub TIESCALAR { bless [pop] }
774sub FETCH     { $_[0][0] }
775tie my $t, "", sub { "cluck up porridge" };
776is eval { sub { goto $t }->() }//$@, 'cluck up porridge',
777  'tied arg returning sub ref';
778
779TODO: {
780  local $::TODO = 'RT #45091: goto in CORE::GLOBAL::exit unsupported';
781  fresh_perl_is(<<'EOC', "before\ndie handler\n", {stderr => 1}, 'RT #45091: goto in CORE::GLOBAL::EXIT');
782  BEGIN {
783    *CORE::GLOBAL::exit = sub {
784      goto FASTCGI_NEXT_REQUEST;
785    };
786  }
787  while (1) {
788    eval { that_cgi_script() };
789    FASTCGI_NEXT_REQUEST:
790    last;
791  }
792
793  sub that_cgi_script {
794    local $SIG{__DIE__} = sub { print "die handler\n"; exit; print "exit failed?\n"; };
795    print "before\n";
796    eval { buggy_code() };
797    print "after\n";
798  }
799  sub buggy_code {
800    die "error!";
801    print "after die\n";
802  }
803EOC
804}
805
806sub revnumcmp ($$) {
807  goto FOO;
808  die;
809  FOO:
810  return $_[1] <=> $_[0];
811}
812is eval { join(":", sort revnumcmp (9,5,1,3,7)) }, "9:7:5:3:1",
813  "can goto at top level of multicalled sub";
814
815# A bit strange, but goingto these constructs should not cause any stack
816# problems.  Let’s test them to make sure that is the case.
817no warnings 'deprecated';
818is \sub :lvalue { goto d; ${*{scalar(do { d: \*foo })}} }->(), \$foo,
819   'goto into rv2sv, rv2gv and scalar';
820is sub { goto e; $#{; do { e: \@_ } } }->(1..7), 6,
821   'goto into $#{...}';
822is sub { goto f; prototype \&{; do { f: sub ($) {} } } }->(), '$',
823   'goto into srefgen, prototype and rv2cv';
824is sub { goto g; ref do { g: [] } }->(), 'ARRAY',
825   'goto into ref';
826is sub { goto j; defined undef ${; do { j: \(my $foo = "foo") } } }->(),'',
827   'goto into defined and undef';
828is sub { goto k; study ++${; do { k: \(my $foo = "foo") } } }->(),'1',
829   'goto into study and preincrement';
830is sub { goto l; ~-!${; do { l: \(my $foo = 0) } }++ }->(),~-1,
831   'goto into complement, not, negation and postincrement';
832like sub { goto n; sin cos exp log sqrt do { n: 1 } }->(),qr/^0\.51439/,
833   'goto into sin, cos, exp, log, and sqrt';
834ok sub { goto o; srand do { o: 0 } }->(),
835   'goto into srand';
836cmp_ok sub { goto p; rand do { p: 1 } }->(), '<', 1,
837   'goto into rand';
838is sub { goto r; chr ord length int hex oct abs do { r: -15.5 } }->(), 2,
839   'goto into chr, ord, length, int, hex, oct and abs';
840is sub { goto t; ucfirst lcfirst uc lc do { t: "q" } }->(), 'Q',
841   'goto into ucfirst, lcfirst, uc and lc';
842{ no strict;
843  is sub { goto u; \@{; quotemeta do { u: "." } } }->(), \@{'\.'},
844   'goto into rv2av and quotemeta';
845}
846is join(" ",sub { goto v; %{; do { v: +{1..2} } } }->()), '1 2',
847   'goto into rv2hv';
848is join(" ",sub { goto w; $_ || do { w: "w" } }->()), 'w',
849   'goto into rhs of or';
850is join(" ",sub { goto x; $_ && do { x: "w" } }->()), 'w',
851   'goto into rhs of and';
852is join(" ",sub { goto z; $_ ? do { z: "w" } : 0 }->()), 'w',
853   'goto into first leg of ?:';
854is join(" ",sub { goto z; $_ ? 0 : do { z: "w" } }->()), 'w',
855   'goto into second leg of ?:';
856is sub { goto z; caller do { z: 0 } }->(), 'main',
857   'goto into caller';
858is sub { goto z; exit do { z: return "foo" } }->(), 'foo',
859   'goto into exit';
860is sub { goto z; eval do { z: "'foo'" } }->(), 'foo',
861   'goto into eval';
862TODO: {
863    local $TODO = "glob() does not currently return a list on VMS" if $^O eq 'VMS';
864    is join(",",sub { goto z; glob do { z: "foo bar" } }->()), 'foo,bar',
865       'goto into glob';
866}
867# [perl #132799]
868# Erroneous inward goto warning, followed by crash.
869# The eval must be in an assignment.
870sub _routine {
871    my $e = eval {
872        goto L2;
873      L2:
874    }
875}
876_routine();
877pass("bug 132799");
878
879# [perl #132854]
880# Goto the *first* parameter of a binary expression, which is harmless.
881eval {
882    goto __GEN_2;
883    my $sent = do {
884        __GEN_2:
885    };
886};
887is $@,'', 'goto the first parameter of a binary expression [perl #132854]';
888
889# v5.31.3-198-gd2cd363728 broke this. goto &XS_sub  wasn't restoring
890# cx->blk_sub.old_cxsubix. Would panic in pp_return
891
892{
893    # isa is an XS sub
894    sub g198 {  goto &UNIVERSAL::isa }
895
896    sub f198 {
897        g198([], 1 );
898        {
899            return 1;
900        }
901    }
902    eval { f198(); };
903    is $@, "", "v5.31.3-198-gd2cd363728";
904}
905