X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/72c8de1ace969ce661556df13526a4e7e1d7eb93..f05e27e5b9aa3dce0aa1ab50210632677c656114:/op.c diff --git a/op.c b/op.c index 9a5dfb1..ab84ef1 100644 --- a/op.c +++ b/op.c @@ -73,6 +73,28 @@ into peep() to do that code's portion of the 3rd pass. It has to be recursive, but it's recursive on basic blocks, not on tree nodes. */ +/* To implement user lexical pragmas, there needs to be a way at run time to + get the compile time state of %^H for that block. Storing %^H in every + block (or even COP) would be very expensive, so a different approach is + taken. The (running) state of %^H is serialised into a tree of HE-like + structs. Stores into %^H are chained onto the current leaf as a struct + refcounted_he * with the key and the value. Deletes from %^H are saved + with a value of PL_sv_placeholder. The state of %^H at any point can be + turned back into a regular HV by walking back up the tree from that point's + leaf, ignoring any key you've already seen (placeholder or not), storing + the rest into the HV structure, then removing the placeholders. Hence + memory is only used to store the %^H deltas from the enclosing COP, rather + than the entire %^H on each COP. + + To cause actions on %^H to write out the serialisation records, it has + magic type 'H'. This magic (itself) does nothing, but its presence causes + the values to gain magic type 'h', which has entries for set and clear. + C updates C with a store + record, with deletes written by C. C + saves the current C on the save stack, so that + it will be correctly restored when any inner compiling scope is exited. +*/ + #include "EXTERN.h" #define PERL_IN_OP_C #include "perl.h" @@ -202,13 +224,13 @@ S_no_bareword_allowed(pTHX_ const OP *o) return; /* various ok barewords are hidden in extra OP_NULL */ qerror(Perl_mess(aTHX_ "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use", - cSVOPo_sv)); + (void*)cSVOPo_sv)); } /* "register" allocation */ PADOFFSET -Perl_allocmy(pTHX_ char *name) +Perl_allocmy(pTHX_ const char *const name) { dVAR; PADOFFSET off; @@ -223,25 +245,11 @@ Perl_allocmy(pTHX_ char *name) { /* name[2] is true if strlen(name) > 2 */ if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) { - /* 1999-02-27 mjd@plover.com */ - char *p; - p = strchr(name, '\0'); - /* The next block assumes the buffer is at least 205 chars - long. At present, it's always at least 256 chars. */ - if (p-name > 200) { - strcpy(name+200, "..."); - p = name+199; - } - else { - p[1] = '\0'; - } - /* Move everything else down one character */ - for (; p-name > 2; p--) - *p = *(p-1); - name[2] = toCTRL(name[1]); - name[1] = '^'; + yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"my\"", + name[0], toCTRL(name[1]), name + 2)); + } else { + yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name)); } - yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name)); } /* check for duplicate declaration */ @@ -250,7 +258,8 @@ Perl_allocmy(pTHX_ char *name) if (PL_in_my_stash && *name != '$') { yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"", - name, is_our ? "our" : "my")); + name, + is_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); } /* allocate a spare slot and store the name in that slot */ @@ -262,7 +271,8 @@ Perl_allocmy(pTHX_ char *name) ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash) : NULL ), - 0 /* not fake */ + 0, /* not fake */ + PL_in_my == KEY_state ); return off; } @@ -480,18 +490,24 @@ clear_pmop: STATIC void S_cop_free(pTHX_ COP* cop) { - Safefree(cop->cop_label); /* FIXME: treaddead ??? */ + if (cop->cop_label) { +#ifdef PERL_TRACK_MEMPOOL + Malloc_t ptr = (Malloc_t)(cop->cop_label - sTHX); + struct perl_memory_debug_header *const header + = (struct perl_memory_debug_header *)ptr; + /* Only the thread that allocated us can free us. */ + if (header->interpreter == aTHX) +#endif + { + Safefree(cop->cop_label); + cop->cop_label = NULL; + } + } CopFILE_free(cop); CopSTASH_free(cop); if (! specialWARN(cop->cop_warnings)) - SvREFCNT_dec(cop->cop_warnings); - if (! specialCopIO(cop->cop_io)) { -#ifdef USE_ITHREADS - /*EMPTY*/ -#else - SvREFCNT_dec(cop->cop_io); -#endif - } + PerlMemShared_free(cop->cop_warnings); + Perl_refcounted_he_free(aTHX_ cop->cop_hints_hash); } void @@ -636,7 +652,7 @@ Perl_scalar(pTHX_ OP *o) else scalar(kid); } - WITH_THR(PL_curcop = &PL_compiling); + PL_curcop = &PL_compiling; break; case OP_SCOPE: case OP_LINESEQ: @@ -647,7 +663,7 @@ Perl_scalar(pTHX_ OP *o) else scalar(kid); } - WITH_THR(PL_curcop = &PL_compiling); + PL_curcop = &PL_compiling; break; case OP_SORT: if (ckWARN(WARN_VOID)) @@ -816,16 +832,16 @@ Perl_scalarvoid(pTHX_ OP *o) if (ckWARN(WARN_VOID)) { useless = "a constant"; if (o->op_private & OPpCONST_ARYBASE) - useless = 0; + useless = NULL; /* don't warn on optimised away booleans, eg * use constant Foo, 5; Foo || print; */ if (cSVOPo->op_private & OPpCONST_SHORTCIRCUIT) - useless = 0; + useless = NULL; /* the constants 0 and 1 are permitted as they are conventionally used as dummies in constructs like 1 while some_condition_with_side_effects; */ else if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0)) - useless = 0; + useless = NULL; else if (SvPOK(sv)) { /* perl4's way of mixing documentation and code (before the invention of POD) was based on a @@ -837,7 +853,7 @@ Perl_scalarvoid(pTHX_ OP *o) if (strnEQ(maybe_macro, "di", 2) || strnEQ(maybe_macro, "ds", 2) || strnEQ(maybe_macro, "ig", 2)) - useless = 0; + useless = NULL; } } } @@ -984,7 +1000,7 @@ Perl_list(pTHX_ OP *o) else list(kid); } - WITH_THR(PL_curcop = &PL_compiling); + PL_curcop = &PL_compiling; break; case OP_SCOPE: case OP_LINESEQ: @@ -994,7 +1010,7 @@ Perl_list(pTHX_ OP *o) else list(kid); } - WITH_THR(PL_curcop = &PL_compiling); + PL_curcop = &PL_compiling; break; case OP_REQUIRE: /* all requires must return a boolean value */ @@ -1009,10 +1025,10 @@ Perl_scalarseq(pTHX_ OP *o) { dVAR; if (o) { - if (o->op_type == OP_LINESEQ || - o->op_type == OP_SCOPE || - o->op_type == OP_LEAVE || - o->op_type == OP_LEAVETRY) + const OPCODE type = o->op_type; + + if (type == OP_LINESEQ || type == OP_SCOPE || + type == OP_LEAVE || type == OP_LEAVETRY) { OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) { @@ -1080,12 +1096,13 @@ Perl_mod(pTHX_ OP *o, I32 type) goto nomod; localize = 0; if (PL_eval_start && PL_eval_start->op_type == OP_CONST) { - PL_compiling.cop_arybase = (I32)SvIV(cSVOPx(PL_eval_start)->op_sv); + CopARYBASE_set(&PL_compiling, + (I32)SvIV(cSVOPx(PL_eval_start)->op_sv)); PL_eval_start = 0; } else if (!type) { - SAVEI32(PL_compiling.cop_arybase); - PL_compiling.cop_arybase = 0; + SAVECOPARYBASE(&PL_compiling); + CopARYBASE_set(&PL_compiling, 0); } else if (type == OP_REFGEN) goto nomod; @@ -1124,15 +1141,14 @@ Perl_mod(pTHX_ OP *o, I32 type) CV *cv; OP *okid; - if (kid->op_type == OP_PUSHMARK) - goto skip_kids; - if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST) - Perl_croak(aTHX_ - "panic: unexpected lvalue entersub " - "args: type/targ %ld:%"UVuf, - (long)kid->op_type, (UV)kid->op_targ); - kid = kLISTOP->op_first; - skip_kids: + if (kid->op_type != OP_PUSHMARK) { + if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST) + Perl_croak(aTHX_ + "panic: unexpected lvalue entersub " + "args: type/targ %ld:%"UVuf, + (long)kid->op_type, (UV)kid->op_targ); + kid = kLISTOP->op_first; + } while (kid->op_sibling) kid = kid->op_sibling; if (!(kid->op_type == OP_NULL && kid->op_targ == OP_RV2CV)) { @@ -1592,7 +1608,7 @@ S_dup_attrlist(pTHX_ OP *o) rop = newSVOP(OP_CONST, o->op_flags, SvREFCNT_inc_NN(cSVOPo->op_sv)); #ifdef PERL_MAD else if (o->op_type == OP_NULL) - rop = Nullop; + rop = NULL; #endif else { assert((o->op_type == OP_LIST) && (o->op_flags & OPf_KIDS)); @@ -1625,7 +1641,7 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my) /* Don't force the C if we don't need it. */ SV * const * const svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE); if (svp && *svp != &PL_sv_undef) - /*EMPTY*/; /* already in %INC */ + NOOP; /* already in %INC */ else Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvs(ATTRSMODULE), NULL); @@ -1746,7 +1762,6 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) return o; type = o->op_type; - if (PL_madskills && type == OP_NULL && o->op_flags & OPf_KIDS) { (void)my_kid(cUNOPo->op_first, attrs, imopsp); return o; @@ -1766,8 +1781,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) type == OP_RV2AV || type == OP_RV2HV) { /* XXX does this let anything illegal in? */ if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */ - yyerror(Perl_form(aTHX_ "Can't declare %s in %s", - OP_DESC(o), PL_in_my == KEY_our ? "our" : "my")); + yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"", + OP_DESC(o), + PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); } else if (attrs) { GV * const gv = cGVOPx_gv(cUNOPo->op_first); PL_in_my = FALSE; @@ -1788,7 +1804,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"", OP_DESC(o), - PL_in_my == KEY_our ? "our" : "my")); + PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); return o; } else if (attrs && type != OP_PUSHMARK) { @@ -1805,6 +1821,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } o->op_flags |= OPf_MOD; o->op_private |= OPpLVAL_INTRO; + if (PL_in_my == KEY_state) + o->op_private |= OPpPAD_STATE; return o; } @@ -1862,48 +1880,50 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) { OP *o; bool ismatchop = 0; + const OPCODE ltype = left->op_type; + const OPCODE rtype = right->op_type; - if ( (left->op_type == OP_RV2AV || - left->op_type == OP_RV2HV || - left->op_type == OP_PADAV || - left->op_type == OP_PADHV) - && ckWARN(WARN_MISC)) + if ( (ltype == OP_RV2AV || ltype == OP_RV2HV || ltype == OP_PADAV + || ltype == OP_PADHV) && ckWARN(WARN_MISC)) { - const char * const desc = PL_op_desc[(right->op_type == OP_SUBST || - right->op_type == OP_TRANS) - ? right->op_type : OP_MATCH]; - const char * const sample = ((left->op_type == OP_RV2AV || - left->op_type == OP_PADAV) - ? "@array" : "%hash"); + const char * const desc + = PL_op_desc[(rtype == OP_SUBST || rtype == OP_TRANS) + ? (int)rtype : OP_MATCH]; + const char * const sample = ((ltype == OP_RV2AV || ltype == OP_PADAV) + ? "@array" : "%hash"); Perl_warner(aTHX_ packWARN(WARN_MISC), "Applying %s to %s will act on scalar(%s)", desc, sample, sample); } - if (right->op_type == OP_CONST && + if (rtype == OP_CONST && cSVOPx(right)->op_private & OPpCONST_BARE && cSVOPx(right)->op_private & OPpCONST_STRICT) { no_bareword_allowed(right); } - ismatchop = right->op_type == OP_MATCH || - right->op_type == OP_SUBST || - right->op_type == OP_TRANS; + ismatchop = rtype == OP_MATCH || + rtype == OP_SUBST || + rtype == OP_TRANS; if (ismatchop && right->op_private & OPpTARGET_MY) { right->op_targ = 0; right->op_private &= ~OPpTARGET_MY; } if (!(right->op_flags & OPf_STACKED) && ismatchop) { + OP *newleft; + right->op_flags |= OPf_STACKED; - if (right->op_type != OP_MATCH && - ! (right->op_type == OP_TRANS && + if (rtype != OP_MATCH && + ! (rtype == OP_TRANS && right->op_private & OPpTRANS_IDENTICAL)) - left = mod(left, right->op_type); + newleft = mod(left, rtype); + else + newleft = left; if (right->op_type == OP_TRANS) - o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right); + o = newBINOP(OP_NULL, OPf_STACKED, scalar(newleft), right); else - o = prepend_elem(right->op_type, scalar(left), right); + o = prepend_elem(rtype, scalar(newleft), right); if (type == OP_NOT) return newUNOP(OP_NOT, 0, scalar(o)); return o; @@ -1917,8 +1937,7 @@ OP * Perl_invert(pTHX_ OP *o) { if (!o) - return o; - /* XXX need to optimize away NOT NOT here? Or do we let optimizer do it? */ + return NULL; return newUNOP(OP_NOT, OPf_SPECIAL, scalar(o)); } @@ -1952,7 +1971,7 @@ Perl_scope(pTHX_ OP *o) } return o; } - + int Perl_block_start(pTHX_ int full) { @@ -1961,16 +1980,8 @@ Perl_block_start(pTHX_ int full) pad_block_start(full); SAVEHINTS(); PL_hints &= ~HINT_BLOCK_SCOPE; - SAVESPTR(PL_compiling.cop_warnings); - if (! specialWARN(PL_compiling.cop_warnings)) { - PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ; - SAVEFREESV(PL_compiling.cop_warnings) ; - } - SAVESPTR(PL_compiling.cop_io); - if (! specialCopIO(PL_compiling.cop_io)) { - PL_compiling.cop_io = newSVsv(PL_compiling.cop_io) ; - SAVEFREESV(PL_compiling.cop_io) ; - } + SAVECOMPILEWARNINGS(); + PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings); return retval; } @@ -1981,7 +1992,7 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; OP* const retval = scalarseq(seq); LEAVE_SCOPE(floor); - PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(&PL_compiling, PL_hints); if (needblockscope) PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */ pad_leavemy(); @@ -1992,7 +2003,7 @@ STATIC OP * S_newDEFSVOP(pTHX) { dVAR; - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); } @@ -2059,7 +2070,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) #if 0 list(o); #else - /*EMPTY*/; + NOOP; #endif else { if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',' @@ -2088,7 +2099,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) if (sigil && (*s == ';' || *s == '=')) { Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS), "Parentheses missing around \"%s\" list", - lex ? (PL_in_my == KEY_our ? "our" : "my") + lex ? (PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my") : "local"); } } @@ -2107,8 +2118,7 @@ Perl_jmaybe(pTHX_ OP *o) { if (o->op_type == OP_LIST) { OP * const o2 - = newSVREF(newGVOP(OP_GV, 0, gv_fetchpvs(";", GV_ADD|GV_NOTQUAL, - SVt_PV))); + = newSVREF(newGVOP(OP_GV, 0, gv_fetchpvs(";", GV_ADD|GV_NOTQUAL, SVt_PV))); o = convert(OP_JOIN, 0, prepend_elem(OP_LIST, o2, o)); } return o; @@ -2120,8 +2130,14 @@ Perl_fold_constants(pTHX_ register OP *o) dVAR; register OP *curop; OP *newop; - I32 type = o->op_type; - SV *sv; + VOL I32 type = o->op_type; + SV * VOL sv = NULL; + int ret = 0; + I32 oldscope; + OP *old_next; + SV * const oldwarnhook = PL_warnhook; + SV * const olddiehook = PL_diehook; + dJMPENV; if (PL_opargs[type] & OA_RETSCALAR) scalar(o); @@ -2163,40 +2179,77 @@ Perl_fold_constants(pTHX_ register OP *o) goto nope; /* Don't try to run w/ errors */ for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) { - if ((curop->op_type != OP_CONST || - (curop->op_private & OPpCONST_BARE)) && - curop->op_type != OP_LIST && - curop->op_type != OP_SCALAR && - curop->op_type != OP_NULL && - curop->op_type != OP_PUSHMARK) + const OPCODE type = curop->op_type; + if ((type != OP_CONST || (curop->op_private & OPpCONST_BARE)) && + type != OP_LIST && + type != OP_SCALAR && + type != OP_NULL && + type != OP_PUSHMARK) { goto nope; } } curop = LINKLIST(o); + old_next = o->op_next; o->op_next = 0; PL_op = curop; - CALLRUNOPS(aTHX); - sv = *(PL_stack_sp--); - if (o->op_targ && sv == PAD_SV(o->op_targ)) /* grab pad temp? */ - pad_swipe(o->op_targ, FALSE); - else if (SvTEMP(sv)) { /* grab mortal temp? */ - SvREFCNT_inc_simple_void(sv); - SvTEMP_off(sv); - } + + oldscope = PL_scopestack_ix; + create_eval_scope(G_FAKINGEVAL); + + PL_warnhook = PERL_WARNHOOK_FATAL; + PL_diehook = NULL; + JMPENV_PUSH(ret); + + switch (ret) { + case 0: + CALLRUNOPS(aTHX); + sv = *(PL_stack_sp--); + if (o->op_targ && sv == PAD_SV(o->op_targ)) /* grab pad temp? */ + pad_swipe(o->op_targ, FALSE); + else if (SvTEMP(sv)) { /* grab mortal temp? */ + SvREFCNT_inc_simple_void(sv); + SvTEMP_off(sv); + } + break; + case 3: + /* Something tried to die. Abandon constant folding. */ + /* Pretend the error never happened. */ + sv_setpvn(ERRSV,"",0); + o->op_next = old_next; + break; + default: + JMPENV_POP; + /* Don't expect 1 (setjmp failed) or 2 (something called my_exit) */ + PL_warnhook = oldwarnhook; + PL_diehook = olddiehook; + /* XXX note that this croak may fail as we've already blown away + * the stack - eg any nested evals */ + Perl_croak(aTHX_ "panic: fold_constants JMPENV_PUSH returned %d", ret); + } + JMPENV_POP; + PL_warnhook = oldwarnhook; + PL_diehook = olddiehook; + + if (PL_scopestack_ix > oldscope) + delete_eval_scope(); + + if (ret) + goto nope; #ifndef PERL_MAD op_free(o); #endif + assert(sv); if (type == OP_RV2GV) newop = newGVOP(OP_GV, 0, (GV*)sv); else - newop = newSVOP(OP_CONST, 0, sv); + newop = newSVOP(OP_CONST, 0, (SV*)sv); op_getmad(o,newop,'f'); return newop; - nope: + nope: return o; } @@ -2217,6 +2270,8 @@ Perl_gen_constant_list(pTHX_ register OP *o) pp_pushmark(); CALLRUNOPS(aTHX); PL_op = curop; + assert (!(curop->op_flags & OPf_SPECIAL)); + assert(curop->op_type == OP_RANGE); pp_anonlist(); PL_tmps_floor = oldtmps_floor; @@ -2788,6 +2843,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) const I32 to_utf = o->op_private & OPpTRANS_TO_UTF; U8* tsave = NULL; U8* rsave = NULL; + const U32 flags = UTF8_ALLOW_DEFAULT; if (!from_utf) { STRLEN len = tlen; @@ -2814,11 +2870,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) i = 0; transv = newSVpvs(""); while (t < tend) { - cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, 0); + cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, flags); t += ulen; if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { t++; - cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, 0); + cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, flags); t += ulen; } else { @@ -2872,11 +2928,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) while (t < tend || tfirst <= tlast) { /* see if we need more "t" chars */ if (tfirst > tlast) { - tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0); + tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); t += ulen; if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { /* illegal utf8 val indicates range */ t++; - tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0); + tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); t += ulen; } else @@ -2886,11 +2942,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) /* now see if we need more "r" chars */ if (rfirst > rlast) { if (r < rend) { - rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0); + rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); r += ulen; if (r < rend && NATIVE_TO_UTF(*r) == 0xff) { /* illegal utf8 val indicates range */ r++; - rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0); + rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); r += ulen; } else @@ -2951,6 +3007,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) bits = 8; Safefree(cPVOPo->op_pv); + cPVOPo->op_pv = NULL; cSVOPo->op_sv = (SV*)swash_init("utf8", "", listsv, bits, none); SvREFCNT_dec(listsv); SvREFCNT_dec(transv); @@ -3181,7 +3238,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) if (DO_UTF8(pat)) pm->op_pmdynflags |= PMdf_UTF8; /* FIXME - can we make this function take const char * args? */ - PM_SETRE(pm, CALLREGCOMP(aTHX_ (char*)p, (char*)p + plen, pm)); + PM_SETRE(pm, CALLREGCOMP((char*)p, (char*)p + plen, pm)); if (strEQ("\\s+", PM_GETRE(pm)->precomp)) pm->op_pmflags |= PMf_WHITE; #ifdef PERL_MAD @@ -3260,7 +3317,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) repl_has_vars = 1; } else if (curop->op_type == OP_PUSHRE) - /*EMPTY*/; /* Okay here, dangerous in newASSIGNOP */ + NOOP; /* Okay here, dangerous in newASSIGNOP */ else break; } @@ -3270,7 +3327,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) if (curop == repl && !(repl_has_vars && (!PM_GETRE(pm) - || PM_GETRE(pm)->reganch & ROPT_EVAL_SEEN))) { + || PM_GETRE(pm)->extflags & RXf_EVAL_SEEN))) { pm->op_pmflags |= PMf_CONST; /* const for long enough */ pm->op_pmpermflags |= PMf_CONST; /* const for long enough */ prepend_elem(o->op_type, scalar(repl), o); @@ -3402,7 +3459,7 @@ Perl_package(pTHX_ OP *o) #else if (!PL_madskills) { op_free(o); - return Nullop; + return NULL; } pegop = newOP(OP_NULL,0); @@ -3527,7 +3584,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) if (!PL_madskills) { /* FIXME - don't allocate pegop if !PL_madskills */ op_free(pegop); - return Nullop; + return NULL; } return pegop; #endif @@ -3630,8 +3687,7 @@ Perl_dofile(pTHX_ OP *term, I32 force_builtin) doop = ck_subr(newUNOP(OP_ENTERSUB, OPf_STACKED, append_elem(OP_LIST, term, scalar(newUNOP(OP_RV2CV, 0, - newGVOP(OP_GV, 0, - gv)))))); + newGVOP(OP_GV, 0, gv)))))); } else { doop = newUNOP(OP_DOFILE, 0, scalar(term)); @@ -3650,13 +3706,18 @@ Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) STATIC I32 S_is_list_assignment(pTHX_ register const OP *o) { + unsigned type; + U8 flags; + if (!o) return TRUE; - if (o->op_type == OP_NULL && o->op_flags & OPf_KIDS) + if ((o->op_type == OP_NULL) && (o->op_flags & OPf_KIDS)) o = cUNOPo->op_first; - if (o->op_type == OP_COND_EXPR) { + flags = o->op_flags; + type = o->op_type; + if (type == OP_COND_EXPR) { const I32 t = is_list_assignment(cLOGOPo->op_first->op_sibling); const I32 f = is_list_assignment(cLOGOPo->op_first->op_sibling->op_sibling); @@ -3667,20 +3728,20 @@ S_is_list_assignment(pTHX_ register const OP *o) return FALSE; } - if (o->op_type == OP_LIST && - (o->op_flags & OPf_WANT) == OPf_WANT_SCALAR && + if (type == OP_LIST && + (flags & OPf_WANT) == OPf_WANT_SCALAR && o->op_private & OPpLVAL_INTRO) return FALSE; - if (o->op_type == OP_LIST || o->op_flags & OPf_PARENS || - o->op_type == OP_RV2AV || o->op_type == OP_RV2HV || - o->op_type == OP_ASLICE || o->op_type == OP_HSLICE) + if (type == OP_LIST || flags & OPf_PARENS || + type == OP_RV2AV || type == OP_RV2HV || + type == OP_ASLICE || type == OP_HSLICE) return TRUE; - if (o->op_type == OP_PADAV || o->op_type == OP_PADHV) + if (type == OP_PADAV || type == OP_PADHV) return TRUE; - if (o->op_type == OP_RV2SV) + if (type == OP_RV2SV) return FALSE; return FALSE; @@ -3737,7 +3798,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) * to store these values, evil chicanery is done with SvCUR(). */ - if (!(left->op_private & OPpLVAL_INTRO)) { + { OP *lastop = o; PL_generation++; for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) { @@ -3792,11 +3853,37 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (curop != o) o->op_private |= OPpASSIGN_COMMON; } + + if ( ((left->op_private & OPpLVAL_INTRO) || ckWARN(WARN_MISC)) + && (left->op_type == OP_LIST + || (left->op_type == OP_NULL && left->op_targ == OP_LIST))) + { + OP* lop = ((LISTOP*)left)->op_first; + while (lop) { + if (lop->op_type == OP_PADSV || + lop->op_type == OP_PADAV || + lop->op_type == OP_PADHV || + lop->op_type == OP_PADANY) + { + if (lop->op_private & OPpPAD_STATE) { + if (left->op_private & OPpLVAL_INTRO) { + o->op_private |= OPpASSIGN_STATE; + /* hijacking PADSTALE for uninitialized state variables */ + SvPADSTALE_on(PAD_SVl(lop->op_targ)); + } + else { /* we already checked for WARN_MISC before */ + Perl_warner(aTHX_ packWARN(WARN_MISC), "State variable %s will be reinitialized", + PAD_COMPNAME_PV(lop->op_targ)); + } + } + } + lop = lop->op_sibling; + } + } + if (right && right->op_type == OP_SPLIT) { - OP* tmpop; - if ((tmpop = ((LISTOP*)right)->op_first) && - tmpop->op_type == OP_PUSHRE) - { + OP* tmpop = ((LISTOP*)right)->op_first; + if (tmpop && (tmpop->op_type == OP_PUSHRE)) { PMOP * const pm = (PMOP*)tmpop; if (left->op_type == OP_RV2AV && !(left->op_private & OPpLVAL_INTRO) && @@ -3854,7 +3941,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) else { /* FIXME for MAD */ op_free(o); - o = newSVOP(OP_CONST, 0, newSViv(PL_compiling.cop_arybase)); + o = newSVOP(OP_CONST, 0, newSViv(CopARYBASE_get(&PL_compiling))); o->op_private |= OPpCONST_ARYBASE; } } @@ -3878,11 +3965,11 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ]; } cop->op_flags = (U8)flags; - cop->op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(cop, PL_hints); #ifdef NATIVE_HINTS cop->op_private |= NATIVE_HINTS; #endif - PL_compiling.op_private = cop->op_private; + CopHINTS_set(&PL_compiling, CopHINTS_get(cop)); cop->op_next = (OP*)cop; if (label) { @@ -3890,16 +3977,16 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) PL_hints |= HINT_BLOCK_SCOPE; } cop->cop_seq = seq; - cop->cop_arybase = PL_curcop->cop_arybase; - if (specialWARN(PL_curcop->cop_warnings)) - cop->cop_warnings = PL_curcop->cop_warnings ; - else - cop->cop_warnings = newSVsv(PL_curcop->cop_warnings) ; - if (specialCopIO(PL_curcop->cop_io)) - cop->cop_io = PL_curcop->cop_io; - else - cop->cop_io = newSVsv(PL_curcop->cop_io) ; - + /* CopARYBASE is now "virtual", in that it's stored as a flag bit in + CopHINTS and a possible value in cop_hints_hash, so no need to copy it. + */ + cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings); + cop->cop_hints_hash = PL_curcop->cop_hints_hash; + if (cop->cop_hints_hash) { + HINTS_REFCNT_LOCK; + cop->cop_hints_hash->refcounted_he_refcnt++; + HINTS_REFCNT_UNLOCK; + } if (PL_copline == NOLINE) CopLINE_set(cop, CopLINE(PL_curcop)); @@ -3915,10 +4002,13 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) CopSTASH_set(cop, PL_curstash); if (PERLDB_LINE && PL_curstash != PL_debstash) { - SV * const * const svp = av_fetch(CopFILEAVx(PL_curcop), (I32)CopLINE(cop), FALSE); - if (svp && *svp != &PL_sv_undef ) { - (void)SvIOK_on(*svp); - SvIV_set(*svp, PTR2IV(cop)); + AV *av = CopFILEAVx(PL_curcop); + if (av) { + SV * const * const svp = av_fetch(av, (I32)CopLINE(cop), FALSE); + if (svp && *svp != &PL_sv_undef ) { + (void)SvIOK_on(*svp); + SvIV_set(*svp, PTR2IV(cop)); + } } } @@ -4325,7 +4415,9 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my) cont = append_elem(OP_LINESEQ, cont, unstack); } + assert(block); listop = append_list(OP_LINESEQ, (LISTOP*)block, (LISTOP*)cont); + assert(listop); redo = LINKLIST(listop); if (expr) { @@ -4377,7 +4469,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP PADOFFSET padoff = 0; I32 iterflags = 0; I32 iterpflags = 0; - OP *madsv = 0; + OP *madsv = NULL; if (sv) { if (sv->op_type == OP_RV2SV) { /* symbol table variable */ @@ -4415,7 +4507,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP iterpflags |= OPpITER_DEF; } else { - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { sv = newGVOP(OP_GV, 0, PL_defgv); } @@ -4436,7 +4528,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP * set the STACKED flag to indicate that these values are to be * treated as min/max values by 'pp_iterinit'. */ - UNOP* const flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first; + const UNOP* const flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first; LOGOP* const range = (LOGOP*) flip->op_first; OP* const left = range->op_first; OP* const right = left->op_sibling; @@ -4479,7 +4571,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP loop = tmp; } #else - Renew(loop, 1, LOOP); + loop = (LOOP*)PerlMemShared_realloc(loop, sizeof(LOOP)); #endif loop->op_targ = padoff; wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0); @@ -4607,7 +4699,7 @@ S_newGIVWHENOP(pTHX_ OP *cond, OP *block, */ STATIC bool -S_looks_like_bool(pTHX_ OP *o) +S_looks_like_bool(pTHX_ const OP *o) { dVAR; switch(o->op_type) { @@ -4678,7 +4770,7 @@ Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off) OP * Perl_newWHENOP(pTHX_ OP *cond, OP *block) { - bool cond_llb = (!cond || looks_like_bool(cond)); + const bool cond_llb = (!cond || looks_like_bool(cond)); OP *cond_op; if (cond_llb) @@ -4715,7 +4807,7 @@ Perl_cv_undef(pTHX_ CV *cv) /* for XSUBs CvFILE point directly to static memory; __FILE__ */ Safefree(CvFILE(cv)); } - CvFILE(cv) = 0; + CvFILE(cv) = NULL; #endif if (!CvISXSUB(cv) && CvROOT(cv)) { @@ -4753,9 +4845,15 @@ Perl_cv_undef(pTHX_ CV *cv) } void -Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) -{ - if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX_const(cv)))) && ckWARN_d(WARN_PROTOTYPE)) { +Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p, + const STRLEN len) +{ + /* Can't just use a strcmp on the prototype, as CONSTSUBs "cheat" by + relying on SvCUR, and doubling up the buffer to hold CvFILE(). */ + if (((!p != !SvPOK(cv)) /* One has prototype, one has not. */ + || (p && (len != SvCUR(cv) /* Not the same length. */ + || memNE(p, SvPVX_const(cv), len)))) + && ckWARN_d(WARN_PROTOTYPE)) { SV* const msg = sv_newmortal(); SV* name = NULL; @@ -4763,17 +4861,17 @@ Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) gv_efullname3(name = sv_newmortal(), gv, NULL); sv_setpv(msg, "Prototype mismatch:"); if (name) - Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name); + Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, (void*)name); if (SvPOK(cv)) - Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv); + Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (void*)cv); else sv_catpvs(msg, ": none"); sv_catpvs(msg, " vs "); if (p) - Perl_sv_catpvf(aTHX_ msg, "(%s)", p); + Perl_sv_catpvf(aTHX_ msg, "(%.*s)", (int) len, p); else sv_catpvs(msg, "none"); - Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, msg); + Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, (void*)msg); } } @@ -4975,7 +5073,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "Runaway prototype"); } - cv_ckproto((CV*)gv, NULL, ps); + cv_ckproto_len((CV*)gv, NULL, ps, ps_len); } if (ps) sv_setpvn((SV*)gv, ps, ps_len); @@ -5019,7 +5117,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) * skipping the prototype check */ if (exists || SvPOK(cv)) - cv_ckproto(cv, gv, ps); + cv_ckproto_len(cv, gv, ps, ps_len); /* already defined (or promised)? */ if (exists || GvASSUMECV(gv)) { if ((!block @@ -5064,7 +5162,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } } if (const_sv) { - SvREFCNT_inc_void_NN(const_sv); + SvREFCNT_inc_simple_void_NN(const_sv); if (cv) { assert(!CvROOT(cv) && !CvCONST(cv)); sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ @@ -5184,7 +5282,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else { /* force display of errors found but not reported */ sv_catpv(ERRSV, not_safe); - Perl_croak(aTHX_ "%"SVf, ERRSV); + Perl_croak(aTHX_ "%"SVf, (void*)ERRSV); } } } @@ -5200,7 +5298,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else { /* This makes sub {}; work as expected. */ if (block->op_type == OP_STUB) { - OP* newblock = newSTATEOP(0, NULL, 0); + OP* const newblock = newSTATEOP(0, NULL, 0); #ifdef PERL_MAD op_getmad(block,newblock,'B'); #else @@ -5260,7 +5358,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else s = tname; - if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I') + if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I' && *s != 'U') goto done; if (strEQ(s, "BEGIN") && !PL_error_count) { @@ -5277,7 +5375,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) call_list(oldscope, PL_beginav); PL_curcop = &PL_compiling; - PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(&PL_compiling, PL_hints); LEAVE; } else if (strEQ(s, "END") && !PL_error_count) { @@ -5288,6 +5386,15 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) av_store(PL_endav, 0, (SV*)cv); GvCV(gv) = 0; /* cv has been hijacked */ } + else if (strEQ(s, "UNITCHECK") && !PL_error_count) { + /* It's never too late to run a unitcheck block */ + if (!PL_unitcheckav) + PL_unitcheckav = newAV(); + DEBUG_x( dump_sub(gv) ); + av_unshift(PL_unitcheckav, 1); + av_store(PL_unitcheckav, 0, (SV*)cv); + GvCV(gv) = 0; /* cv has been hijacked */ + } else if (strEQ(s, "CHECK") && !PL_error_count) { if (!PL_checkav) PL_checkav = newAV(); @@ -5330,6 +5437,15 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) { dVAR; CV* cv; +#ifdef USE_ITHREADS + const char *const temp_p = CopFILE(PL_curcop); + const STRLEN len = temp_p ? strlen(temp_p) : 0; +#else + SV *const temp_sv = CopFILESV(PL_curcop); + STRLEN len; + const char *const temp_p = temp_sv ? SvPV_const(temp_sv, len) : NULL; +#endif + char *const file = savepvn(temp_p, temp_p ? len : 0); ENTER; @@ -5346,10 +5462,14 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) CopSTASH_set(PL_curcop,stash); } - cv = newXS(name, const_sv_xsub, savepv(CopFILE(PL_curcop))); + /* file becomes the CvFILE. For an XS, it's supposed to be static storage, + and so doesn't get free()d. (It's expected to be from the C pre- + processor __FILE__ directive). But we need a dynamically allocated one, + and we need it to get freed. */ + cv = newXS_flags(name, const_sv_xsub, file, "", XS_DYNAMIC_FILENAME); CvXSUBANY(cv).any_ptr = sv; CvCONST_on(cv); - sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ + Safefree(file); #ifdef USE_ITHREADS if (stash) @@ -5360,10 +5480,56 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) return cv; } +CV * +Perl_newXS_flags(pTHX_ const char *name, XSUBADDR_t subaddr, + const char *const filename, const char *const proto, + U32 flags) +{ + CV *cv = newXS(name, subaddr, filename); + + if (flags & XS_DYNAMIC_FILENAME) { + /* We need to "make arrangements" (ie cheat) to ensure that the + filename lasts as long as the PVCV we just created, but also doesn't + leak */ + STRLEN filename_len = strlen(filename); + STRLEN proto_and_file_len = filename_len; + char *proto_and_file; + STRLEN proto_len; + + if (proto) { + proto_len = strlen(proto); + proto_and_file_len += proto_len; + + Newx(proto_and_file, proto_and_file_len + 1, char); + Copy(proto, proto_and_file, proto_len, char); + Copy(filename, proto_and_file + proto_len, filename_len + 1, char); + } else { + proto_len = 0; + proto_and_file = savepvn(filename, filename_len); + } + + /* This gets free()d. :-) */ + sv_usepvn_flags((SV*)cv, proto_and_file, proto_and_file_len, + SV_HAS_TRAILING_NUL); + if (proto) { + /* This gives us the correct prototype, rather than one with the + file name appended. */ + SvCUR_set(cv, proto_len); + } else { + SvPOK_off(cv); + } + CvFILE(cv) = proto_and_file + proto_len; + } else { + sv_setpv((SV *)cv, proto); + } + return cv; +} + /* =for apidoc U||newXS -Used by C to hook up XSUBs as Perl subs. +Used by C to hook up XSUBs as Perl subs. I needs to be +static storage, as it is used directly as CvFILE(), without a copy being made. =cut */ @@ -5509,7 +5675,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ packWARN(WARN_REDEFINE), o ? "Format %"SVf" redefined" - : "Format STDOUT redefined" ,cSVOPo->op_sv); + : "Format STDOUT redefined", (void*)cSVOPo->op_sv); CopLINE_set(PL_curcop, oldline); } SvREFCNT_dec(cv); @@ -5543,15 +5709,13 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) OP * Perl_newANONLIST(pTHX_ OP *o) { - return newUNOP(OP_REFGEN, 0, - mod(list(convert(OP_ANONLIST, 0, o)), OP_REFGEN)); + return convert(OP_ANONLIST, OPf_SPECIAL, o); } OP * Perl_newANONHASH(pTHX_ OP *o) { - return newUNOP(OP_REFGEN, 0, - mod(list(convert(OP_ANONHASH, 0, o)), OP_REFGEN)); + return convert(OP_ANONHASH, OPf_SPECIAL, o); } OP * @@ -5690,7 +5854,7 @@ Perl_ck_anoncode(pTHX_ OP *o) { cSVOPo->op_targ = pad_add_anon(cSVOPo->op_sv, o->op_type); if (!PL_madskills) - cSVOPo->op_sv = Nullsv; + cSVOPo->op_sv = NULL; return o; } @@ -5706,7 +5870,7 @@ Perl_ck_bitop(pTHX_ OP *o) (op) == OP_EQ || (op) == OP_I_EQ || \ (op) == OP_NE || (op) == OP_I_NE || \ (op) == OP_NCMP || (op) == OP_I_NCMP) - o->op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + o->op_private = (U8)(PL_hints & HINT_INTEGER); if (!(o->op_flags & OPf_STACKED) /* Not an assignment */ && (o->op_type == OP_BIT_OR || o->op_type == OP_BIT_AND @@ -5750,13 +5914,12 @@ Perl_ck_spair(pTHX_ OP *o) o = modkids(ck_fun(o), type); kid = cUNOPo->op_first; newop = kUNOP->op_first->op_sibling; - if (newop && - (newop->op_sibling || - !(PL_opargs[newop->op_type] & OA_RETSCALAR) || - newop->op_type == OP_PADAV || newop->op_type == OP_PADHV || - newop->op_type == OP_RV2AV || newop->op_type == OP_RV2HV)) { - - return o; + if (newop) { + const OPCODE type = newop->op_type; + if (newop->op_sibling || !(PL_opargs[type] & OA_RETSCALAR) || + type == OP_PADAV || type == OP_PADHV || + type == OP_RV2AV || type == OP_RV2HV) + return o; } #ifdef PERL_MAD op_getmad(kUNOP->op_first,newop,'K'); @@ -5810,12 +5973,11 @@ OP * Perl_ck_eof(pTHX_ OP *o) { dVAR; - const I32 type = o->op_type; if (o->op_flags & OPf_KIDS) { if (cLISTOPo->op_first->op_type == OP_STUB) { - OP* newop - = newUNOP(type, OPf_SPECIAL, newGVOP(OP_GV, 0, PL_argvgv)); + OP * const newop + = newUNOP(o->op_type, OPf_SPECIAL, newGVOP(OP_GV, 0, PL_argvgv)); #ifdef PERL_MAD op_getmad(o,newop,'O'); #else @@ -5843,7 +6005,7 @@ Perl_ck_eval(pTHX_ OP *o) else if (kid->op_type == OP_LINESEQ || kid->op_type == OP_STUB) { LOGOP *enter; #ifdef PERL_MAD - OP* oldo = o; + OP* const oldo = o; #endif cUNOPo->op_first = 0; @@ -5873,7 +6035,7 @@ Perl_ck_eval(pTHX_ OP *o) } else { #ifdef PERL_MAD - OP* oldo = o; + OP* const oldo = o; #else op_free(o); #endif @@ -5883,7 +6045,8 @@ Perl_ck_eval(pTHX_ OP *o) o->op_targ = (PADOFFSET)PL_hints; if ((PL_hints & HINT_LOCALIZE_HH) != 0 && GvHV(PL_hintgv)) { /* Store a copy of %^H that pp_entereval can pick up */ - OP *hhop = newSVOP(OP_CONST, 0, (SV*)newHVhv(GvHV(PL_hintgv))); + OP *hhop = newSVOP(OP_CONST, 0, + (SV*)Perl_hv_copy_hints_hv(aTHX_ GvHV(PL_hintgv))); cUNOPo->op_first->op_sibling = hhop; o->op_private |= OPpEVAL_HAS_HH; } @@ -5962,24 +6125,24 @@ Perl_ck_rvconst(pTHX_ register OP *o) /* Is it a constant from cv_const_sv()? */ if (SvROK(kidsv) && SvREADONLY(kidsv)) { SV * const rsv = SvRV(kidsv); - const int svtype = SvTYPE(rsv); + const svtype type = SvTYPE(rsv); const char *badtype = NULL; switch (o->op_type) { case OP_RV2SV: - if (svtype > SVt_PVMG) + if (type > SVt_PVMG) badtype = "a SCALAR"; break; case OP_RV2AV: - if (svtype != SVt_PVAV) + if (type != SVt_PVAV) badtype = "an ARRAY"; break; case OP_RV2HV: - if (svtype != SVt_PVHV) + if (type != SVt_PVHV) badtype = "a HASH"; break; case OP_RV2CV: - if (svtype != SVt_PVCV) + if (type != SVt_PVCV) badtype = "a CODE"; break; } @@ -6016,8 +6179,8 @@ Perl_ck_rvconst(pTHX_ register OP *o) } if (badthing) Perl_croak(aTHX_ - "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use", - kidsv, badthing); + "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use", + (void*)kidsv, badthing); } /* * This is a little tricky. We only want to add the symbol if we @@ -6067,12 +6230,13 @@ Perl_ck_ftst(pTHX_ OP *o) const I32 type = o->op_type; if (o->op_flags & OPf_REF) { - /*EMPTY*/; + NOOP; } else if (o->op_flags & OPf_KIDS && cUNOPo->op_first->op_type != OP_STUB) { SVOP * const kid = (SVOP*)cUNOPo->op_first; + const OPCODE kidtype = kid->op_type; - if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { + if (kidtype == OP_CONST && (kid->op_private & OPpCONST_BARE)) { OP * const newop = newGVOP(type, OPf_REF, gv_fetchsv(kid->op_sv, GV_ADD, SVt_PVIO)); #ifdef PERL_MAD @@ -6080,21 +6244,17 @@ Perl_ck_ftst(pTHX_ OP *o) #else op_free(o); #endif - o = newop; - return o; + return newop; } - else { - if ((PL_hints & HINT_FILETEST_ACCESS) && - OP_IS_FILETEST_ACCESS(o)) + if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o)) o->op_private |= OPpFT_ACCESS; - } - if (PL_check[kid->op_type] == MEMBER_TO_FPTR(Perl_ck_ftst) - && kid->op_type != OP_STAT && kid->op_type != OP_LSTAT) + if (PL_check[kidtype] == MEMBER_TO_FPTR(Perl_ck_ftst) + && kidtype != OP_STAT && kidtype != OP_LSTAT) o->op_private |= OPpFT_STACKED; } else { #ifdef PERL_MAD - OP* oldo = o; + OP* const oldo = o; #else op_free(o); #endif @@ -6178,7 +6338,7 @@ Perl_ck_fun(pTHX_ OP *o) if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Array @%"SVf" missing the @ in argument %"IVdf" of %s()", - ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); + (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); #ifdef PERL_MAD op_getmad(kid,newop,'K'); #else @@ -6201,7 +6361,7 @@ Perl_ck_fun(pTHX_ OP *o) if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()", - ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); + (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); #ifdef PERL_MAD op_getmad(kid,newop,'K'); #else @@ -6282,6 +6442,7 @@ Perl_ck_fun(pTHX_ OP *o) else if (kid->op_type == OP_AELEM || kid->op_type == OP_HELEM) { + OP *firstop; OP *op = ((BINOP*)kid)->op_first; name = NULL; if (op) { @@ -6291,10 +6452,10 @@ Perl_ck_fun(pTHX_ OP *o) "[]" : "{}"; if (((op->op_type == OP_RV2AV) || (op->op_type == OP_RV2HV)) && - (op = ((UNOP*)op)->op_first) && - (op->op_type == OP_GV)) { + (firstop = ((UNOP*)op)->op_first) && + (firstop->op_type == OP_GV)) { /* packagevar $a[] or $h{} */ - GV * const gv = cGVOPx_gv(op); + GV * const gv = cGVOPx_gv(firstop); if (gv) tmpstr = Perl_newSVpvf(aTHX_ @@ -6448,7 +6609,7 @@ Perl_ck_grep(pTHX_ OP *o) LOGOP *gwop = NULL; OP *kid; const OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE; - I32 offset; + PADOFFSET offset; o->op_ppaddr = PL_ppaddr[OP_GREPSTART]; /* don't allocate gwop here, as we may leak it if PL_error_count > 0 */ @@ -6609,16 +6770,6 @@ Perl_ck_listiob(pTHX_ OP *o) } OP * -Perl_ck_say(pTHX_ OP *o) -{ - o = ck_listiob(o); - o->op_type = OP_PRINT; - cLISTOPo->op_last = cLISTOPo->op_last->op_sibling - = newSVOP(OP_CONST, 0, newSVpvs("\n")); - return o; -} - -OP * Perl_ck_smartmatch(pTHX_ OP *o) { dVAR; @@ -6649,7 +6800,7 @@ Perl_ck_smartmatch(pTHX_ OP *o) OP * Perl_ck_sassign(pTHX_ OP *o) { - OP *kid = cLISTOPo->op_first; + OP * const kid = cLISTOPo->op_first; /* has a disposable target? */ if ((PL_opargs[kid->op_type] & OA_TARGLEX) && !(kid->op_flags & OPf_STACKED) @@ -6678,6 +6829,16 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } + if (kid->op_sibling) { + OP *kkid = kid->op_sibling; + if (kkid->op_type == OP_PADSV + && (kkid->op_private & OPpLVAL_INTRO) + && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) { + o->op_private |= OPpASSIGN_STATE; + /* hijacking PADSTALE for uninitialized state variables */ + SvPADSTALE_on(PAD_SVl(kkid->op_targ)); + } + } return o; } @@ -6686,7 +6847,7 @@ Perl_ck_match(pTHX_ OP *o) { dVAR; if (o->op_type != OP_QR && PL_compcv) { - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) { o->op_targ = offset; o->op_private |= OPpTARGET_MY; @@ -6901,7 +7062,7 @@ Perl_ck_shift(pTHX_ OP *o) OP *argop; /* FIXME - this can be refactored to reduce code in #ifdefs */ #ifdef PERL_MAD - OP *oldo = o; + OP * const oldo = o; #else op_free(o); #endif @@ -6924,8 +7085,7 @@ Perl_ck_sort(pTHX_ OP *o) dVAR; OP *firstkid; - if (o->op_type == OP_SORT && (PL_hints & HINT_LOCALIZE_HH) != 0) - { + if (o->op_type == OP_SORT && (PL_hints & HINT_LOCALIZE_HH) != 0) { HV * const hinthv = GvHV(PL_hintgv); if (hinthv) { SV ** const svp = hv_fetchs(hinthv, "sort", FALSE); @@ -7117,6 +7277,7 @@ Perl_ck_split(pTHX_ OP *o) if (!kid->op_sibling) append_elem(OP_SPLIT, o, newSVOP(OP_CONST, 0, newSViv(0))); + assert(kid->op_sibling); kid = kid->op_sibling; scalar(kid); @@ -7151,13 +7312,14 @@ Perl_ck_subr(pTHX_ OP *o) ? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first; OP *o2 = prev->op_sibling; OP *cvop; - char *proto = NULL; + const char *proto = NULL; + const char *proto_end = NULL; CV *cv = NULL; GV *namegv = NULL; int optional = 0; I32 arg = 0; I32 contextclass = 0; - char *e = NULL; + const char *e = NULL; bool delete_op = 0; o->op_private |= OPpENTERSUB_HASTARG; @@ -7174,17 +7336,26 @@ Perl_ck_subr(pTHX_ OP *o) tmpop->op_private |= OPpEARLY_CV; else { if (SvPOK(cv)) { + STRLEN len; namegv = CvANON(cv) ? gv : CvGV(cv); - proto = SvPV_nolen((SV*)cv); + proto = SvPV((SV*)cv, len); + proto_end = proto + len; } if (CvASSERTION(cv)) { - if (PL_hints & HINT_ASSERTING) { + U32 asserthints = 0; + HV *const hinthv = GvHV(PL_hintgv); + if (hinthv) { + SV **svp = hv_fetchs(hinthv, "assertions", FALSE); + if (svp && *svp) + asserthints = SvUV(*svp); + } + if (asserthints & HINT_ASSERTING) { if (PERLDB_ASSERTION && PL_curstash != PL_debstash) o->op_private |= OPpENTERSUB_DB; } else { delete_op = 1; - if (!(PL_hints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) { + if (!(asserthints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) { Perl_warner(aTHX_ packWARN(WARN_ASSERTIONS), "Impossible to activate assertion call"); } @@ -7212,13 +7383,18 @@ Perl_ck_subr(pTHX_ OP *o) else o3 = o2; if (proto) { - switch (*proto) { - case '\0': + if (proto >= proto_end) return too_many_arguments(o, gv_ename(namegv)); + + switch (*proto) { case ';': optional = 1; proto++; continue; + case '_': + /* _ must be at the end */ + if (proto[1] && proto[1] != ';') + goto oops; case '$': proto++; arg++; @@ -7262,7 +7438,7 @@ Perl_ck_subr(pTHX_ OP *o) OP * const sibling = o2->op_sibling; SV * const n = newSVpvs(""); #ifdef PERL_MAD - OP *oldo2 = o2; + OP * const oldo2 = o2; #else op_free(o2); #endif @@ -7297,15 +7473,13 @@ Perl_ck_subr(pTHX_ OP *o) break; case ']': if (contextclass) { - /* XXX We shouldn't be modifying proto, so we can const proto */ - char *p = proto; - const char s = *p; + const char *p = proto; + const char *const end = proto; contextclass = 0; - *p = '\0'; while (*--p != '['); - bad_type(arg, Perl_form(aTHX_ "one of %s", p), - gv_ename(namegv), o3); - *proto = s; + bad_type(arg, Perl_form(aTHX_ "one of %.*s", + (int)(end - p), p), + gv_ename(namegv), o3); } else goto oops; break; @@ -7371,7 +7545,7 @@ Perl_ck_subr(pTHX_ OP *o) default: oops: Perl_croak(aTHX_ "Malformed prototype for %s: %"SVf, - gv_ename(namegv), cv); + gv_ename(namegv), (void*)cv); } } else @@ -7380,12 +7554,18 @@ Perl_ck_subr(pTHX_ OP *o) prev = o2; o2 = o2->op_sibling; } /* while */ - if (proto && !optional && - (*proto && *proto != '@' && *proto != '%' && *proto != ';')) + if (o2 == cvop && proto && *proto == '_') { + /* generate an access to $_ */ + o2 = newDEFSVOP(); + o2->op_sibling = prev->op_sibling; + prev->op_sibling = o2; /* instead of cvop */ + } + if (proto && !optional && proto_end > proto && + (*proto != '@' && *proto != '%' && *proto != ';' && *proto != '_')) return too_few_arguments(o, gv_ename(namegv)); if(delete_op) { #ifdef PERL_MAD - OP *oldo = o; + OP * const oldo = o; #else op_free(o); #endif @@ -7407,7 +7587,7 @@ OP * Perl_ck_chdir(pTHX_ OP *o) { if (o->op_flags & OPf_KIDS) { - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; if (kid && kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) @@ -7453,7 +7633,7 @@ OP * Perl_ck_substr(pTHX_ OP *o) { o = ck_fun(o); - if ((o->op_flags & OPf_KIDS) && o->op_private == 4) { + if ((o->op_flags & OPf_KIDS) && (o->op_private == 4)) { OP *kid = cLISTOPo->op_first; if (kid->op_type == OP_NULL) @@ -7597,7 +7777,7 @@ Perl_peep(pTHX_ register OP *o) pop->op_next->op_type == OP_AELEM && !(pop->op_next->op_private & (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)) && - (i = SvIV(((SVOP*)pop)->op_sv) - PL_curcop->cop_arybase) + (i = SvIV(((SVOP*)pop)->op_sv) - CopARYBASE_get(PL_curcop)) <= 255 && i >= 0) { @@ -7642,7 +7822,7 @@ Perl_peep(pTHX_ register OP *o) gv_efullname3(sv, gv, NULL); Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf"() called too early to check prototype", - sv); + (void*)sv); } } else if (o->op_next->op_type == OP_READLINE @@ -7705,18 +7885,17 @@ Perl_peep(pTHX_ register OP *o) if (o->op_next && o->op_next->op_type == OP_NEXTSTATE && ckWARN(WARN_SYNTAX)) { - if (o->op_next->op_sibling && - o->op_next->op_sibling->op_type != OP_EXIT && - o->op_next->op_sibling->op_type != OP_WARN && - o->op_next->op_sibling->op_type != OP_DIE) { - const line_t oldline = CopLINE(PL_curcop); - - CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "Statement unlikely to be reached"); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "\t(Maybe you meant system() when you said exec()?)\n"); - CopLINE_set(PL_curcop, oldline); + if (o->op_next->op_sibling) { + const OPCODE type = o->op_next->op_sibling->op_type; + if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) { + const line_t oldline = CopLINE(PL_curcop); + CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "Statement unlikely to be reached"); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "\t(Maybe you meant system() when you said exec()?)\n"); + CopLINE_set(PL_curcop, oldline); + } } } break; @@ -7739,7 +7918,7 @@ Perl_peep(pTHX_ register OP *o) if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) { key = SvPV_const(sv, keylen); lexname = newSVpvn_share(key, - SvUTF8(sv) ? -(I32)keylen : keylen, + SvUTF8(sv) ? -(I32)keylen : (I32)keylen, 0); SvREFCNT_dec(sv); *svp = lexname; @@ -7759,7 +7938,7 @@ Perl_peep(pTHX_ register OP *o) break; key = SvPV_const(*svp, keylen); if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE)) + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { Perl_croak(aTHX_ "No such class field \"%s\" " "in variable %s of type %s", @@ -7816,7 +7995,7 @@ Perl_peep(pTHX_ register OP *o) svp = cSVOPx_svp(key_op); key = SvPV_const(*svp, keylen); if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE)) + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { Perl_croak(aTHX_ "No such class field \"%s\" " "in variable %s of type %s", @@ -8145,7 +8324,7 @@ const_sv_xsub(pTHX_ CV* cv) dVAR; dXSARGS; if (items != 0) { - /*EMPTY*/; + NOOP; #if 0 Perl_croak(aTHX_ "usage: %s::%s()", HvNAME_get(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv)));