diff --git a/class.c b/class.c index 9797db9eacbc..0838a39f2d0c 100644 --- a/class.c +++ b/class.c @@ -254,9 +254,14 @@ XS(injected_constructor) /* TODO: People would probably expect to find this in pp.c ;) */ PP(pp_methstart) { - /* note that if AvREAL(@_), be careful not to leak self: - * so keep it in @_ for now, and only shift it later */ - SV *self = *(av_fetch(GvAV(PL_defgv), 0, 1)); + bool self_in_pad = PL_op->op_private & OPpSELF_IN_PAD; + SV *self; + if (self_in_pad) + self = PAD_SVl(PADIX_SELF); + else + /* note that if AvREAL(@_), be careful not to leak self: + * so keep it in @_ for now, and only shift it later */ + self = *(av_fetch(GvAV(PL_defgv), 0, 1)); SV *rv = NULL; /* pp_methstart happens before the first OP_NEXTSTATE of the method body, @@ -285,8 +290,10 @@ PP(pp_methstart) croak("Cannot invoke a method of %" HvNAMEf_QUOTEDPREFIX " on an instance of %" HvNAMEf_QUOTEDPREFIX, HvNAMEfARG(CvSTASH(curcv)), HvNAMEfARG(SvSTASH(rv))); - save_clearsv(&PAD_SVl(PADIX_SELF)); - sv_setsv(PAD_SVl(PADIX_SELF), self); + if (!self_in_pad) { + save_clearsv(&PAD_SVl(PADIX_SELF)); + sv_setsv(PAD_SVl(PADIX_SELF), self); + } UNOP_AUX_item *aux = cUNOP_AUX->op_aux; if(aux) { @@ -318,10 +325,12 @@ PP(pp_methstart) } } - /* safe to shift and free self now */ - self = av_shift(GvAV(PL_defgv)); - if (AvREAL(GvAV(PL_defgv))) - SvREFCNT_dec_NN(self); + if (!self_in_pad) { + /* safe to shift and free self now */ + self = av_shift(GvAV(PL_defgv)); + if (AvREAL(GvAV(PL_defgv))) + SvREFCNT_dec_NN(self); + } if(PL_op->op_private & OPpINITFIELDS) { SV *params = *av_fetch(GvAV(PL_defgv), 0, 0); @@ -1080,11 +1089,17 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) I32 save_ix = block_start(TRUE); + subsignature_start(); + PADOFFSET padix; padix = pad_add_name_pvs("$self", 0, NULL, NULL); assert(padix == PADIX_SELF); + subsignature_append_positional(padix, 0, NULL); + + OP *sigop = subsignature_finish(); + padix = pad_add_name_pvn(PadnamePV(pn), PadnameLEN(pn), 0, NULL, NULL); intro_my(); @@ -1101,19 +1116,7 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) (ap++)->uv = padix; (ap++)->uv = fieldix; - methstartop = newUNOP_AUX(OP_METHSTART, 0, NULL, aux); - } - - OP *argcheckop; - { - struct op_argcheck_aux *aux = (struct op_argcheck_aux *) - PerlMemShared_malloc(sizeof(*aux)); - - aux->params = 0; - aux->opt_params = 0; - aux->slurpy = 0; - - argcheckop = newUNOP_AUX(OP_ARGCHECK, 0, NULL, (UNOP_AUX_item *)aux); + methstartop = newUNOP_AUX(OP_METHSTART, OPpSELF_IN_PAD << 8, NULL, aux); } OP *retop; @@ -1132,8 +1135,8 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) } OP *ops = newLISTOPn(OP_LINESEQ, 0, + sigop, methstartop, - argcheckop, retop, NULL); @@ -1147,18 +1150,6 @@ apply_field_attribute_reader(pTHX_ PADNAME *pn, SV *value) CvIsMETHOD_on(cv); } -/* If '@_' is called "snail", then elements of it can be called "slugs"; i.e. - * snails out of their container. */ -#define newSLUGOP(idx) S_newSLUGOP(aTHX_ idx) -static OP * -S_newSLUGOP(pTHX_ IV idx) -{ - assert(idx >= 0 && idx <= 255); - OP *op = newGVOP(OP_AELEMFAST, 0, PL_defgv); - op->op_private = idx; - return op; -} - static void apply_field_attribute_writer(pTHX_ PADNAME *pn, SV *value) { @@ -1185,11 +1176,24 @@ apply_field_attribute_writer(pTHX_ PADNAME *pn, SV *value) I32 save_ix = block_start(TRUE); + subsignature_start(); + PADOFFSET padix; padix = pad_add_name_pvs("$self", 0, NULL, NULL); assert(padix == PADIX_SELF); + subsignature_append_positional(padix, 0, NULL); + + /* param pad variable doesn't technically need a name, so don't bother as + * reusing the field name will provoke a warning */ + PADOFFSET param_padix = padix = pad_add_name_pvn("$", 1, 0, NULL, NULL); + intro_my(); + + subsignature_append_positional(param_padix, 0, NULL); + + OP *sigop = subsignature_finish(); + padix = pad_add_name_pvn(PadnamePV(pn), PadnameLEN(pn), 0, NULL, NULL); intro_my(); @@ -1206,23 +1210,11 @@ apply_field_attribute_writer(pTHX_ PADNAME *pn, SV *value) (ap++)->uv = padix; (ap++)->uv = fieldix; - methstartop = newUNOP_AUX(OP_METHSTART, 0, NULL, aux); - } - - OP *argcheckop; - { - struct op_argcheck_aux *aux = (struct op_argcheck_aux *) - PerlMemShared_malloc(sizeof(*aux)); - - aux->params = 1; - aux->opt_params = 0; - aux->slurpy = 0; - - argcheckop = newUNOP_AUX(OP_ARGCHECK, 0, NULL, (UNOP_AUX_item *)aux); + methstartop = newUNOP_AUX(OP_METHSTART, OPpSELF_IN_PAD << 8, NULL, aux); } OP *assignop = newBINOP(OP_SASSIGN, 0, - newSLUGOP(0), + newPADxVOP(OP_PADSV, 0, param_padix), newPADxVOP(OP_PADSV, OPf_MOD|OPf_REF, padix)); OP *retop = newLISTOP(OP_RETURN, 0, @@ -1230,8 +1222,8 @@ apply_field_attribute_writer(pTHX_ PADNAME *pn, SV *value) newPADxVOP(OP_PADSV, 0, PADIX_SELF)); OP *ops = newLISTOPn(OP_LINESEQ, 0, + sigop, methstartop, - argcheckop, assignop, retop, NULL); diff --git a/embed.fnc b/embed.fnc index c0b1f18150be..852c20e34dde 100644 --- a/embed.fnc +++ b/embed.fnc @@ -3104,12 +3104,12 @@ CRp |NV |str_to_version |NN SV *sv p |void |sub_crush_depth|NN CV *cv : Used in perly.y p |void |subsignature_append_positional \ - |NULLOK OP *varop \ + |PADOFFSET padix \ |OPCODE defmode \ |NULLOK OP *defexpr p |void |subsignature_append_slurpy \ |I32 sigil \ - |NULLOK OP *varop + |PADOFFSET padix p |OP * |subsignature_finish p |void |subsignature_start Adp |void |suspend_compcv |NN struct suspended_compcv *buffer diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm index 8ef1f875c4d2..c0db96633bfa 100644 --- a/lib/B/Op_private.pm +++ b/lib/B/Op_private.pm @@ -473,7 +473,7 @@ $bits{method_named}{0} = $bf[0]; $bits{method_redir}{0} = $bf[0]; $bits{method_redir_super}{0} = $bf[0]; $bits{method_super}{0} = $bf[0]; -@{$bits{methstart}}{7,0} = ('OPpINITFIELDS', $bf[0]); +@{$bits{methstart}}{7,6,0} = ('OPpINITFIELDS', 'OPpSELF_IN_PAD', $bf[0]); @{$bits{mkdir}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); @{$bits{modulo}}{1,0} = ($bf[1], $bf[1]); @{$bits{msgctl}}{3,2,1,0} = ($bf[5], $bf[5], $bf[5], $bf[5]); @@ -731,6 +731,7 @@ our %defines = ( OPpREPEAT_DOLIST => 64, OPpREVERSE_INPLACE => 8, OPpRV2HV_ISKEYS => 1, + OPpSELF_IN_PAD => 64, OPpSLICE => 64, OPpSLICEWARNING => 4, OPpSORT_DESCEND => 16, @@ -852,6 +853,7 @@ our %labels = ( OPpREPEAT_DOLIST => 'DOLIST', OPpREVERSE_INPLACE => 'INPLACE', OPpRV2HV_ISKEYS => 'KEYS', + OPpSELF_IN_PAD => 'SELF_IN_PAD', OPpSLICE => 'SLICE', OPpSLICEWARNING => 'SLICEWARN', OPpSORT_DESCEND => 'DESC', @@ -969,6 +971,7 @@ $ops_using{OPpMULTIDEREF_EXISTS} = $ops_using{OPpMULTIDEREF_DELETE}; $ops_using{OPpOPEN_IN_RAW} = $ops_using{OPpOPEN_IN_CRLF}; $ops_using{OPpOPEN_OUT_CRLF} = $ops_using{OPpOPEN_IN_CRLF}; $ops_using{OPpOPEN_OUT_RAW} = $ops_using{OPpOPEN_IN_CRLF}; +$ops_using{OPpSELF_IN_PAD} = $ops_using{OPpINITFIELDS}; $ops_using{OPpSLICE} = $ops_using{OPpKVSLICE}; $ops_using{OPpSORT_INPLACE} = $ops_using{OPpSORT_DESCEND}; $ops_using{OPpSORT_INTEGER} = $ops_using{OPpSORT_DESCEND}; diff --git a/op.c b/op.c index 386c9a9a8ae5..ad63e51bd438 100644 --- a/op.c +++ b/op.c @@ -16516,17 +16516,15 @@ Perl_subsignature_start(pTHX) } /* Appends another positional scalar parameter to the accumulated set of - * subroutine params. `varop` may be NULL, but if not it must be an OP_ARGELEM - * whose op_targ refers to an already-declared pad lexical. That lexical must - * be a scalar. It is not necessary to set the argument index in the op_aux - * field; that will be filled in by this function. + * subroutine params. `padix` may be zero, but if not it must be the pad + * index of a scalar pad lexical to store the incoming argument value into. * If `defexpr` is not NULL, it gives a defaulting expression to be evaluated * if required, according to `defmode` - one of zero, `OP_DORASSIGN` or * `OP_ORASSIGN`. */ void -Perl_subsignature_append_positional(pTHX_ OP *varop, OPCODE defmode, OP *defexpr) +Perl_subsignature_append_positional(pTHX_ PADOFFSET padix, OPCODE defmode, OP *defexpr) { PERL_ARGS_ASSERT_SUBSIGNATURE_APPEND_POSITIONAL; assert(PL_parser); @@ -16538,13 +16536,13 @@ Perl_subsignature_append_positional(pTHX_ OP *varop, OPCODE defmode, OP *defexpr UV argix = signature->elems; - if(varop) { - assert(varop->op_type == OP_ARGELEM); - assert((varop->op_private & OPpARGELEM_MASK) == OPpARGELEM_SV); - assert(varop->op_targ); - assert(PadnamePV(PadnamelistARRAY(PL_comppad_name)[varop->op_targ])[0] == '$'); + OP *varop = NULL; + if(padix) { + assert(PadnamePV(PadnamelistARRAY(PL_comppad_name)[padix])[0] == '$'); - /* Now fill in the argix */ + varop = newUNOP_AUX(OP_ARGELEM, 0, NULL, NULL); + varop->op_private |= OPpARGELEM_SV; + varop->op_targ = padix; cUNOP_AUXx(varop)->op_aux = INT2PTR(UNOP_AUX_item *, argix); } @@ -16601,14 +16599,13 @@ Perl_subsignature_append_positional(pTHX_ OP *varop, OPCODE defmode, OP *defexpr } /* Appends a final slurpy parameter to the accumulated set of subroutine - * params. `varop` may be NULL, but if not it must be an OP_ARGELEM whose - * op_targ refers to an already-declared pad lexical. That lexical must match - * the `sigil` parameter. It is not necessary to set the argument index in the - * op_aux field; that will be filled in by this function. + * params. `padix` may be zero, but if not it must be the pad index of an + * array or hash lexical to store the remaining argument values into. Its + * sigil must match the `sigil` parameter. */ void -Perl_subsignature_append_slurpy(pTHX_ I32 sigil, OP *varop) +Perl_subsignature_append_slurpy(pTHX_ I32 sigil, PADOFFSET padix) { PERL_ARGS_ASSERT_SUBSIGNATURE_APPEND_SLURPY; assert(PL_parser); @@ -16621,21 +16618,19 @@ Perl_subsignature_append_slurpy(pTHX_ I32 sigil, OP *varop) UV argix = signature->elems; - if(varop) { - assert(varop->op_type == OP_ARGELEM); - assert((varop->op_private & OPpARGELEM_MASK) == - ((sigil == '@') ? OPpARGELEM_AV : OPpARGELEM_HV)); - assert(varop->op_targ); - assert(PadnamePV(PadnamelistARRAY(PL_comppad_name)[varop->op_targ])[0] == sigil); + signature->slurpy = (char)sigil; - /* Now fill in the argix */ - cUNOP_AUXx(varop)->op_aux = INT2PTR(UNOP_AUX_item *, argix); - } + if(padix) { + assert(PadnamePV(PadnamelistARRAY(PL_comppad_name)[padix])[0] == sigil); - signature->slurpy = (char)sigil; + OP *varop = newUNOP_AUX(OP_ARGELEM, 0, NULL, NULL); + if(sigil == '@') + varop->op_private |= OPpARGELEM_AV; + if(sigil == '%') + varop->op_private |= OPpARGELEM_HV; + varop->op_targ = padix; + cUNOP_AUXx(varop)->op_aux = INT2PTR(UNOP_AUX_item *, argix); - if(varop) { - /* TODO: assert() the sigil of the pad variable matches */ signature->elemops = op_append_list(OP_LINESEQ, signature->elemops, newSTATEOP(0, NULL, varop)); } diff --git a/opcode.h b/opcode.h index bcd9023068e6..670fbf9dd407 100644 --- a/opcode.h +++ b/opcode.h @@ -2415,6 +2415,7 @@ END_EXTERN_C #define OPpPAD_STATE 0x40 #define OPpREFCOUNTED 0x40 #define OPpREPEAT_DOLIST 0x40 +#define OPpSELF_IN_PAD 0x40 #define OPpSLICE 0x40 #define OPpTRANS_USE_SVOP 0x40 #define OPpPADRANGE_COUNTMASK 0x7f @@ -2547,6 +2548,7 @@ EXTCONST char PL_op_private_labels[] = { 'R','E','P','L','1','S','T','\0', 'R','E','V','\0', 'R','E','V','E','R','S','E','D','\0', + 'S','E','L','F','_','I','N','_','P','A','D','\0', 'S','H','O','R','T','\0', 'S','L','I','C','E','\0', 'S','L','I','C','E','W','A','R','N','\0', @@ -2585,16 +2587,16 @@ EXTCONST char PL_op_private_labels[] = { EXTCONST I16 PL_op_private_bitfields[] = { 0, 8, -1, 0, 8, -1, - 0, 715, 1, 554, 2, 71, 3, 298, -1, - 0, 749, -1, + 0, 727, 1, 554, 2, 71, 3, 298, -1, + 0, 761, -1, 0, 8, -1, 0, 8, -1, - 0, 756, -1, - 0, 745, -1, - 1, -1, 0, 694, 1, 39, 2, 324, -1, + 0, 768, -1, + 0, 757, -1, + 1, -1, 0, 706, 1, 39, 2, 324, -1, 4, -1, 1, 185, 2, 192, 3, 199, -1, - 4, -1, 0, 694, 1, 39, 2, 324, 3, 131, -1, - 6, 709, 1, 463, 2, 246, 3, 596, -1, + 4, -1, 0, 706, 1, 39, 2, 324, 3, 131, -1, + 6, 721, 1, 463, 2, 246, 3, 596, -1, }; @@ -3027,7 +3029,7 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { 0, /* is_tainted */ 265, /* helemexistsor */ 267, /* methstart */ - 269, /* initfield */ + 270, /* initfield */ -1, /* classname */ }; @@ -3048,60 +3050,60 @@ EXTCONST I16 PL_op_private_bitdef_ix[] = { EXTCONST U16 PL_op_private_bitdefs[] = { 0x0003, /* scalar, prototype, refgen, srefgen, readline, regcmaybe, regcreset, regcomp, substcont, chop, schop, defined, study, preinc, i_preinc, predec, i_predec, postinc, i_postinc, postdec, i_postdec, not, ucfirst, lcfirst, uc, lc, quotemeta, aeach, avalues, each, pop, shift, grepstart, anywhile, mapstart, mapwhile, range, and, or, dor, andassign, orassign, dorassign, argcheck, entergiven, leavegiven, enterwhen, leavewhen, untie, tied, dbmclose, getsockname, getpeername, lstat, stat, readlink, readdir, telldir, rewinddir, closedir, localtime, alarm, require, dofile, entertry, ghbyname, gnbyname, gpbyname, shostent, snetent, sprotoent, sservent, gpwnam, gpwuid, ggrnam, ggrgid, lock, once, fc, anonconst, cmpchain_and, cmpchain_dup, entertrycatch, catch, is_bool, is_weak, weaken, unweaken, is_tainted */ - 0x3cfc, 0x5379, /* pushmark */ + 0x3cfc, 0x54f9, /* pushmark */ 0x00bd, /* wantarray, runcv */ - 0x077e, 0x0554, 0x1b70, 0x542c, 0x4fc8, 0x4225, /* const */ + 0x077e, 0x0554, 0x1b70, 0x55ac, 0x5148, 0x4225, /* const */ 0x3cfc, 0x47f9, /* gvsv */ 0x19d5, /* gv */ 0x0067, /* gelem, lt, i_lt, gt, i_gt, le, i_le, ge, i_ge, eq, i_eq, ne, i_ne, ncmp, i_ncmp, slt, sgt, sle, sge, seq, sne, scmp, smartmatch, lslice, xor, isa */ - 0x3cfc, 0x5378, 0x04f7, /* padsv */ - 0x3cfc, 0x5378, 0x0003, /* padsv_store, lvavref */ - 0x3cfc, 0x5378, 0x06d4, 0x3dec, 0x5149, /* padav */ - 0x3cfc, 0x5378, 0x06d4, 0x0770, 0x3dec, 0x5148, 0x37c1, /* padhv */ - 0x3cfc, 0x1e38, 0x04f6, 0x3dec, 0x4148, 0x5424, 0x0003, /* rv2gv */ - 0x3cfc, 0x47f8, 0x04f6, 0x5424, 0x0003, /* rv2sv */ + 0x3cfc, 0x54f8, 0x04f7, /* padsv */ + 0x3cfc, 0x54f8, 0x0003, /* padsv_store, lvavref */ + 0x3cfc, 0x54f8, 0x06d4, 0x3dec, 0x52c9, /* padav */ + 0x3cfc, 0x54f8, 0x06d4, 0x0770, 0x3dec, 0x52c8, 0x37c1, /* padhv */ + 0x3cfc, 0x1e38, 0x04f6, 0x3dec, 0x4148, 0x55a4, 0x0003, /* rv2gv */ + 0x3cfc, 0x47f8, 0x04f6, 0x55a4, 0x0003, /* rv2sv */ 0x3dec, 0x0003, /* av2arylen, akeys, values, keys */ - 0x40bc, 0x1198, 0x0ef4, 0x014c, 0x5728, 0x5424, 0x0003, /* rv2cv */ + 0x40bc, 0x1198, 0x0ef4, 0x014c, 0x58a8, 0x55a4, 0x0003, /* rv2cv */ 0x06d4, 0x0770, 0x0003, /* ref, blessed */ 0x02af, /* bless, glob, sprintf, formline, unpack, pack, join, anonlist, anonhash, splice, warn, die, reset, exit, close, pipe_op, fileno, umask, binmode, tie, dbmopen, sselect, select, getc, read, enterwrite, sysopen, sysseek, sysread, syswrite, eof, tell, seek, truncate, fcntl, ioctl, send, recv, socket, sockpair, bind, connect, listen, accept, shutdown, gsockopt, ssockopt, chdir, open_dir, seekdir, gmtime, shmget, shmctl, shmread, shmwrite, msgget, msgctl, msgsnd, msgrcv, semop, semget, semctl, ghbyaddr, gnbyaddr, gpbynumber, gsbyname, gsbyport, syscall */ 0x49dc, 0x48f8, 0x2e74, 0x2db0, 0x0003, /* backtick */ 0x06d5, /* subst */ - 0x129c, 0x5b98, 0x0ad4, 0x528c, 0x28e8, 0x00c7, /* trans, transr */ + 0x129c, 0x5d18, 0x0ad4, 0x540c, 0x28e8, 0x00c7, /* trans, transr */ 0x10dc, 0x05f8, 0x0067, /* sassign */ 0x0d98, 0x0c94, 0x0b90, 0x3dec, 0x06c8, 0x0067, /* aassign */ - 0x57d0, 0x0003, /* chomp, schomp, negate, i_negate, scomplement, sin, cos, exp, log, sqrt, int, hex, oct, abs, ord, chr, chroot, rmdir */ - 0x3cfc, 0x5378, 0x36d4, 0x57d0, 0x0003, /* undef */ + 0x5950, 0x0003, /* chomp, schomp, negate, i_negate, scomplement, sin, cos, exp, log, sqrt, int, hex, oct, abs, ord, chr, chroot, rmdir */ + 0x3cfc, 0x54f8, 0x36d4, 0x5950, 0x0003, /* undef */ 0x06d4, 0x3dec, 0x0003, /* pos */ - 0x57d0, 0x0067, /* pow, multiply, i_multiply, divide, i_divide, modulo, i_modulo, add, i_add, subtract, i_subtract */ + 0x5950, 0x0067, /* pow, multiply, i_multiply, divide, i_divide, modulo, i_modulo, add, i_add, subtract, i_subtract */ 0x1658, 0x0067, /* repeat */ - 0x3fd8, 0x57d0, 0x0067, /* concat */ - 0x3cfc, 0x0338, 0x1e34, 0x57d0, 0x550c, 0x0003, /* multiconcat */ - 0x57d0, 0x02af, /* stringify, atan2, rand, srand, crypt, push, unshift, flock, chown, unlink, chmod, utime, rename, link, symlink, mkdir, waitpid, system, exec, kill, getpgrp, setpgrp, getpriority, setpriority, sleep */ - 0x57d0, 0x5aa9, /* left_shift, right_shift, nbit_and, nbit_xor, nbit_or, ncomplement */ - 0x5aa9, /* bit_and, bit_xor, bit_or, sbit_and, sbit_xor, sbit_or, complement */ - 0x06d4, 0x57d0, 0x0003, /* length */ + 0x3fd8, 0x5950, 0x0067, /* concat */ + 0x3cfc, 0x0338, 0x1e34, 0x5950, 0x568c, 0x0003, /* multiconcat */ + 0x5950, 0x02af, /* stringify, atan2, rand, srand, crypt, push, unshift, flock, chown, unlink, chmod, utime, rename, link, symlink, mkdir, waitpid, system, exec, kill, getpgrp, setpgrp, getpriority, setpriority, sleep */ + 0x5950, 0x5c29, /* left_shift, right_shift, nbit_and, nbit_xor, nbit_or, ncomplement */ + 0x5c29, /* bit_and, bit_xor, bit_or, sbit_and, sbit_xor, sbit_or, complement */ + 0x06d4, 0x5950, 0x0003, /* length */ 0x4d30, 0x3dec, 0x024b, /* substr */ - 0x57d0, 0x024b, /* substr_left */ + 0x5950, 0x024b, /* substr_left */ 0x3dec, 0x0067, /* vec */ - 0x3f58, 0x06d4, 0x57d0, 0x02af, /* index, rindex */ - 0x3cfc, 0x47f8, 0x06d4, 0x3dec, 0x5148, 0x5424, 0x0003, /* rv2av */ + 0x3f58, 0x06d4, 0x5950, 0x02af, /* index, rindex */ + 0x3cfc, 0x47f8, 0x06d4, 0x3dec, 0x52c8, 0x55a4, 0x0003, /* rv2av */ 0x037f, /* aelemfast, aelemfast_lex, aelemfastlex_store */ 0x3cfc, 0x3bf8, 0x04f6, 0x3dec, 0x0067, /* aelem, helem */ - 0x3cfc, 0x3dec, 0x5149, /* aslice, hslice */ + 0x3cfc, 0x3dec, 0x52c9, /* aslice, hslice */ 0x3ded, /* kvaslice, kvhslice */ - 0x3cfc, 0x5098, 0x3874, 0x0003, /* delete */ - 0x5658, 0x0003, /* exists */ - 0x3cfc, 0x47f8, 0x06d4, 0x0770, 0x3dec, 0x5148, 0x5424, 0x37c1, /* rv2hv */ - 0x3cfc, 0x3bf8, 0x1314, 0x1d50, 0x3dec, 0x5424, 0x0003, /* multideref */ + 0x3cfc, 0x5218, 0x3874, 0x0003, /* delete */ + 0x57d8, 0x0003, /* exists */ + 0x3cfc, 0x47f8, 0x06d4, 0x0770, 0x3dec, 0x52c8, 0x55a4, 0x37c1, /* rv2hv */ + 0x3cfc, 0x3bf8, 0x1314, 0x1d50, 0x3dec, 0x55a4, 0x0003, /* multideref */ 0x3cfc, 0x47f8, 0x0410, 0x396c, 0x2be9, /* split */ 0x3cfc, 0x2619, /* list */ - 0x3cfc, 0x5378, 0x0214, 0x57d0, 0x02af, /* emptyavhv */ + 0x3cfc, 0x54f8, 0x0214, 0x5950, 0x02af, /* emptyavhv */ 0x15b0, 0x34ac, 0x4e28, 0x35a4, 0x44c1, /* sort */ 0x34ac, 0x0003, /* reverse */ 0x06d4, 0x0003, /* grepwhile */ 0x3a98, 0x0003, /* flip, flop */ 0x3cfc, 0x0003, /* cond_expr */ - 0x3cfc, 0x1198, 0x04f6, 0x014c, 0x5728, 0x5424, 0x2cc1, /* entersub */ + 0x3cfc, 0x1198, 0x04f6, 0x014c, 0x58a8, 0x55a4, 0x2cc1, /* entersub */ 0x4b98, 0x0003, /* leavesub, leavesublv, leavewrite, leaveeval */ 0x03ca, 0x0003, /* argelem */ 0x2adc, 0x29b8, 0x0003, /* argdefelem */ @@ -3111,24 +3113,24 @@ EXTCONST U16 PL_op_private_bitdefs[] = { 0x3cfc, 0x47f8, 0x120c, 0x4ea5, /* enteriter */ 0x2f08, 0x4ea5, /* iter */ 0x3b9c, 0x0067, /* leaveloop */ - 0x5cbc, 0x0003, /* last, next, redo, dump */ - 0x5cbc, 0x5728, 0x0003, /* goto */ + 0x5e3c, 0x0003, /* last, next, redo, dump */ + 0x5e3c, 0x58a8, 0x0003, /* goto */ 0x42e4, 0x0003, /* method, method_named, method_super, method_redir, method_redir_super */ 0x49dc, 0x48f8, 0x2e74, 0x2db0, 0x02af, /* open */ 0x2190, 0x23ec, 0x22a8, 0x2064, 0x0003, /* ftrread, ftrwrite, ftrexec, fteread, ftewrite, fteexec */ 0x2190, 0x23ec, 0x22a8, 0x0003, /* ftis, ftsize, ftmtime, ftatime, ftctime, ftrowned, fteowned, ftzero, ftsock, ftchr, ftblk, ftfile, ftdir, ftpipe, ftsuid, ftsgid, ftsvtx, ftlink, fttty, fttext, ftbinary */ - 0x57d1, /* wait, getppid, time */ - 0x1c78, 0x4c34, 0x0fb0, 0x082c, 0x5a28, 0x2704, 0x0003, /* entereval */ + 0x5951, /* wait, getppid, time */ + 0x1c78, 0x4c34, 0x0fb0, 0x082c, 0x5ba8, 0x2704, 0x0003, /* entereval */ 0x3ebc, 0x0018, 0x14c4, 0x13e1, /* coreargs */ 0x3dec, 0x01e7, /* avhvswitch */ 0x3cfc, 0x031b, /* padrange */ - 0x3cfc, 0x5378, 0x0616, 0x362c, 0x1ac8, 0x0067, /* refassign */ - 0x3cfc, 0x5378, 0x0616, 0x362c, 0x1ac8, 0x0003, /* lvref */ + 0x3cfc, 0x54f8, 0x0616, 0x362c, 0x1ac8, 0x0067, /* refassign */ + 0x3cfc, 0x54f8, 0x0616, 0x362c, 0x1ac8, 0x0003, /* lvref */ 0x3cfd, /* lvrefslice */ 0x1f7c, 0x0003, /* pushdefer */ - 0x57d0, 0x5728, 0x0003, /* refaddr, reftype, ceil, floor */ + 0x5950, 0x58a8, 0x0003, /* refaddr, reftype, ceil, floor */ 0x131c, 0x0003, /* helemexistsor */ - 0x301c, 0x0003, /* methstart */ + 0x301c, 0x4fd8, 0x0003, /* methstart */ 0x3308, 0x3164, 0x0003, /* initfield */ }; @@ -3561,7 +3563,7 @@ EXTCONST U8 PL_op_private_valid[] = { /* FLOOR */ (OPpARG1_MASK|OPpENTERSUB_HASTARG|OPpTARGET_MY), /* IS_TAINTED */ (OPpARG1_MASK), /* HELEMEXISTSOR */ (OPpARG1_MASK|OPpHELEMEXISTSOR_DELETE), - /* METHSTART */ (OPpARG1_MASK|OPpINITFIELDS), + /* METHSTART */ (OPpARG1_MASK|OPpSELF_IN_PAD|OPpINITFIELDS), /* INITFIELD */ (OPpARG1_MASK|OPpINITFIELD_AV|OPpINITFIELD_HV), /* CLASSNAME */ (0), diff --git a/perly.act b/perly.act index 03cd049fdd6e..fa005d9ba57b 100644 --- a/perly.act +++ b/perly.act @@ -933,15 +933,15 @@ case 2: /* @1: %empty */ break; - case 119: /* sigvarname: %empty */ + case 119: /* sigvar: %empty */ #line 826 "perly.y" - { parser->in_my = 0; (yyval.opval) = NULL; } + { parser->in_my = 0; (yyval.ival) = 0; } break; - case 120: /* sigvarname: PRIVATEREF */ + case 120: /* sigvar: PRIVATEREF */ #line 828 "perly.y" - { parser->in_my = 0; (yyval.opval) = (ps[0].val.opval); } + { parser->in_my = 0; (yyval.ival) = (ps[0].val.opval)->op_targ; op_free((ps[0].val.opval)); } break; @@ -957,16 +957,16 @@ case 2: /* @1: %empty */ break; - case 123: /* sigslurpelem: sigslurpsigil sigvarname */ + case 123: /* sigslurpelem: sigslurpsigil sigvar */ #line 839 "perly.y" { - subsignature_append_slurpy((ps[-1].val.ival), (ps[0].val.opval)); + subsignature_append_slurpy((ps[-1].val.ival), (ps[0].val.ival)); (yyval.opval) = NULL; } break; - case 124: /* sigslurpelem: sigslurpsigil sigvarname ASSIGNOP */ + case 124: /* sigslurpelem: sigslurpsigil sigvar ASSIGNOP */ #line 844 "perly.y" { yyerror("A slurpy parameter may not have a default value"); @@ -974,7 +974,7 @@ case 2: /* @1: %empty */ break; - case 125: /* sigslurpelem: sigslurpsigil sigvarname ASSIGNOP term */ + case 125: /* sigslurpelem: sigslurpsigil sigvar ASSIGNOP term */ #line 848 "perly.y" { yyerror("A slurpy parameter may not have a default value"); @@ -982,28 +982,28 @@ case 2: /* @1: %empty */ break; - case 126: /* sigscalarelem: PERLY_DOLLAR sigvarname */ + case 126: /* sigscalarelem: PERLY_DOLLAR sigvar */ #line 856 "perly.y" { - subsignature_append_positional((ps[0].val.opval), 0, NULL); + subsignature_append_positional((ps[0].val.ival), 0, NULL); (yyval.opval) = NULL; } break; - case 127: /* sigscalarelem: PERLY_DOLLAR sigvarname ASSIGNOP */ + case 127: /* sigscalarelem: PERLY_DOLLAR sigvar ASSIGNOP */ #line 861 "perly.y" { - subsignature_append_positional((ps[-1].val.opval), (ps[0].val.ival), newOP(OP_NULL, 0)); + subsignature_append_positional((ps[-1].val.ival), (ps[0].val.ival), newOP(OP_NULL, 0)); (yyval.opval) = NULL; } break; - case 128: /* sigscalarelem: PERLY_DOLLAR sigvarname ASSIGNOP term */ + case 128: /* sigscalarelem: PERLY_DOLLAR sigvar ASSIGNOP term */ #line 866 "perly.y" { - subsignature_append_positional((ps[-2].val.opval), (ps[-1].val.ival), (ps[0].val.opval)); + subsignature_append_positional((ps[-2].val.ival), (ps[-1].val.ival), (ps[0].val.opval)); (yyval.opval) = NULL; } @@ -2285,6 +2285,6 @@ case 2: /* @1: %empty */ /* Generated from: - * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y + * 50e36766e33adf09a4e7a67e33f0a36ae1ecd272526f93746f7170736720d9da perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.h b/perly.h index 214f412c362c..8f19b1b499b8 100644 --- a/perly.h +++ b/perly.h @@ -244,6 +244,6 @@ int yyparse (void); /* Generated from: - * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y + * 50e36766e33adf09a4e7a67e33f0a36ae1ecd272526f93746f7170736720d9da perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.tab b/perly.tab index d134b54b5427..92eb4876d6fc 100644 --- a/perly.tab +++ b/perly.tab @@ -196,7 +196,7 @@ enum yysymbol_kind_t YYSYMBOL_proto = 185, /* proto */ YYSYMBOL_subattrlist = 186, /* subattrlist */ YYSYMBOL_myattrlist = 187, /* myattrlist */ - YYSYMBOL_sigvarname = 188, /* sigvarname */ + YYSYMBOL_sigvar = 188, /* sigvar */ YYSYMBOL_sigslurpsigil = 189, /* sigslurpsigil */ YYSYMBOL_sigslurpelem = 190, /* sigslurpelem */ YYSYMBOL_sigscalarelem = 191, /* sigscalarelem */ @@ -417,7 +417,7 @@ static const char *const yytname[] = "formline", "formarg", "condition", "sideff", "else", "cont", "finally", "mintro", "nexpr", "texpr", "iexpr", "mexpr", "mnexpr", "formname", "startsub", "startanonsub", "startanonmethod", "startformsub", "subname", - "proto", "subattrlist", "myattrlist", "sigvarname", "sigslurpsigil", + "proto", "subattrlist", "myattrlist", "sigvar", "sigslurpsigil", "sigslurpelem", "sigscalarelem", "sigelem", "siglist", "optsiglist", "optsubsignature", "subsignature", "subsigguts", "$@20", "optsubbody", "subbody", "optsigsubbody", "sigsubbody", "$@21", "expr", "listexpr", @@ -1585,7 +1585,7 @@ static const toketypes yy_type_tab[] = toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_ival, toketype_ival, toketype_ival, toketype_opval, - toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_ival, + toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_ival, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_opval, toketype_opval, toketype_opval, toketype_opval, toketype_ival, toketype_opval, toketype_opval, @@ -1599,6 +1599,6 @@ static const toketypes yy_type_tab[] = }; /* Generated from: - * 77a59f73bcda0e12f216863101470b10051433a1712bbf7219acbd22399b8568 perly.y + * 50e36766e33adf09a4e7a67e33f0a36ae1ecd272526f93746f7170736720d9da perly.y * f13e9c08cea6302f0c1d1f467405bd0e0880d0ea92d0669901017a7f7e94ab28 regen_perly.pl * ex: set ro ft=c: */ diff --git a/perly.y b/perly.y index 1f337c477add..031c8351dc96 100644 --- a/perly.y +++ b/perly.y @@ -114,8 +114,8 @@ %type optfieldattrlist fielddecl %type termbinop termunop anonymous termdo %type termrelop relopchain termeqop eqopchain -%type sigslurpsigil -%type sigvarname sigscalarelem sigslurpelem +%type sigslurpsigil sigvar +%type sigscalarelem sigslurpelem %type sigelem siglist optsiglist subsigguts subsignature optsubsignature %type subbody optsubbody sigsubbody optsigsubbody %type formstmtseq formline formarg @@ -822,10 +822,10 @@ myattrlist: COLONATTR THING */ /* the '' or 'foo' part of a '$' or '@foo' etc signature variable */ -sigvarname: %empty - { parser->in_my = 0; $$ = NULL; } +sigvar: %empty + { parser->in_my = 0; $$ = 0; } | PRIVATEREF - { parser->in_my = 0; $$ = $PRIVATEREF; } + { parser->in_my = 0; $$ = $PRIVATEREF->op_targ; op_free($PRIVATEREF); } ; sigslurpsigil: @@ -835,16 +835,16 @@ sigslurpsigil: { $$ = '%'; } /* @, %, @foo, %foo */ -sigslurpelem: sigslurpsigil sigvarname +sigslurpelem: sigslurpsigil sigvar { - subsignature_append_slurpy($sigslurpsigil, $sigvarname); + subsignature_append_slurpy($sigslurpsigil, $sigvar); $$ = NULL; } - | sigslurpsigil sigvarname ASSIGNOP + | sigslurpsigil sigvar ASSIGNOP { yyerror("A slurpy parameter may not have a default value"); } - | sigslurpsigil sigvarname ASSIGNOP term + | sigslurpsigil sigvar ASSIGNOP term { yyerror("A slurpy parameter may not have a default value"); } @@ -852,19 +852,19 @@ sigslurpelem: sigslurpsigil sigvarname /* subroutine signature scalar element: e.g. '$x', '$=', '$x = $default' */ sigscalarelem: - PERLY_DOLLAR sigvarname + PERLY_DOLLAR sigvar { - subsignature_append_positional($sigvarname, 0, NULL); + subsignature_append_positional($sigvar, 0, NULL); $$ = NULL; } - | PERLY_DOLLAR sigvarname ASSIGNOP + | PERLY_DOLLAR sigvar ASSIGNOP { - subsignature_append_positional($sigvarname, $ASSIGNOP, newOP(OP_NULL, 0)); + subsignature_append_positional($sigvar, $ASSIGNOP, newOP(OP_NULL, 0)); $$ = NULL; } - | PERLY_DOLLAR sigvarname ASSIGNOP term[defop] + | PERLY_DOLLAR sigvar ASSIGNOP term[defop] { - subsignature_append_positional($sigvarname, $ASSIGNOP, $defop); + subsignature_append_positional($sigvar, $ASSIGNOP, $defop); $$ = NULL; } ; diff --git a/proto.h b/proto.h index f2376e95381f..2bfa5a9c8c21 100644 --- a/proto.h +++ b/proto.h @@ -4420,12 +4420,12 @@ Perl_sub_crush_depth(pTHX_ CV *cv) assert(cv); assert(SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM) PERL_CALLCONV void -Perl_subsignature_append_positional(pTHX_ OP *varop, OPCODE defmode, OP *defexpr) +Perl_subsignature_append_positional(pTHX_ PADOFFSET padix, OPCODE defmode, OP *defexpr) __attribute__visibility__("hidden"); #define PERL_ARGS_ASSERT_SUBSIGNATURE_APPEND_POSITIONAL PERL_CALLCONV void -Perl_subsignature_append_slurpy(pTHX_ I32 sigil, OP *varop) +Perl_subsignature_append_slurpy(pTHX_ I32 sigil, PADOFFSET padix) __attribute__visibility__("hidden"); #define PERL_ARGS_ASSERT_SUBSIGNATURE_APPEND_SLURPY diff --git a/regen/op_private b/regen/op_private index a08986a38426..b8cff44dbaa5 100644 --- a/regen/op_private +++ b/regen/op_private @@ -930,7 +930,8 @@ addbits('helemexistsor', ); addbits('methstart', - 7 => qw(OPpINITFIELDS INITFIELDS), + 7 => qw(OPpINITFIELDS INITFIELDS), + 6 => qw(OPpSELF_IN_PAD SELF_IN_PAD), # $self has already been set up in pad ); addbits('initfield', diff --git a/t/class/accessor.t b/t/class/accessor.t index 979d3e1c7a01..97b37941d941 100644 --- a/t/class/accessor.t +++ b/t/class/accessor.t @@ -33,7 +33,7 @@ no warnings 'experimental::class'; # Read accessor does not permit arguments ok(!eval { $o->s("value") }, 'Reader accessor fails with argument'); - like($@, qr/^Too many arguments for subroutine \'Testcase1::s\' \(got 1; expected 0\) at /, + like($@, qr/^Too many arguments for subroutine \'Testcase1::s\' \(got 2; expected 1\) at /, 'Failure from argument to accessor'); } @@ -51,11 +51,11 @@ no warnings 'experimental::class'; # Write accessor wants exactly one argument ok(!eval { $o->set_s() }, 'Reader accessor fails with no argument'); - like($@, qr/^Too few arguments for subroutine \'Testcase2::set_s\' \(got 0; expected 1\) at /, + like($@, qr/^Too few arguments for subroutine \'Testcase2::set_s\' \(got 1; expected 2\) at /, 'Failure from argument to accessor'); ok(!eval { $o->set_s(1, 2) }, 'Reader accessor fails with 2 arguments'); - like($@, qr/^Too many arguments for subroutine \'Testcase2::set_s\' \(got 2; expected 1\) at /, + like($@, qr/^Too many arguments for subroutine \'Testcase2::set_s\' \(got 3; expected 2\) at /, 'Failure from argument to accessor'); } diff --git a/toke.c b/toke.c index 525bd38fc622..7955bd9171f6 100644 --- a/toke.c +++ b/toke.c @@ -10000,25 +10000,7 @@ S_pending_ident(pTHX) GCC_DIAG_RESTORE_STMT; } - if (PL_in_my == KEY_sigvar) { - /* A signature 'padop' needs in addition, an op_first to - * point to a child sigdefelem, and an extra field to hold - * the signature index. We can achieve both by using an - * UNOP_AUX and (ab)using the op_aux field to hold the - * index. If we ever need more fields, use a real malloced - * aux strut instead. - */ - assert(PL_parser->signature); - /* We don't yet know the argindex but subsignature_append_*() - * will fill it in - */ - o = newUNOP_AUX(OP_ARGELEM, 0, NULL, NULL); - o->op_private |= ( PL_tokenbuf[0] == '$' ? OPpARGELEM_SV - : PL_tokenbuf[0] == '@' ? OPpARGELEM_AV - : OPpARGELEM_HV); - } - else - o = newOP(OP_PADANY, 0); + o = newOP(OP_PADANY, 0); o->op_targ = allocmy(PL_tokenbuf, tokenbuf_len, UTF ? SVf_UTF8 : 0); if (PL_in_my == KEY_sigvar)