diff --git a/op.c b/op.c index 7027f18f036c..13ec73959b20 100644 --- a/op.c +++ b/op.c @@ -4141,7 +4141,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } else if (attrs) { GV * const gv = cGVOPx_gv(cUNOPo->op_first); assert(PL_parser); - PL_parser->in_my = FALSE; + PL_parser->in_my = KEY_NULL; PL_parser->in_my_stash = NULL; apply_attrs(GvSTASH(gv), (type == OP_RV2SV ? GvSVn(gv) : @@ -4174,7 +4174,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) HV *stash; assert(PL_parser); - PL_parser->in_my = FALSE; + PL_parser->in_my = KEY_NULL; PL_parser->in_my_stash = NULL; /* check for C when deciding package */ @@ -4232,7 +4232,7 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs) o = op_append_list(OP_LIST, o, rops); } } - PL_parser->in_my = FALSE; + PL_parser->in_my = KEY_NULL; PL_parser->in_my_stash = NULL; return o; } @@ -4857,7 +4857,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) o = my(o); else o = op_lvalue(o, OP_NULL); /* a bit kludgey */ - PL_parser->in_my = FALSE; + PL_parser->in_my = KEY_NULL; PL_parser->in_my_stash = NULL; return o; } diff --git a/perly.act b/perly.act index 8c329f1ae66b..03cd049fdd6e 100644 --- a/perly.act +++ b/perly.act @@ -201,7 +201,7 @@ case 2: /* @1: %empty */ case 25: /* $@8: %empty */ #line 292 "perly.y" - { parser->in_my = 1; } + { parser->in_my = KEY_catch; } break; @@ -2285,6 +2285,6 @@ case 2: /* @1: %empty */ /* Generated from: - * 57ef509d481a8f100fca417b83deb7d66655912f27495b2f6daa0699748ea44f perly.y + * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.h b/perly.h index 30c58ba885fc..214f412c362c 100644 --- a/perly.h +++ b/perly.h @@ -244,6 +244,6 @@ int yyparse (void); /* Generated from: - * 57ef509d481a8f100fca417b83deb7d66655912f27495b2f6daa0699748ea44f perly.y + * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.tab b/perly.tab index a54e65d81b0d..d134b54b5427 100644 --- a/perly.tab +++ b/perly.tab @@ -1599,6 +1599,6 @@ static const toketypes yy_type_tab[] = }; /* Generated from: - * 57ef509d481a8f100fca417b83deb7d66655912f27495b2f6daa0699748ea44f perly.y + * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.y b/perly.y index 03baaec51002..1f337c477add 100644 --- a/perly.y +++ b/perly.y @@ -289,7 +289,7 @@ catch_paren: empty /* not really valid grammar but we detect it in the * action block to throw a nicer error message */ | PERLY_PAREN_OPEN - { parser->in_my = 1; } + { parser->in_my = KEY_catch; } scalar { parser->in_my = 0; intro_my(); } PERLY_PAREN_CLOSE diff --git a/pod/perldelta.pod b/pod/perldelta.pod index a722ab7cf428..187644fe5e2c 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -198,6 +198,22 @@ and L XXX L +=item * + +L + +(F) A C, C or C keyword was used with the exception variable in +a C block: + + try { ... } + catch (my $e) { ... } + # or catch (our $e) { ... } + # or catch (state $e) { ... } + +This is not valid syntax. C takes a bare variable name, which is +automatically lexically declared. +[GH #23222] + =back =head3 New Warnings diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 69e332ded180..cf956fb2f84f 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -1485,10 +1485,23 @@ missing. You need to figure out where your CRTL misplaced its environ or define F (see L) so that environ is not searched. +=item Can't redeclare catch variable as "%s" + +(F) A C, C or C keyword was used with the exception variable in +a C block: + + try { ... } + catch (my $e) { ... } + # or catch (our $e) { ... } + # or catch (state $e) { ... } + +This is not valid syntax. C takes a bare variable name, which is +automatically lexically declared. + =item Can't redeclare "%s" in "%s" -(F) A "my", "our" or "state" declaration was found within another declaration, -such as C or C. +(F) A C, C or C declaration was found within another +declaration, such as C or C. =item Can't "redo" outside a loop block diff --git a/t/lib/croak/toke b/t/lib/croak/toke index ac766871e2d6..a50f256b0b0d 100644 --- a/t/lib/croak/toke +++ b/t/lib/croak/toke @@ -423,6 +423,30 @@ EXPECT Can't redeclare "state" in "state" at - line 2, near ", state" Execution of - aborted due to compilation errors. ######## +# NAME catch (my $x) errors +use feature 'try'; +try {} catch (my $x) {} +EXPECT +Can't redeclare catch variable as "my" at - line 2, near "(my" +syntax error at - line 2, near "(my " +Execution of - aborted due to compilation errors. +######## +# NAME catch (our $x) errors +use feature 'try'; +try {} catch (our $x) {} +EXPECT +Can't redeclare catch variable as "our" at - line 2, near "(our" +syntax error at - line 2, near "(our " +Execution of - aborted due to compilation errors. +######## +# NAME catch (state $x) errors +use feature 'try', 'state'; +try {} catch (state $x) {} +EXPECT +Can't redeclare catch variable as "state" at - line 2, near "(state" +syntax error at - line 2, near "(state " +Execution of - aborted due to compilation errors. +######## # NAME BEGIN <> [perl #125341] BEGIN <> EXPECT diff --git a/toke.c b/toke.c index e6acb5a70177..7d0de3118aae 100644 --- a/toke.c +++ b/toke.c @@ -7186,17 +7186,37 @@ yyl_do(pTHX_ char *s, I32 orig_keyword) OPERATOR(KW_DO); } +static const char * +declarator_name(I32 k) { + switch (k) { + case KEY_my: return "my"; + case KEY_state: return "state"; + case KEY_our: return "our"; + case KEY_field: return "field"; + case KEY_catch: return "catch"; + default: return "???"; + } +} + static int yyl_my(pTHX_ char *s, I32 my) { + assert(my == KEY_my || my == KEY_state || my == KEY_our); if (PL_in_my) { PL_bufptr = s; - yyerror(form( - "Can't redeclare \"%s\" in \"%s\"", - my == KEY_my ? "my" : - my == KEY_state ? "state" : "our", - PL_in_my == KEY_my ? "my" : - PL_in_my == KEY_state ? "state" : "our")); + if (PL_in_my == KEY_catch) { + yyerror(form( + "Can't redeclare catch variable as \"%s\"", + declarator_name(my) + )); + } else { + assert(PL_in_my == KEY_my || PL_in_my == KEY_state || PL_in_my == KEY_our); + yyerror(form( + "Can't redeclare \"%s\" in \"%s\"", + declarator_name(my), + declarator_name(PL_in_my) + )); + } } PL_in_my = (U16)my; s = skipspace(s);