Since $a and $b are aliased to the actual scalars being sorted, and
since they can be modified, the list of items needs to be in lvalue
context, like the arguments to grep. Otherwise implementation
details leak through, in that sort{$a=1} $_,... will modify $_, but
sort{$a=1} $#_,... will fail to modify $#_.
The way I have written the loop and if() condition (the if inside the
loop) may seem odd and inefficient, but the next commit will take
advantage of that.
{
dVAR;
OP *firstkid;
+ OP *kid;
HV * const hinthv =
PL_hints & HINT_LOCALIZE_HH ? GvHV(PL_hintgv) : NULL;
+ U8 stacked;
PERL_ARGS_ASSERT_CK_SORT;
if (o->op_flags & OPf_STACKED)
simplify_sort(o);
firstkid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
- if (o->op_flags & OPf_STACKED) { /* may have been cleared */
+ if ((stacked = o->op_flags & OPf_STACKED)) { /* may have been cleared */
OP *kid = cUNOPx(firstkid)->op_first; /* get past null */
if (kid->op_type == OP_SCOPE || kid->op_type == OP_LEAVE) {
/* provide list context for arguments */
list(firstkid);
+ for (kid = firstkid; kid; kid = kid->op_sibling) {
+ if (stacked)
+ op_lvalue(kid, OP_GREPSTART);
+ }
return o;
}
require 'test.pl';
}
use warnings;
-plan( tests => 178 );
+plan( tests => 179 );
# these shouldn't hang
{
eval { eval { use warnings FATAL => 'all'; () = sort yarn 1,2 } };
is $@, "",
'no panic/crash with fatal warnings when sort sub($$) returns string';
+
+$#a = -1;
+() = [sort { $a = 10; $b = 10; 0 } $#a, $#a];
+is $#a, 10, 'sort block modifying $a and $b';