In perl.git, the branch blead has been updated <https://perl5.git.perl.org/perl.git/commitdiff/a01f4640266aacbed7ecc9df01890abb555c69b2?hp=436908e565f0e613465123e7cb08fa54487c3b8f>
- Log ----------------------------------------------------------------- commit a01f4640266aacbed7ecc9df01890abb555c69b2 Author: Father Chrysostomos <spr...@cpan.org> Date: Sun Dec 10 07:07:07 2017 -0800 [perl #74764] Forbid ‘goto’ jumping into ‘given’ It does not make sense to jump into a ‘given’ any more than it makes sense to jump into ‘foreach’, which has long been forbidden, since there is no value to turn into a topic. Up till now this construct has always crashed. commit e7afb05e35570e271ae017d47b64dd5aad3e2009 Author: Father Chrysostomos <spr...@cpan.org> Date: Wed Dec 6 13:55:26 2017 -0800 Explicitly test goto-into-foreach It is already tested in t/op/goto.t, but only as part of an existing test to see which of multiple identical labels gets chosen. commit b537774295099f6b543a9e2b7375f72593328389 Author: Father Chrysostomos <spr...@cpan.org> Date: Wed Dec 6 13:44:32 2017 -0800 pp_ctl.c: Move goto-into-foreach error Put it in a static function, instead of repeating the code. This way I can add more conditions to that code in subsequent commits. ----------------------------------------------------------------------- Summary of changes: pod/perldelta.pod | 5 ++++- pod/perldiag.pod | 5 +++++ pod/perlfunc.pod | 3 ++- pp_ctl.c | 25 ++++++++++++++++++------- t/lib/croak/pp_ctl | 22 ++++++++++++++++++++++ 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 21c855a0c8..5cf9d5e3fc 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -212,7 +212,10 @@ and New Warnings =item * -XXX L<message|perldiag/"message"> +L<Can't "goto" into a "given" block|perldiag/"Can't E<quot>gotoE<quot> into a E<quot>givenE<quot> block"> + +(F) A "goto" statement was executed to jump into the middle of a C<given> +block. You can't get there from here. See L<perlfunc/goto>. =back diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 77726f54a1..d18baa8a39 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1031,6 +1031,11 @@ pipe, Perl can't retrieve its name for later use. (P) An error peculiar to VMS. Perl asked $GETSYI how big you want your mailbox buffers to be, and didn't get an answer. +=item Can't "goto" into a "given" block + +(F) A "goto" statement was executed to jump into the middle of a C<given> +block. You can't get there from here. See L<perlfunc/goto>. + =item Can't "goto" into the middle of a foreach loop (F) A "goto" statement was executed to jump into the middle of a foreach diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index 32f0e64f2c..8e3a9079b5 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -3400,7 +3400,8 @@ assignment. Use of C<goto LABEL> or C<goto EXPR> to jump into a construct is deprecated and will issue a warning. Even then, it may not be used to go into any construct that requires initialization, such as a -subroutine or a C<foreach> loop. It also can't be used to go into a +subroutine, a C<foreach> loop, or a C<given> +block. It also can't be used to go into a construct that is optimized away. The C<goto &NAME> form is quite different from the other forms of diff --git a/pp_ctl.c b/pp_ctl.c index 4026d4d579..9ff2abecd3 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -2658,7 +2658,8 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac o->op_type == OP_SCOPE || o->op_type == OP_LEAVELOOP || o->op_type == OP_LEAVESUB || - o->op_type == OP_LEAVETRY) + o->op_type == OP_LEAVETRY || + o->op_type == OP_LEAVEGIVEN) { *ops++ = cUNOPo->op_first; if (ops >= oplimit) @@ -2709,6 +2710,20 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac } +static void +S_check_op_type(pTHX_ OP * const o) +{ + /* Eventually we may want to stack the needed arguments + * for each op. For now, we punt on the hard ones. */ + /* XXX This comment seems to me like wishful thinking. --sprout */ + if (o->op_type == OP_ENTERITER) + Perl_croak(aTHX_ + "Can't \"goto\" into the middle of a foreach loop"); + if (o->op_type == OP_ENTERGIVEN) + Perl_croak(aTHX_ + "Can't \"goto\" into a \"given\" block"); +} + /* also used for: pp_dump() */ PP(pp_goto) @@ -3050,8 +3065,7 @@ PP(pp_goto) if (leaving_eval && *enterops && enterops[1]) { I32 i; for (i = 1; enterops[i]; i++) - if (enterops[i]->op_type == OP_ENTERITER) - DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop"); + S_check_op_type(aTHX_ enterops[i]); } if (*enterops && enterops[1]) { @@ -3077,10 +3091,7 @@ PP(pp_goto) ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1; for (; enterops[ix]; ix++) { PL_op = enterops[ix]; - /* Eventually we may want to stack the needed arguments - * for each op. For now, we punt on the hard ones. */ - if (PL_op->op_type == OP_ENTERITER) - DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop"); + S_check_op_type(aTHX_ PL_op); PL_op->op_ppaddr(aTHX); } PL_op = oldop; diff --git a/t/lib/croak/pp_ctl b/t/lib/croak/pp_ctl index ec664138e0..2943bf7551 100644 --- a/t/lib/croak/pp_ctl +++ b/t/lib/croak/pp_ctl @@ -1,4 +1,26 @@ __END__ +# NAME goto into foreach +no warnings 'deprecated'; +goto f; +foreach(1){f:} +EXPECT +Can't "goto" into the middle of a foreach loop at - line 3. +######## +# NAME goto into given +no warnings 'deprecated'; +goto f; +CORE::given(1){f:} +EXPECT +given is experimental at - line 3. +Can't "goto" into a "given" block at - line 3. +######## +# NAME goto from given topic expression +no warnings 'deprecated'; +CORE::given(goto f){f:} +EXPECT +given is experimental at - line 2. +Can't "goto" into a "given" block at - line 2. +######## # NAME dump with computed label no warnings 'deprecated'; my $label = "foo"; -- Perl5 Master Repository