Skip to content

Commit 04106f2

Browse files
committed
assertion failure on foo(my $x : bar)
RT #126257 'my var : attr' injects a void-context sub call just after the pad op. However, Perl_ck_entersub_args_list() tries to impose lvalue context on each of its args, which causes an assertion failure. This commit makes Perl_ck_entersub_args_list() skip calling op_lvalue() on any args which are OP_ENTERSUB/OPf_WANT_VOID. Strictly speaking it should check that the sub call is actually an attribute method call (e.g. first child is a const("attibutes") etc), but this was far too much like hard work.
1 parent a44fa0e commit 04106f2

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

op.c

+9
Original file line numberDiff line numberDiff line change
@@ -11156,11 +11156,20 @@ OP *
1115611156
Perl_ck_entersub_args_list(pTHX_ OP *entersubop)
1115711157
{
1115811158
OP *aop;
11159+
1115911160
PERL_ARGS_ASSERT_CK_ENTERSUB_ARGS_LIST;
11161+
1116011162
aop = cUNOPx(entersubop)->op_first;
1116111163
if (!OpHAS_SIBLING(aop))
1116211164
aop = cUNOPx(aop)->op_first;
1116311165
for (aop = OpSIBLING(aop); OpHAS_SIBLING(aop); aop = OpSIBLING(aop)) {
11166+
/* skip the extra attributes->import() call implicitly added in
11167+
* something like foo(my $x : bar)
11168+
*/
11169+
if ( aop->op_type == OP_ENTERSUB
11170+
&& (aop->op_flags & OPf_WANT) == OPf_WANT_VOID
11171+
)
11172+
continue;
1116411173
list(aop);
1116511174
op_lvalue(aop, OP_ENTERSUB);
1116611175
}

t/op/attrs.t

+19
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,23 @@ package _123817 {
428428
eval 'return my $x : m';
429429
}
430430

431+
# [perl #126257]
432+
# attributed lex var as function arg caused assertion failure
433+
434+
package P126257 {
435+
sub MODIFY_SCALAR_ATTRIBUTES {}
436+
sub MODIFY_ARRAY_ATTRIBUTES {}
437+
sub MODIFY_HASH_ATTRIBUTES {}
438+
sub MODIFY_CODE_ATTRIBUTES {}
439+
sub foo {}
440+
eval { foo(my $x : bar); };
441+
::is $@, "", "RT 126257 scalar";
442+
eval { foo(my @x : bar); };
443+
::is $@, "", "RT 126257 array";
444+
eval { foo(my %x : bar); };
445+
::is $@, "", "RT 126257 hash";
446+
eval { foo(sub : bar {}); };
447+
::is $@, "", "RT 126257 sub";
448+
}
449+
431450
done_testing();

0 commit comments

Comments
 (0)