X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/7777302a0051987e602dfe05c34b52adf18cc9f0..ec610f8a9f2738d8a59ee84a3ec7ed858addea85:/sv.c diff --git a/sv.c b/sv.c index d2b549e..f2f86d0 100644 --- a/sv.c +++ b/sv.c @@ -638,8 +638,6 @@ do_curse(pTHX_ SV * const sv) { if ((PL_stderrgv && GvGP(PL_stderrgv) && (SV*)GvIO(PL_stderrgv) == sv) || (PL_defoutgv && GvGP(PL_defoutgv) && (SV*)GvIO(PL_defoutgv) == sv)) return; - if (SvPAD_NAME(sv)) - return; (void)curse(sv, 0); } @@ -1332,10 +1330,6 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type) there's no way that it can be safely upgraded, because perl.c expects to Safefree(SvANY(PL_mess_sv)) */ assert(sv != PL_mess_sv); - /* This flag bit is used to mean other things in other scalar types. - Given that it only has meaning inside the pad, it shouldn't be set - on anything that can get upgraded. */ - assert(!SvPAD_TYPED(sv)); break; default: if (UNLIKELY(old_type_details->cant_upgrade)) @@ -1431,6 +1425,7 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type) no route from NV to PVIV, NOK can never be true */ assert(!SvNOKp(sv)); assert(!SvNOK(sv)); + /* FALLTHROUGH */ case SVt_PVIO: case SVt_PVFM: case SVt_PVGV: @@ -1600,8 +1595,11 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen) * make more strings COW-able. * If the new size is a big power of two, don't bother: we assume the * caller wanted a nice 2^N sized block and will be annoyed at getting - * 2^N+1 */ - if (newlen & 0xff) + * 2^N+1. + * Only increment if the allocation isn't MEM_SIZE_MAX, + * otherwise it will wrap to 0. + */ + if (newlen & 0xff && newlen != MEM_SIZE_MAX) newlen++; #endif @@ -1619,7 +1617,9 @@ Perl_sv_grow(pTHX_ SV *const sv, STRLEN newlen) /* Don't round up on the first allocation, as odds are pretty good that * the initial request is accurate as to what is really needed */ if (SvLEN(sv)) { - newlen = PERL_STRLEN_ROUNDUP(newlen); + STRLEN rounded = PERL_STRLEN_ROUNDUP(newlen); + if (rounded > newlen) + newlen = rounded; } #endif if (SvLEN(sv) && s) { @@ -1939,6 +1939,7 @@ Perl_looks_like_number(pTHX_ SV *const sv) { const char *sbegin; STRLEN len; + int numtype; PERL_ARGS_ASSERT_LOOKS_LIKE_NUMBER; @@ -1947,7 +1948,8 @@ Perl_looks_like_number(pTHX_ SV *const sv) } else return SvFLAGS(sv) & (SVf_NOK|SVp_NOK|SVf_IOK|SVp_IOK); - return grok_number(sbegin, len, NULL); + numtype = grok_number(sbegin, len, NULL); + return ((numtype & IS_NUMBER_TRAILING)) ? 0 : numtype; } STATIC bool @@ -2108,6 +2110,10 @@ S_sv_2iuv_non_preserve(pTHX_ SV *const sv /* If numtype is infnan, set the NV of the sv accordingly. * If numtype is anything else, try setting the NV using Atof(PV). */ +#ifdef USING_MSVC6 +# pragma warning(push) +# pragma warning(disable:4756;disable:4056) +#endif static void S_sv_setnv(pTHX_ SV* sv, int numtype) { @@ -2132,6 +2138,9 @@ S_sv_setnv(pTHX_ SV* sv, int numtype) SvPOK_on(sv); /* PV is okay, though. */ } } +#ifdef USING_MSVC6 +# pragma warning(pop) +#endif STATIC bool S_sv_2iuv_common(pTHX_ SV *const sv) @@ -2164,6 +2173,7 @@ S_sv_2iuv_common(pTHX_ SV *const sv) SvIV_set(sv, I_V(SvNVX(sv))); if (SvNVX(sv) == (NV) SvIVX(sv) #ifndef NV_PRESERVES_UV + && SvIVX(sv) != IV_MIN /* avoid negating IV_MIN below */ && (((UV)1 << NV_PRESERVES_UV_BITS) > (UV)(SvIVX(sv) > 0 ? SvIVX(sv) : -SvIVX(sv))) /* Don't flag it as "accurately an integer" if the number @@ -2251,6 +2261,8 @@ S_sv_2iuv_common(pTHX_ SV *const sv) sv_upgrade(sv, SVt_PVNV); if ((numtype & (IS_NUMBER_INFINITY | IS_NUMBER_NAN))) { + if (ckWARN(WARN_NUMERIC) && ((numtype & IS_NUMBER_TRAILING))) + not_a_number(sv); S_sv_setnv(aTHX_ sv, numtype); return FALSE; } @@ -2279,7 +2291,8 @@ S_sv_2iuv_common(pTHX_ SV *const sv) } else { /* 2s complement assumption */ if (value <= (UV)IV_MIN) { - SvIV_set(sv, -(IV)value); + SvIV_set(sv, value == (UV)IV_MIN + ? IV_MIN : -(IV)value); } else { /* Too negative for an IV. This is a double upgrade, but I'm assuming it will be rare. */ @@ -2738,7 +2751,7 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags) SvNOK_on(sv); } else { /* value has been set. It may not be precise. */ - if ((numtype & IS_NUMBER_NEG) && (value > (UV)IV_MIN)) { + if ((numtype & IS_NUMBER_NEG) && (value >= (UV)IV_MIN)) { /* 2s complement assumption for (UV)IV_MIN */ SvNOK_on(sv); /* Integer is too negative. */ } else { @@ -2746,6 +2759,10 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags) SvIOKp_on(sv); if (numtype & IS_NUMBER_NEG) { + /* -IV_MIN is undefined, but we should never reach + * this point with both IS_NUMBER_NEG and value == + * (UV)IV_MIN */ + assert(value != (UV)IV_MIN); SvIV_set(sv, -(IV)value); } else if (value <= (UV)IV_MAX) { SvIV_set(sv, (IV)value); @@ -2823,8 +2840,8 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags) =for apidoc sv_2num Return an SV with the numeric value of the source SV, doing any necessary -reference or overload conversion. You must use the C macro to -access this function. +reference or overload conversion. The caller is expected to have handled +get-magic already. =cut */ @@ -2867,7 +2884,7 @@ S_uiv_2buf(char *const buf, const IV iv, UV uv, const int is_uv, char **const pe uv = iv; sign = 0; } else { - uv = -iv; + uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv); sign = 1; } do { @@ -2889,7 +2906,7 @@ S_uiv_2buf(char *const buf, const IV iv, UV uv, const int is_uv, char **const pe * shared string constants we point to, instead of generating a new * string for each instance. */ STATIC size_t -S_infnan_2pv(NV nv, char* buffer, size_t maxlen) { +S_infnan_2pv(NV nv, char* buffer, size_t maxlen, char plus) { assert(maxlen >= 4); if (maxlen < 4) /* "Inf\0", "NaN\0" */ return 0; @@ -2900,6 +2917,8 @@ S_infnan_2pv(NV nv, char* buffer, size_t maxlen) { if (maxlen < 5) /* "-Inf\0" */ return 0; *s++ = '-'; + } else if (plus) { + *s++ = '+'; } *s++ = 'I'; *s++ = 'n'; @@ -3114,7 +3133,7 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags) STRLEN size = 5; /* "-Inf\0" */ s = SvGROW_mutable(sv, size); - len = S_infnan_2pv(SvNVX(sv), s, size); + len = S_infnan_2pv(SvNVX(sv), s, size, 0); if (len > 0) { s += len; SvPOK_on(sv); @@ -3141,7 +3160,8 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const I32 flags) #else { bool local_radix; - DECLARE_STORE_LC_NUMERIC_SET_TO_NEEDED(); + DECLARATION_FOR_LC_NUMERIC_MANIPULATION; + STORE_LC_NUMERIC_SET_TO_NEEDED(); local_radix = PL_numeric_local && @@ -3243,14 +3263,6 @@ include SV_GMAGIC. */ void -Perl_sv_copypv(pTHX_ SV *const dsv, SV *const ssv) -{ - PERL_ARGS_ASSERT_SV_COPYPV; - - sv_copypv_flags(dsv, ssv, 0); -} - -void Perl_sv_copypv_flags(pTHX_ SV *const dsv, SV *const ssv, const I32 flags) { STRLEN len; @@ -3521,7 +3533,7 @@ Perl_sv_utf8_upgrade_flags_grow(pTHX_ SV *const sv, const I32 flags, STRLEN extr if (extra) SvGROW(sv, SvCUR(sv) + extra); return SvCUR(sv); -must_be_utf8: + must_be_utf8: /* Here, the string should be converted to utf8, either because of an * input flag (two_byte_count = 0), or because a character that @@ -4276,7 +4288,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) PERL_ARGS_ASSERT_SV_SETSV_FLAGS; - if (sstr == dstr) + if (UNLIKELY( sstr == dstr )) return; if (SvIS_FREED(dstr)) { @@ -4284,7 +4296,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) " to a freed scalar %p", SVfARG(sstr), (void *)dstr); } SV_CHECK_THINKFIRST_COW_DROP(dstr); - if (!sstr) + if (UNLIKELY( !sstr )) sstr = &PL_sv_undef; if (SvIS_FREED(sstr)) { Perl_croak(aTHX_ "panic: attempt to copy freed scalar %p to %p", @@ -4298,7 +4310,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) switch (stype) { case SVt_NULL: undef_sstr: - if (dtype != SVt_PVGV && dtype != SVt_PVLV) { + if (LIKELY( dtype != SVt_PVGV && dtype != SVt_PVLV )) { (void)SvOK_off(dstr); return; } @@ -4308,7 +4320,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) switch (dtype) { case SVt_NULL: /* For performance, we inline promoting to type SVt_IV. */ - /* We're starting from SVt_NULL, so provided that's + /* We're starting from SVt_NULL, so provided that define is * actual 0, we don't have to unset any SV type flags * to promote to SVt_IV. */ STATIC_ASSERT_STMT(SVt_NULL == 0); @@ -4341,7 +4353,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) break; case SVt_NV: - if (SvNOK(sstr)) { + if (LIKELY( SvNOK(sstr) )) { switch (dtype) { case SVt_NULL: case SVt_IV: @@ -4430,7 +4442,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) dtype = SvTYPE(dstr); sflags = SvFLAGS(sstr); - if (dtype == SVt_PVCV) { + if (UNLIKELY( dtype == SVt_PVCV )) { /* Assigning to a subroutine sets the prototype. */ if (SvOK(sstr)) { STRLEN len; @@ -5194,22 +5206,27 @@ S_sv_uncow(pTHX_ SV * const sv, const U32 flags) } SvIsCOW_off(sv); # ifdef PERL_NEW_COPY_ON_WRITE - if (len && CowREFCNT(sv) == 0) - /* We own the buffer ourselves. */ - sv_buf_to_rw(sv); + if (len) { + /* Must do this first, since the CowREFCNT uses SvPVX and + we need to write to CowREFCNT, or de-RO the whole buffer if we are + the only owner left of the buffer. */ + sv_buf_to_rw(sv); /* NOOP if RO-ing not supported */ + { + U8 cowrefcnt = CowREFCNT(sv); + if(cowrefcnt != 0) { + cowrefcnt--; + CowREFCNT(sv) = cowrefcnt; + sv_buf_to_ro(sv); + goto copy_over; + } + } + /* Else we are the only owner of the buffer. */ + } else # endif { - /* This SV doesn't own the buffer, so need to Newx() a new one: */ -# ifdef PERL_NEW_COPY_ON_WRITE - /* Must do this first, since the macro uses SvPVX. */ - if (len) { - sv_buf_to_rw(sv); - CowREFCNT(sv)--; - sv_buf_to_ro(sv); - } -# endif + copy_over: SvPV_set(sv, NULL); SvCUR_set(sv, 0); SvLEN_set(sv, 0); @@ -5653,8 +5670,6 @@ Perl_sv_magicext(pTHX_ SV *const sv, SV *const obj, const int how, PERL_ARGS_ASSERT_SV_MAGICEXT; - if (SvTYPE(sv)==SVt_PVAV) { assert (!AvPAD_NAMELIST(sv)); } - SvUPGRADE(sv, SVt_PVMG); Newxz(mg, 1, MAGIC); mg->mg_moremagic = SvMAGIC(sv); @@ -5932,6 +5947,45 @@ Perl_sv_rvweaken(pTHX_ SV *const sv) return sv; } +/* +=for apidoc sv_get_backrefs + +If the sv is the target of a weak reference then it returns the back +references structure associated with the sv; otherwise return NULL. + +When returning a non-null result the type of the return is relevant. If it +is an AV then the elements of the AV are the weak reference RVs which +point at this item. If it is any other type then the item itself is the +weak reference. + +See also Perl_sv_add_backref(), Perl_sv_del_backref(), +Perl_sv_kill_backrefs() + +=cut +*/ + +SV * +Perl_sv_get_backrefs(SV *const sv) +{ + SV *backrefs= NULL; + + PERL_ARGS_ASSERT_SV_GET_BACKREFS; + + /* find slot to store array or singleton backref */ + + if (SvTYPE(sv) == SVt_PVHV) { + if (SvOOK(sv)) { + struct xpvhv_aux * const iter = HvAUX((HV *)sv); + backrefs = (SV *)iter->xhv_backreferences; + } + } else if (SvMAGICAL(sv)) { + MAGIC *mg = mg_find(sv, PERL_MAGIC_backref); + if (mg) + backrefs = mg->mg_obj; + } + return backrefs; +} + /* Give tsv backref magic if it hasn't already got it, then push a * back-reference to sv onto the array associated with the backref magic. * @@ -6252,8 +6306,6 @@ Perl_sv_insert_flags(pTHX_ SV *const bigstr, const STRLEN offset, const STRLEN l PERL_ARGS_ASSERT_SV_INSERT_FLAGS; - if (!bigstr) - Perl_croak(aTHX_ "Can't modify nonexistent substring"); SvPV_force_flags(bigstr, curlen, flags); (void)SvPOK_only_UTF8(bigstr); if (offset + len > curlen) { @@ -6467,7 +6519,8 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) SV* iter_sv = NULL; SV* next_sv = NULL; SV *sv = orig_sv; - STRLEN hash_index; + STRLEN hash_index = 0; /* initialise to make Coverity et al happy. + Not strictly necessary */ PERL_ARGS_ASSERT_SV_CLEAR; @@ -6495,10 +6548,10 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) /* objs are always >= MG, but pad names use the SVs_OBJECT flag for another purpose */ - assert(!SvOBJECT(sv) || type >= SVt_PVMG || SvPAD_NAME(sv)); + assert(!SvOBJECT(sv) || type >= SVt_PVMG); if (type >= SVt_PVMG) { - if (SvOBJECT(sv) && !SvPAD_NAME(sv)) { + if (SvOBJECT(sv)) { if (!curse(sv, 1)) goto get_next_sv; type = SvTYPE(sv); /* destructor may have changed it */ } @@ -6509,19 +6562,12 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) if (SvMAGIC(sv)) mg_free(sv); } - else if (type == SVt_PVMG && SvPAD_OUR(sv)) { - SvREFCNT_dec(SvOURSTASH(sv)); - } - else if (type == SVt_PVAV && AvPAD_NAMELIST(sv)) { - assert(!SvMAGICAL(sv)); - } else if (SvMAGIC(sv)) { + else if (SvMAGIC(sv)) { /* Free back-references before other types of magic. */ sv_unmagic(sv, PERL_MAGIC_backref); mg_free(sv); } SvMAGICAL_off(sv); - if (type == SVt_PVMG && SvPAD_TYPED(sv)) - SvREFCNT_dec(SvSTASH(sv)); } switch (type) { /* case SVt_INVLIST: */ @@ -6565,17 +6611,19 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) PL_last_swash_hv = NULL; } if (HvTOTALKEYS((HV*)sv) > 0) { - const char *name; + const HEK *hek; /* this statement should match the one at the beginning of * hv_undef_flags() */ if ( PL_phase != PERL_PHASE_DESTRUCT - && (name = HvNAME((HV*)sv))) + && (hek = HvNAME_HEK((HV*)sv))) { if (PL_stashcache) { - DEBUG_o(Perl_deb(aTHX_ "sv_clear clearing PL_stashcache for '%"SVf"'\n", - SVfARG(sv))); + DEBUG_o(Perl_deb(aTHX_ + "sv_clear clearing PL_stashcache for '%"HEKf + "'\n", + HEKfARG(hek))); (void)hv_deletehek(PL_stashcache, - HvNAME_HEK((HV*)sv), G_DISCARD); + hek, G_DISCARD); } hv_name_set((HV*)sv, NULL, 0, 0); } @@ -6626,6 +6674,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) else if (LvTYPE(sv) != 't') /* unless tie: unrefcnted fake SV** */ SvREFCNT_dec(LvTARG(sv)); if (isREGEXP(sv)) goto freeregexp; + /* FALLTHROUGH */ case SVt_PVGV: if (isGV_with_GP(sv)) { if(GvCVu((const GV *)sv) && (stash = GvSTASH(MUTABLE_GV(sv))) @@ -6650,6 +6699,7 @@ Perl_sv_clear(pTHX_ SV *const orig_sv) PL_statgv = NULL; else if ((const GV *)sv == PL_stderrgv) PL_stderrgv = NULL; + /* FALLTHROUGH */ case SVt_PVMG: case SVt_PVNV: case SVt_PVIV: @@ -8544,13 +8594,13 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append) goto thats_all_folks; } -thats_all_folks: + thats_all_folks: /* check if we have actually found the separator - only really applies * when rslen > 1 */ if ((rslen > 1 && (STRLEN)(bp - (STDCHAR*)SvPVX_const(sv)) < rslen) || memNE((char*)bp - rslen, rsptr, rslen)) goto screamer; /* go back to the fray */ -thats_really_all_folks: + thats_really_all_folks: if (shortbuffered) cnt += shortbuffered; DEBUG_P(PerlIO_printf(Perl_debug_log, @@ -8578,7 +8628,7 @@ thats_really_all_folks: STDCHAR buf[8192]; #endif -screamer2: + screamer2: if (rslen) { const STDCHAR * const bpe = buf + sizeof(buf); bp = buf; @@ -9407,7 +9457,7 @@ Perl_newSVuv(pTHX_ const UV u) /* We're starting from SVt_FIRST, so provided that's * actual 0, we don't have to unset any SV type flags * to promote to SVt_IV. */ - assert(SVt_FIRST == 0); + STATIC_ASSERT_STMT(SVt_FIRST == 0); SET_SVANY_FOR_BODYLESS_IV(sv); SvFLAGS(sv) |= SVt_IV; @@ -9462,7 +9512,7 @@ Perl_newRV_noinc(pTHX_ SV *const tmpRef) /* We're starting from SVt_FIRST, so provided that's * actual 0, we don't have to unset any SV type flags * to promote to SVt_IV. */ - assert(SVt_FIRST == 0); + STATIC_ASSERT_STMT(SVt_FIRST == 0); SET_SVANY_FOR_BODYLESS_IV(sv); SvFLAGS(sv) |= SVt_IV; @@ -10054,7 +10104,7 @@ Perl_newSVrv(pTHX_ SV *const rv, const char *const classname) SV_CHECK_THINKFIRST_COW_DROP(rv); - if (SvTYPE(rv) >= SVt_PVMG) { + if (UNLIKELY( SvTYPE(rv) >= SVt_PVMG )) { const U32 refcnt = SvREFCNT(rv); SvREFCNT(rv) = 0; sv_clear(rv); @@ -10739,7 +10789,7 @@ S_F0convert(NV nv, char *const endbuf, STRLEN *const len) PERL_ARGS_ASSERT_F0CONVERT; if (UNLIKELY(Perl_isinfnan(nv))) { - STRLEN n = S_infnan_2pv(nv, endbuf - *len, *len); + STRLEN n = S_infnan_2pv(nv, endbuf - *len, *len, 0); *len = n; return endbuf - n; } @@ -10797,34 +10847,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, sv_vcatpvfn_flags(sv, pat, patlen, args, svargs, svmax, maybe_tainted, SV_GMAGIC|SV_SMAGIC); } -#if DOUBLEKIND == DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN || \ - DOUBLEKIND == DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN || \ - DOUBLEKIND == DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN -# define DOUBLE_LITTLE_ENDIAN -#endif - -#ifdef HAS_LONG_DOUBLEKIND - -# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN -# define LONGDOUBLE_LITTLE_ENDIAN -# endif - -# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN -# define LONGDOUBLE_BIG_ENDIAN -# endif - -# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN -# define LONGDOUBLE_X86_80_BIT -# endif - -# if LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN || \ - LONG_DOUBLEKIND == LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN -# define LONGDOUBLE_DOUBLEDOUBLE +#ifdef LONGDOUBLE_DOUBLEDOUBLE /* The first double can be as large as 2**1023, or '1' x '0' x 1023. * The second double can be as small as 2**-1074, or '0' x 1073 . '1'. * The sum of them can be '1' . '0' x 2096 . '1', with implied radix point @@ -10834,10 +10857,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, * of dynamically growing buffer might be better, start at just 16 bytes * (for example) and grow only when necessary. Or maybe just by looking * at the exponents of the two doubles? */ -# define DOUBLEDOUBLE_MAXBITS 2098 -# endif - -#endif /* HAS_LONG_DOUBLE */ +# define DOUBLEDOUBLE_MAXBITS 2098 +#endif /* vhex will contain the values (0..15) of the hex digits ("nybbles" * of 4 bits); 1 for the implicit 1, and the mantissa bits, four bits @@ -11184,7 +11205,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p bool no_redundant_warning = FALSE; /* did we use any explicit format parameter index? */ bool hexfp = FALSE; /* hexadecimal floating point? */ - DECLARATION_FOR_STORE_LC_NUMERIC_SET_TO_NEEDED; + DECLARATION_FOR_LC_NUMERIC_MANIPULATION; PERL_ARGS_ASSERT_SV_VCATPVFN_FLAGS; PERL_UNUSED_ARG(maybe_tainted); @@ -11343,6 +11364,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p #ifndef FV_ISFINITE # define FV_ISFINITE(x) Perl_isfinite((NV)(x)) #endif + NV nv; STRLEN have; STRLEN need; STRLEN gap; @@ -11713,6 +11735,8 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p if (argsv && strchr("BbcDdiOopuUXx",*q)) { /* XXX va_arg(*args) case? need peek, use va_copy? */ SvGETMAGIC(argsv); + if (UNLIKELY(SvAMAGIC(argsv))) + argsv = sv_2num(argsv); infnan = UNLIKELY(isinfnansv(argsv)); } @@ -11866,7 +11890,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p esignbuf[esignlen++] = plus; } else { - uv = -iv; + uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv); esignbuf[esignlen++] = '-'; } } @@ -12084,19 +12108,25 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p #ifdef USE_QUADMATH fv = intsize == 'q' ? va_arg(*args, NV) : va_arg(*args, double); + nv = fv; #elif LONG_DOUBLESIZE > DOUBLESIZE - if (intsize == 'q') + if (intsize == 'q') { fv = va_arg(*args, long double); - else - NV_TO_FV(va_arg(*args, double), fv); + nv = fv; + } else { + nv = va_arg(*args, double); + NV_TO_FV(nv, fv); + } #else - fv = va_arg(*args, double); + nv = va_arg(*args, double); + fv = nv; #endif } else { if (!infnan) SvGETMAGIC(argsv); - NV_TO_FV(SvNV_nomg(argsv), fv); + nv = SvNV_nomg(argsv); + NV_TO_FV(nv, fv); } need = 0; @@ -12243,7 +12273,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p goto float_converted; } } else if ( c == 'f' && !precis ) { - if ((eptr = F0convert(fv, ebuf + sizeof ebuf, &elen))) + if ((eptr = F0convert(nv, ebuf + sizeof ebuf, &elen))) break; } } @@ -12271,10 +12301,8 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p * should be output as 0x0.0000000000001p-1022 to * match its internal structure. */ - /* Note: fv can be (and often is) long double. - * Here it is explicitly cast to NV. */ - vend = S_hextract(aTHX_ (NV)fv, &exponent, vhex, NULL); - S_hextract(aTHX_ (NV)fv, &exponent, vhex, vend); + vend = S_hextract(aTHX_ nv, &exponent, vhex, NULL); + S_hextract(aTHX_ nv, &exponent, vhex, vend); #if NVSIZE > DOUBLESIZE # ifdef HEXTRACT_HAS_IMPLICIT_BIT @@ -12326,12 +12354,14 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p #endif if (precis > 0) { - v = vhex + precis + 1; - if (v < vend) { + if ((SSize_t)(precis + 1) < vend - vhex) { + bool round; + + v = vhex + precis + 1; /* Round away from zero: if the tail * beyond the precis xdigits is equal to * or greater than 0x8000... */ - bool round = *v > 0x8; + round = *v > 0x8; if (!round && *v == 0x8) { for (v++; v < vend; v++) { if (*v) { @@ -12429,8 +12459,25 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p elen = width; } } - else - elen = S_infnan_2pv(fv, PL_efloatbuf, PL_efloatsize); + else { + elen = S_infnan_2pv(nv, PL_efloatbuf, PL_efloatsize, plus); + if (elen) { + /* Not affecting infnan output: precision, alt, fill. */ + if (elen < width) { + if (left) { + /* Pack the back with spaces. */ + memset(PL_efloatbuf + elen, ' ', width - elen); + } else { + /* Move it to the right. */ + Move(PL_efloatbuf, PL_efloatbuf + width - elen, + elen, char); + /* Pad the front with spaces. */ + memset(PL_efloatbuf, ' ', width - elen); + } + elen = width; + } + } + } if (elen == 0) { char *ptr = ebuf + sizeof ebuf; @@ -12489,7 +12536,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p if (!qfmt) Perl_croak_nocontext("panic: quadmath invalid format \"%s\"", ptr); elen = quadmath_snprintf(PL_efloatbuf, PL_efloatsize, - qfmt, fv); + qfmt, nv); if ((IV)elen == -1) Perl_croak_nocontext("panic: quadmath_snprintf failed, format \"%s|'", qfmt); if (qfmt != ptr) @@ -13407,7 +13454,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) #endif /* don't clone objects whose class has asked us not to */ - if (SvOBJECT(sstr) && !SvPAD_NAME(sstr) + if (SvOBJECT(sstr) && ! (SvFLAGS(SvSTASH(sstr)) & SVphv_CLONEABLE)) { SvFLAGS(dstr) = 0; @@ -13494,13 +13541,9 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) missing by always going for the destination. FIXME - instrument and check that assumption */ if (sv_type >= SVt_PVMG) { - if ((sv_type == SVt_PVMG) && SvPAD_OUR(dstr)) { - SvOURSTASH_set(dstr, hv_dup_inc(SvOURSTASH(dstr), param)); - } else if (sv_type == SVt_PVAV && AvPAD_NAMELIST(dstr)) { - NOOP; - } else if (SvMAGIC(dstr)) + if (SvMAGIC(dstr)) SvMAGIC_set(dstr, mg_dup(SvMAGIC(dstr), param)); - if (SvOBJECT(dstr) && !SvPAD_NAME(dstr) && SvSTASH(dstr)) + if (SvOBJECT(dstr) && SvSTASH(dstr)) SvSTASH_set(dstr, hv_dup_inc(SvSTASH(dstr), param)); else SvSTASH_set(dstr, 0); /* don't copy DESTROY cache */ } @@ -13597,7 +13640,7 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param) } items = AvMAX((const AV *)sstr) - AvFILLp((const AV *)sstr); while (items-- > 0) { - *dst_ary++ = &PL_sv_undef; + *dst_ary++ = NULL; } } else { @@ -13838,17 +13881,22 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max, CLONE_PARAMS* param) case CXt_LOOP_LAZYSV: ncx->blk_loop.state_u.lazysv.end = sv_dup_inc(ncx->blk_loop.state_u.lazysv.end, param); - /* We are taking advantage of av_dup_inc and sv_dup_inc - actually being the same function, and order equivalence of - the two unions. + /* Fallthrough: duplicate lazysv.cur by using the ary.ary + duplication code instead. + We are taking advantage of (1) av_dup_inc and sv_dup_inc + actually being the same function, and (2) order + equivalence of the two unions. We can assert the later [but only at run time :-(] */ assert ((void *) &ncx->blk_loop.state_u.ary.ary == (void *) &ncx->blk_loop.state_u.lazysv.cur); + /* FALLTHROUGH */ case CXt_LOOP_FOR: ncx->blk_loop.state_u.ary.ary = av_dup_inc(ncx->blk_loop.state_u.ary.ary, param); + /* FALLTHROUGH */ case CXt_LOOP_LAZYIV: case CXt_LOOP_PLAIN: + /* code common to all CXt_LOOP_* types */ if (CxPADLOOP(ncx)) { ncx->blk_loop.itervar_u.oldcomppad = (PAD*)ptr_table_fetch(PL_ptr_table, @@ -13999,14 +14047,16 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) case SAVEt_CLEARPADRANGE: break; case SAVEt_HELEM: /* hash element */ + case SAVEt_SV: /* scalar reference */ sv = (const SV *)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv, param); + TOPPTR(nss,ix) = SvREFCNT_inc(sv_dup_inc(sv, param)); /* FALLTHROUGH */ case SAVEt_ITEM: /* normal string */ case SAVEt_GVSV: /* scalar slot in GV */ - case SAVEt_SV: /* scalar reference */ sv = (const SV *)POPPTR(ss,ix); TOPPTR(nss,ix) = sv_dup_inc(sv, param); + if (type == SAVEt_SV) + break; /* FALLTHROUGH */ case SAVEt_FREESV: case SAVEt_MORTALIZESV: @@ -14014,6 +14064,11 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) sv = (const SV *)POPPTR(ss,ix); TOPPTR(nss,ix) = sv_dup_inc(sv, param); break; + case SAVEt_FREEPADNAME: + ptr = POPPTR(ss,ix); + TOPPTR(nss,ix) = padname_dup((PADNAME *)ptr, param); + PadnameREFCNT((PADNAME *)TOPPTR(nss,ix))++; + break; case SAVEt_SHARED_PVREF: /* char* in shared space */ c = (char*)POPPTR(ss,ix); TOPPTR(nss,ix) = savesharedpv(c); @@ -14024,6 +14079,8 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) case SAVEt_SVREF: /* scalar reference */ sv = (const SV *)POPPTR(ss,ix); TOPPTR(nss,ix) = sv_dup_inc(sv, param); + if (type == SAVEt_SVREF) + SvREFCNT_inc_simple_void((SV *)TOPPTR(nss,ix)); ptr = POPPTR(ss,ix); TOPPTR(nss,ix) = svp_dup_inc((SV**)ptr, proto_perl);/* XXXXX */ break; @@ -14176,7 +14233,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) break; case SAVEt_AELEM: /* array element */ sv = (const SV *)POPPTR(ss,ix); - TOPPTR(nss,ix) = sv_dup_inc(sv, param); + TOPPTR(nss,ix) = SvREFCNT_inc(sv_dup_inc(sv, param)); i = POPINT(ss,ix); TOPINT(nss,ix) = i; av = (const AV *)POPPTR(ss,ix); @@ -14221,11 +14278,13 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param) ptr = POPPTR(ss,ix); TOPPTR(nss,ix) = parser_dup((const yy_parser*)ptr, param); break; - case SAVEt_GP_ALIASED_SV: - ptr = POPPTR(ss,ix); - TOPPTR(nss,ix) = gp_dup((GP *)ptr, param); - ((GP *)ptr)->gp_refcnt++; + case SAVEt_GP_ALIASED_SV: { + GP * gp_ptr = (GP *)POPPTR(ss,ix); + GP * new_gp_ptr = gp_dup(gp_ptr, param); + TOPPTR(nss,ix) = new_gp_ptr; + new_gp_ptr->gp_refcnt++; break; + } default: Perl_croak(aTHX_ "panic: ss_dup inconsistency (%"IVdf")", (IV) type); @@ -14383,9 +14442,14 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_sig_pending = 0; PL_parser = NULL; Zero(&PL_debug_pad, 1, struct perl_debug_pad); + Zero(&PL_padname_undef, 1, PADNAME); + Zero(&PL_padname_const, 1, PADNAME); # ifdef DEBUG_LEAKING_SCALARS PL_sv_serial = (((UV)my_perl >> 2) & 0xfff) * 1000000; # endif +# ifdef PERL_TRACE_OPS + Zero(PL_op_exec_cnt, OP_max+2, UV); +# endif #else /* !DEBUGGING */ Zero(my_perl, 1, PerlInterpreter); #endif /* DEBUGGING */ @@ -14525,6 +14589,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_subline = proto_perl->Isubline; + PL_cv_has_eval = proto_perl->Icv_has_eval; + #ifdef FCRYPT PL_cryptseen = proto_perl->Icryptseen; #endif @@ -14663,6 +14729,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef); ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no); ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes); + ptr_table_store(PL_ptr_table, &proto_perl->Ipadname_const, + &PL_padname_const); /* create (a non-shared!) shared string table */ PL_strtab = newHV(); @@ -14778,6 +14846,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_endav = av_dup_inc(proto_perl->Iendav, param); PL_checkav = av_dup_inc(proto_perl->Icheckav, param); PL_initav = av_dup_inc(proto_perl->Iinitav, param); + PL_savebegin = proto_perl->Isavebegin; PL_isarev = hv_dup_inc(proto_perl->Iisarev, param); @@ -14857,6 +14926,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, PL_subname = sv_dup_inc(proto_perl->Isubname, param); +#ifdef USE_LOCALE_CTYPE + /* Should we warn if uses locale? */ + PL_warn_locale = sv_dup_inc(proto_perl->Iwarn_locale, param); +#endif + #ifdef USE_LOCALE_COLLATE PL_collation_name = SAVEPV(proto_perl->Icollation_name); #endif /* USE_LOCALE_COLLATE */ @@ -14882,9 +14956,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags, for (i = 0; i < POSIX_CC_COUNT; i++) { PL_XPosix_ptrs[i] = sv_dup_inc(proto_perl->IXPosix_ptrs[i], param); } + PL_GCB_invlist = sv_dup_inc(proto_perl->IGCB_invlist, param); + PL_SB_invlist = sv_dup_inc(proto_perl->ISB_invlist, param); + PL_WB_invlist = sv_dup_inc(proto_perl->IWB_invlist, param); PL_utf8_mark = sv_dup_inc(proto_perl->Iutf8_mark, param); - PL_utf8_X_regular_begin = sv_dup_inc(proto_perl->Iutf8_X_regular_begin, param); - PL_utf8_X_extend = sv_dup_inc(proto_perl->Iutf8_X_extend, param); PL_utf8_toupper = sv_dup_inc(proto_perl->Iutf8_toupper, param); PL_utf8_totitle = sv_dup_inc(proto_perl->Iutf8_totitle, param); PL_utf8_tolower = sv_dup_inc(proto_perl->Iutf8_tolower, param); @@ -15173,6 +15248,8 @@ Perl_init_constants(pTHX) SvLEN_set(&PL_sv_yes, 0); SvIV_set(&PL_sv_yes, 1); SvNV_set(&PL_sv_yes, 1); + + PadnamePV(&PL_padname_const) = (char *)PL_No; } /* @@ -15211,6 +15288,7 @@ Perl_sv_recode_to_utf8(pTHX_ SV *sv, SV *encoding) nsv = sv_newmortal(); SvSetSV_nosteal(nsv, sv); } + save_re_context(); PUSHMARK(sp); EXTEND(SP, 3); PUSHs(encoding); @@ -15276,11 +15354,12 @@ Perl_sv_cat_decode(pTHX_ SV *dsv, SV *encoding, PERL_ARGS_ASSERT_SV_CAT_DECODE; - if (SvPOK(ssv) && SvPOK(dsv) && SvROK(encoding) && offset) { + if (SvPOK(ssv) && SvPOK(dsv) && SvROK(encoding)) { SV *offsv; dSP; ENTER; SAVETMPS; + save_re_context(); PUSHMARK(sp); EXTEND(SP, 6); PUSHs(encoding); @@ -15410,16 +15489,15 @@ Perl_varname(pTHX_ const GV *const gv, const char gvtype, PADOFFSET targ, } else { CV * const cv = gv ? ((CV *)gv) : find_runcv(NULL); - SV *sv; - AV *av; + PADNAME *sv; assert(!cv || SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM); if (!cv || !CvPADLIST(cv)) return NULL; - av = *PadlistARRAY(CvPADLIST(cv)); - sv = *av_fetch(av, targ, FALSE); - sv_setsv_flags(name, sv, 0); + sv = padnamelist_fetch(PadlistNAMES(CvPADLIST(cv)), targ); + sv_setpvn(name, PadnamePV(sv), PadnameLEN(sv)); + SvUTF8_on(name); } if (subscript_type == FUV_SUBSCRIPT_HASH) { @@ -15454,6 +15532,8 @@ warning, then following the direct child of the op may yield an OP_PADSV or OP_GV that gives the name of the undefined variable. On the other hand, with OP_ADD there are two branches to follow, so we only print the variable name if we get an exact match. +desc_p points to a string pointer holding the description of the op. +This may be updated if needed. The name is returned as a mortal SV. @@ -15465,13 +15545,15 @@ PL_comppad/PL_curpad points to the currently executing pad. STATIC SV * S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, - bool match) + bool match, const char **desc_p) { dVAR; SV *sv; const GV *gv; const OP *o, *o2, *kid; + PERL_ARGS_ASSERT_FIND_UNINIT_VAR; + if (!obase || (match && (!uninit_sv || uninit_sv == &PL_sv_undef || uninit_sv == &PL_sv_placeholder))) return NULL; @@ -15511,7 +15593,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, } else if (obase == PL_op) /* @{expr}, %{expr} */ return find_uninit_var(cUNOPx(obase)->op_first, - uninit_sv, match); + uninit_sv, match, desc_p); else /* @{expr}, %{expr} as a sub-expression */ return NULL; } @@ -15546,7 +15628,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, return varname(gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE); } /* ${expr} */ - return find_uninit_var(cUNOPx(obase)->op_first, uninit_sv, 1); + return find_uninit_var(cUNOPx(obase)->op_first, uninit_sv, 1, desc_p); case OP_PADSV: if (match && PAD_SVl(obase->op_targ) != uninit_sv) @@ -15596,7 +15678,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, if (!o || o->op_type != OP_NULL || ! (o->op_targ == OP_AELEM || o->op_targ == OP_HELEM)) break; - return find_uninit_var(cBINOPo->op_last, uninit_sv, match); + return find_uninit_var(cBINOPo->op_last, uninit_sv, match, desc_p); case OP_AELEM: case OP_HELEM: @@ -15605,7 +15687,8 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, if (PL_op == obase) /* $a[uninit_expr] or $h{uninit_expr} */ - return find_uninit_var(cBINOPx(obase)->op_last, uninit_sv, match); + return find_uninit_var(cBINOPx(obase)->op_last, + uninit_sv, match, desc_p); gv = NULL; o = cBINOPx(obase)->op_first; @@ -15694,18 +15777,214 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, NOT_REACHED; /* NOTREACHED */ } + case OP_MULTIDEREF: { + /* If we were executing OP_MULTIDEREF when the undef warning + * triggered, then it must be one of the index values within + * that triggered it. If not, then the only possibility is that + * the value retrieved by the last aggregate lookup might be the + * culprit. For the former, we set PL_multideref_pc each time before + * using an index, so work though the item list until we reach + * that point. For the latter, just work through the entire item + * list; the last aggregate retrieved will be the candidate. + */ + + /* the named aggregate, if any */ + PADOFFSET agg_targ = 0; + GV *agg_gv = NULL; + /* the last-seen index */ + UV index_type; + PADOFFSET index_targ; + GV *index_gv; + IV index_const_iv = 0; /* init for spurious compiler warn */ + SV *index_const_sv; + int depth = 0; /* how many array/hash lookups we've done */ + + UNOP_AUX_item *items = cUNOP_AUXx(obase)->op_aux; + UNOP_AUX_item *last = NULL; + UV actions = items->uv; + bool is_hv; + + if (PL_op == obase) { + last = PL_multideref_pc; + assert(last >= items && last <= items + items[-1].uv); + } + + assert(actions); + + while (1) { + is_hv = FALSE; + switch (actions & MDEREF_ACTION_MASK) { + + case MDEREF_reload: + actions = (++items)->uv; + continue; + + case MDEREF_HV_padhv_helem: /* $lex{...} */ + is_hv = TRUE; + /* FALLTHROUGH */ + case MDEREF_AV_padav_aelem: /* $lex[...] */ + agg_targ = (++items)->pad_offset; + agg_gv = NULL; + break; + + case MDEREF_HV_gvhv_helem: /* $pkg{...} */ + is_hv = TRUE; + /* FALLTHROUGH */ + case MDEREF_AV_gvav_aelem: /* $pkg[...] */ + agg_targ = 0; + agg_gv = (GV*)UNOP_AUX_item_sv(++items); + assert(isGV_with_GP(agg_gv)); + break; + + case MDEREF_HV_gvsv_vivify_rv2hv_helem: /* $pkg->{...} */ + case MDEREF_HV_padsv_vivify_rv2hv_helem: /* $lex->{...} */ + ++items; + /* FALLTHROUGH */ + case MDEREF_HV_pop_rv2hv_helem: /* expr->{...} */ + case MDEREF_HV_vivify_rv2hv_helem: /* vivify, ->{...} */ + agg_targ = 0; + agg_gv = NULL; + is_hv = TRUE; + break; + + case MDEREF_AV_gvsv_vivify_rv2av_aelem: /* $pkg->[...] */ + case MDEREF_AV_padsv_vivify_rv2av_aelem: /* $lex->[...] */ + ++items; + /* FALLTHROUGH */ + case MDEREF_AV_pop_rv2av_aelem: /* expr->[...] */ + case MDEREF_AV_vivify_rv2av_aelem: /* vivify, ->[...] */ + agg_targ = 0; + agg_gv = NULL; + } /* switch */ + + index_targ = 0; + index_gv = NULL; + index_const_sv = NULL; + + index_type = (actions & MDEREF_INDEX_MASK); + switch (index_type) { + case MDEREF_INDEX_none: + break; + case MDEREF_INDEX_const: + if (is_hv) + index_const_sv = UNOP_AUX_item_sv(++items) + else + index_const_iv = (++items)->iv; + break; + case MDEREF_INDEX_padsv: + index_targ = (++items)->pad_offset; + break; + case MDEREF_INDEX_gvsv: + index_gv = (GV*)UNOP_AUX_item_sv(++items); + assert(isGV_with_GP(index_gv)); + break; + } + + if (index_type != MDEREF_INDEX_none) + depth++; + + if ( index_type == MDEREF_INDEX_none + || (actions & MDEREF_FLAG_last) + || (last && items == last) + ) + break; + + actions >>= MDEREF_SHIFT; + } /* while */ + + if (PL_op == obase) { + /* index was undef */ + + *desc_p = ( (actions & MDEREF_FLAG_last) + && (obase->op_private + & (OPpMULTIDEREF_EXISTS|OPpMULTIDEREF_DELETE))) + ? + (obase->op_private & OPpMULTIDEREF_EXISTS) + ? "exists" + : "delete" + : is_hv ? "hash element" : "array element"; + assert(index_type != MDEREF_INDEX_none); + if (index_gv) + return varname(index_gv, '$', 0, NULL, 0, FUV_SUBSCRIPT_NONE); + if (index_targ) + return varname(NULL, '$', index_targ, + NULL, 0, FUV_SUBSCRIPT_NONE); + assert(is_hv); /* AV index is an IV and can't be undef */ + /* can a const HV index ever be undef? */ + return NULL; + } + + /* the SV returned by pp_multideref() was undef, if anything was */ + + if (depth != 1) + break; + + if (agg_targ) + sv = PAD_SV(agg_targ); + else if (agg_gv) + sv = is_hv ? MUTABLE_SV(GvHV(agg_gv)) : MUTABLE_SV(GvAV(agg_gv)); + else + break; + + if (index_type == MDEREF_INDEX_const) { + if (match) { + if (SvMAGICAL(sv)) + break; + if (is_hv) { + HE* he = hv_fetch_ent(MUTABLE_HV(sv), index_const_sv, 0, 0); + if (!he || HeVAL(he) != uninit_sv) + break; + } + else { + SV * const * const svp = + av_fetch(MUTABLE_AV(sv), index_const_iv, FALSE); + if (!svp || *svp != uninit_sv) + break; + } + } + return is_hv + ? varname(agg_gv, '%', agg_targ, + index_const_sv, 0, FUV_SUBSCRIPT_HASH) + : varname(agg_gv, '@', agg_targ, + NULL, index_const_iv, FUV_SUBSCRIPT_ARRAY); + } + else { + /* index is an var */ + if (is_hv) { + SV * const keysv = find_hash_subscript((const HV*)sv, uninit_sv); + if (keysv) + return varname(agg_gv, '%', agg_targ, + keysv, 0, FUV_SUBSCRIPT_HASH); + } + else { + const I32 index + = find_array_subscript((const AV *)sv, uninit_sv); + if (index >= 0) + return varname(agg_gv, '@', agg_targ, + NULL, index, FUV_SUBSCRIPT_ARRAY); + } + if (match) + break; + return varname(agg_gv, + is_hv ? '%' : '@', + agg_targ, NULL, 0, FUV_SUBSCRIPT_WITHIN); + } + NOT_REACHED; /* NOTREACHED */ + } + case OP_AASSIGN: /* only examine RHS */ - return find_uninit_var(cBINOPx(obase)->op_first, uninit_sv, match); + return find_uninit_var(cBINOPx(obase)->op_first, uninit_sv, + match, desc_p); case OP_OPEN: o = cUNOPx(obase)->op_first; if ( o->op_type == OP_PUSHMARK || (o->op_type == OP_NULL && o->op_targ == OP_PUSHMARK) ) - o = OP_SIBLING(o); + o = OpSIBLING(o); - if (!OP_HAS_SIBLING(o)) { + if (!OpHAS_SIBLING(o)) { /* one-arg version of open is highly magical */ if (o->op_type == OP_GV) { /* open FOO; */ @@ -15748,7 +16027,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, && ( o->op_type == OP_PUSHMARK || (o->op_type == OP_NULL && o->op_targ == OP_PUSHMARK))) - o = OP_SIBLING(OP_SIBLING(o)); + o = OpSIBLING(OpSIBLING(o)); goto do_op2; @@ -15879,7 +16158,7 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, * it replaced are still in the tree, so we work on them instead. */ o2 = NULL; - for (kid=o; kid; kid = OP_SIBLING(kid)) { + for (kid=o; kid; kid = OpSIBLING(kid)) { const OPCODE type = kid->op_type; if ( (type == OP_CONST && SvOK(cSVOPx_sv(kid))) || (type == OP_NULL && ! (kid->op_flags & OPf_KIDS)) @@ -15895,14 +16174,14 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv, o2 = kid; } if (o2) - return find_uninit_var(o2, uninit_sv, match); + return find_uninit_var(o2, uninit_sv, match, desc_p); /* scan all args */ while (o) { - sv = find_uninit_var(o, uninit_sv, 1); + sv = find_uninit_var(o, uninit_sv, 1, desc_p); if (sv) return sv; - o = OP_SIBLING(o); + o = OpSIBLING(o); } break; } @@ -15924,14 +16203,15 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv) if (PL_op) { SV* varname = NULL; const char *desc; + + desc = PL_op->op_type == OP_STRINGIFY && PL_op->op_folded + ? "join or string" + : OP_DESC(PL_op); if (uninit_sv && PL_curpad) { - varname = find_uninit_var(PL_op, uninit_sv,0); + varname = find_uninit_var(PL_op, uninit_sv, 0, &desc); if (varname) sv_insert(varname, 0, 0, " ", 1); } - desc = PL_op->op_type == OP_STRINGIFY && PL_op->op_folded - ? "join or string" - : OP_DESC(PL_op); /* PL_warn_uninit_sv is constant */ GCC_DIAG_IGNORE(-Wformat-nonliteral); /* diag_listed_as: Use of uninitialized value%s */ @@ -15950,11 +16230,5 @@ Perl_report_uninit(pTHX_ const SV *uninit_sv) } /* - * Local variables: - * c-indentation-style: bsd - * c-basic-offset: 4 - * indent-tabs-mode: nil - * End: - * * ex: set ts=8 sts=4 sw=4 et: */