summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-12-04 16:07:45 -0800
committerFather Chrysostomos <sprout@cpan.org>2014-12-04 18:56:12 -0800
commit6d4eed2136c73d9331ed2edb2e7650c90b974ea7 (patch)
tree76655c4fa4e84d2b439e501caa33ebd856132b5d /op.c
parent2310e17474d466b55500d4967d2d30e25058760c (diff)
downloadperl-6d4eed2136c73d9331ed2edb2e7650c90b974ea7.tar.gz
Return fresh scalar from join(const,const)
$ perl5.20.1 -Ilib -le 'for(1,2) { push @_, \join "x", 1 } print for @_' SCALAR(0x7fb131005438) SCALAR(0x7fb131005648) $ ./perl -Ilib -le 'for(1,2) { push @_, \join "x", 1 } print for @_' SCALAR(0x7fe612831b30) SCALAR(0x7fe612831b30) Notice how we now get two references to the same scalar. I broke this accidentally in 987c9691. If join has two arguments, it gets con- verted to a stringify op. The stringify op might get constant-folded, and folding of stringify is special, because the parser uses it itself to implement qq(). So I had ck_join set op_folded to flag the op as being a folded join. Only that came too late, because op_convert_list(OP_STRINGIFY,...) folds the op before it returns it. Hence, the folded constant was flagged the wrong way, and stopped being implicitly copied by refgen (\).
Diffstat (limited to 'op.c')
-rw-r--r--op.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/op.c b/op.c
index 476d1544c1..1ca2cd35cf 100644
--- a/op.c
+++ b/op.c
@@ -4225,7 +4225,8 @@ S_fold_constants(pTHX_ OP *o)
folded = cBOOL(o->op_folded);
op_free(o);
assert(sv);
- if (type == OP_STRINGIFY) SvPADTMP_off(sv);
+ if (type == OP_STRINGIFY && !folded)
+ SvPADTMP_off(sv);
else if (!SvIMMORTAL(sv)) {
SvPADTMP_on(sv);
SvREADONLY_on(sv);
@@ -4450,6 +4451,8 @@ Perl_op_convert_list(pTHX_ I32 type, I32 flags, OP *o)
CHANGE_TYPE(o, type);
o->op_flags |= flags;
+ if (flags & OPf_FOLDED)
+ o->op_folded = 1;
o = CHECKOP(type, o);
if (o->op_type != (unsigned)type)
@@ -10973,10 +10976,9 @@ Perl_ck_join(pTHX_ OP *o)
if (bairn && !OP_HAS_SIBLING(bairn) /* single-item list */
&& PL_opargs[bairn->op_type] & OA_RETSCALAR)
{
- OP * const ret = op_convert_list(OP_STRINGIFY, 0,
+ OP * const ret = op_convert_list(OP_STRINGIFY, OPf_FOLDED,
op_sibling_splice(o, kid, 1, NULL));
op_free(o);
- ret->op_folded = 1;
return ret;
}
}