This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_match(): clarify intuit parens behaviour
[perl5.git] / pp_hot.c
index a2d6f91..17d1e8f 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -505,9 +505,7 @@ PP(pp_add)
        unsigned code below is actually shorter than the old code. :-)
     */
 
-    SvIV_please_nomg(svr);
-
-    if (SvIOK(svr)) {
+    if (SvIV_please_nomg(svr)) {
        /* Unless the left argument is integer in range we are going to have to
           use NV maths. Hence only attempt to coerce the right argument if
           we know the left is integer.  */
@@ -523,8 +521,7 @@ PP(pp_add)
               lots of code to speed up what is probably a rarish case.  */
        } else {
            /* Left operand is defined, so is it IV? */
-           SvIV_please_nomg(svl);
-           if (SvIOK(svl)) {
+           if (SvIV_please_nomg(svl)) {
                if ((auvok = SvUOK(svl)))
                    auv = SvUVX(svl);
                else {
@@ -774,6 +771,7 @@ PP(pp_rv2av)
        }
        sv = SvRV(sv);
        if (SvTYPE(sv) != type)
+           /* diag_listed_as: Not an ARRAY reference */
            DIE(aTHX_ "Not %s reference", is_pp_rv2av ? an_array : a_hash);
        if (PL_op->op_flags & OPf_REF) {
            SETs(sv);
@@ -994,6 +992,8 @@ PP(pp_aassign)
        case SVt_PVAV:
            ary = MUTABLE_AV(sv);
            magic = SvMAGICAL(ary) != 0;
+           ENTER;
+           SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
            av_clear(ary);
            av_extend(ary, lastrelem - relem);
            i = 0;
@@ -1014,6 +1014,7 @@ PP(pp_aassign)
            }
            if (PL_delaymagic & DM_ARRAY_ISA)
                SvSETMAGIC(MUTABLE_SV(ary));
+           LEAVE;
            break;
        case SVt_PVHV: {                                /* normal hash */
                SV *tmpstr;
@@ -1021,6 +1022,8 @@ PP(pp_aassign)
 
                hash = MUTABLE_HV(sv);
                magic = SvMAGICAL(hash) != 0;
+               ENTER;
+               SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
                hv_clear(hash);
                firsthashrelem = relem;
 
@@ -1057,6 +1060,7 @@ PP(pp_aassign)
                    do_oddball(hash, relem, firstrelem);
                    relem++;
                }
+               LEAVE;
            }
            break;
        default:
@@ -1084,71 +1088,77 @@ PP(pp_aassign)
        }
     }
     if (PL_delaymagic & ~DM_DELAY) {
+       /* Will be used to set PL_tainting below */
+       UV tmp_uid  = PerlProc_getuid();
+       UV tmp_euid = PerlProc_geteuid();
+       UV tmp_gid  = PerlProc_getgid();
+       UV tmp_egid = PerlProc_getegid();
+
        if (PL_delaymagic & DM_UID) {
 #ifdef HAS_SETRESUID
-           (void)setresuid((PL_delaymagic & DM_RUID) ? PL_uid  : (Uid_t)-1,
-                           (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1,
+           (void)setresuid((PL_delaymagic & DM_RUID) ? PL_delaymagic_uid  : (Uid_t)-1,
+                           (PL_delaymagic & DM_EUID) ? PL_delaymagic_euid : (Uid_t)-1,
                            (Uid_t)-1);
 #else
 #  ifdef HAS_SETREUID
-           (void)setreuid((PL_delaymagic & DM_RUID) ? PL_uid  : (Uid_t)-1,
-                          (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1);
+           (void)setreuid((PL_delaymagic & DM_RUID) ? PL_delaymagic_uid  : (Uid_t)-1,
+                          (PL_delaymagic & DM_EUID) ? PL_delaymagic_euid : (Uid_t)-1);
 #  else
 #    ifdef HAS_SETRUID
            if ((PL_delaymagic & DM_UID) == DM_RUID) {
-               (void)setruid(PL_uid);
+               (void)setruid(PL_delaymagic_uid);
                PL_delaymagic &= ~DM_RUID;
            }
 #    endif /* HAS_SETRUID */
 #    ifdef HAS_SETEUID
            if ((PL_delaymagic & DM_UID) == DM_EUID) {
-               (void)seteuid(PL_euid);
+               (void)seteuid(PL_delaymagic_euid);
                PL_delaymagic &= ~DM_EUID;
            }
 #    endif /* HAS_SETEUID */
            if (PL_delaymagic & DM_UID) {
-               if (PL_uid != PL_euid)
+               if (PL_delaymagic_uid != PL_delaymagic_euid)
                    DIE(aTHX_ "No setreuid available");
-               (void)PerlProc_setuid(PL_uid);
+               (void)PerlProc_setuid(PL_delaymagic_uid);
            }
 #  endif /* HAS_SETREUID */
 #endif /* HAS_SETRESUID */
-           PL_uid = PerlProc_getuid();
-           PL_euid = PerlProc_geteuid();
+           tmp_uid  = PerlProc_getuid();
+           tmp_euid = PerlProc_geteuid();
        }
        if (PL_delaymagic & DM_GID) {
 #ifdef HAS_SETRESGID
-           (void)setresgid((PL_delaymagic & DM_RGID) ? PL_gid  : (Gid_t)-1,
-                           (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1,
+           (void)setresgid((PL_delaymagic & DM_RGID) ? PL_delaymagic_gid  : (Gid_t)-1,
+                           (PL_delaymagic & DM_EGID) ? PL_delaymagic_egid : (Gid_t)-1,
                            (Gid_t)-1);
 #else
 #  ifdef HAS_SETREGID
-           (void)setregid((PL_delaymagic & DM_RGID) ? PL_gid  : (Gid_t)-1,
-                          (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1);
+           (void)setregid((PL_delaymagic & DM_RGID) ? PL_delaymagic_gid  : (Gid_t)-1,
+                          (PL_delaymagic & DM_EGID) ? PL_delaymagic_egid : (Gid_t)-1);
 #  else
 #    ifdef HAS_SETRGID
            if ((PL_delaymagic & DM_GID) == DM_RGID) {
-               (void)setrgid(PL_gid);
+               (void)setrgid(PL_delaymagic_gid);
                PL_delaymagic &= ~DM_RGID;
            }
 #    endif /* HAS_SETRGID */
 #    ifdef HAS_SETEGID
            if ((PL_delaymagic & DM_GID) == DM_EGID) {
-               (void)setegid(PL_egid);
+               (void)setegid(PL_delaymagic_egid);
                PL_delaymagic &= ~DM_EGID;
            }
 #    endif /* HAS_SETEGID */
            if (PL_delaymagic & DM_GID) {
-               if (PL_gid != PL_egid)
+               if (PL_delaymagic_gid != PL_delaymagic_egid)
                    DIE(aTHX_ "No setregid available");
-               (void)PerlProc_setgid(PL_gid);
+               (void)PerlProc_setgid(PL_delaymagic_gid);
            }
 #  endif /* HAS_SETREGID */
 #endif /* HAS_SETRESGID */
-           PL_gid = PerlProc_getgid();
-           PL_egid = PerlProc_getegid();
+           tmp_gid  = PerlProc_getgid();
+           tmp_egid = PerlProc_getegid();
        }
-       PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
+       PL_tainting |= (tmp_uid && (tmp_euid != tmp_uid || tmp_egid != tmp_gid));
     }
     PL_delaymagic = 0;
 
@@ -1198,6 +1208,8 @@ PP(pp_qr)
     REGEXP * rx = PM_GETRE(pm);
     SV * const pkg = rx ? CALLREG_PACKAGE(rx) : NULL;
     SV * const rv = sv_newmortal();
+    CV **cvp;
+    CV *cv;
 
     SvUPGRADE(rv, SVt_IV);
     /* For a subroutine describing itself as "This is a hacky workaround" I'm
@@ -1209,6 +1221,12 @@ PP(pp_qr)
     SvRV_set(rv, MUTABLE_SV(reg_temp_copy(NULL, rx)));
     SvROK_on(rv);
 
+    cvp = &( ((struct regexp*)SvANY(SvRV(rv)))->qr_anoncv);
+    if ((cv = *cvp) && CvCLONE(*cvp)) {
+       *cvp = cv_clone(cv);
+       SvREFCNT_dec(cv);
+    }
+
     if (pkg) {
        HV *const stash = gv_stashsv(pkg, GV_ADD);
        SvREFCNT_dec(pkg);
@@ -1324,8 +1342,6 @@ PP(pp_match)
            || SvTEMP(TARG) || SvAMAGIC(TARG) || PL_sawampersand
            || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY)))
        r_flags |= REXEC_COPY_STR;
-    if (SvSCREAM(TARG))
-       r_flags |= REXEC_SCREAM;
 
   play_it_again:
     if (global && RX_OFFS(rx)[0].start != -1) {
@@ -1346,9 +1362,6 @@ PP(pp_match)
        if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
             && !PL_sawampersand
             && !(RX_EXTFLAGS(rx) & RXf_PMf_KEEPCOPY)
-            && ((RX_EXTFLAGS(rx) & RXf_NOSCAN)
-                || !((RX_EXTFLAGS(rx) & RXf_INTUIT_TAIL)
-                     && (r_flags & REXEC_SCREAM)))
             && !SvROK(TARG))   /* Cannot trust since INTUIT cannot guess ^ */
            goto yup;
     }
@@ -1383,7 +1396,10 @@ PP(pp_match)
                s = RX_OFFS(rx)[i].start + truebase;
                if (RX_OFFS(rx)[i].end < 0 || RX_OFFS(rx)[i].start < 0 ||
                    len < 0 || len > strend - s)
-                   DIE(aTHX_ "panic: pp_match start/end pointers");
+                   DIE(aTHX_ "panic: pp_match start/end pointers, i=%ld, "
+                       "start=%ld, end=%ld, s=%p, strend=%p, len=%"UVuf,
+                       (long) i, (long) RX_OFFS(rx)[i].start,
+                       (long)RX_OFFS(rx)[i].end, s, strend, (UV) len);
                sv_setpvn(*SP, s, len);
                if (DO_UTF8(TARG) && is_utf8_string((U8*)s, len))
                    SvUTF8_on(*SP);
@@ -1511,9 +1527,9 @@ yup:                                      /* Confirmed by INTUIT */
        RX_OFFS(rx)[0].start = s - truebase;
        RX_OFFS(rx)[0].end = s - truebase + RX_MINLENRET(rx);
     }
-    /* including RX_NPARENS(rx) in the below code seems highly suspicious.
-       -dmq */
-    RX_NPARENS(rx) = RX_LASTPAREN(rx) = RX_LASTCLOSEPAREN(rx) = 0;     /* used by @-, @+, and $^N */
+    /* match via INTUIT shouldn't have any captures. Let @-, @+, $^N know */
+    assert(!RX_NPARENS(rx));
+    RX_LASTPAREN(rx) = RX_LASTCLOSEPAREN(rx) = 0;
     LEAVE_SCOPE(oldsave);
     RETPUSHYES;
 
@@ -1591,7 +1607,7 @@ Perl_do_readline(pTHX)
            && ckWARN2(WARN_GLOB, WARN_CLOSED))
        {
            if (type == OP_GLOB)
-               Perl_warner(aTHX_ packWARN(WARN_GLOB),
+               Perl_ck_warner_d(aTHX_ packWARN(WARN_GLOB),
                            "glob failed (can't start child: %s)",
                            Strerror(errno));
            else
@@ -1773,7 +1789,7 @@ PP(pp_helem)
     he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
     svp = he ? &HeVAL(he) : NULL;
     if (lval) {
-       if (!svp || *svp == &PL_sv_undef) {
+       if (!svp || !*svp || *svp == &PL_sv_undef) {
            SV* lv;
            SV* key2;
            if (!defer) {
@@ -1803,7 +1819,7 @@ PP(pp_helem)
            RETURN;
        }
     }
-    sv = (svp ? *svp : &PL_sv_undef);
+    sv = (svp && *svp ? *svp : &PL_sv_undef);
     /* Originally this did a conditional C<sv = sv_mortalcopy(sv)>; this
      * was to make C<local $tied{foo} = $tied{foo}> possible.
      * However, it seems no longer to be needed for that purpose, and
@@ -1834,7 +1850,7 @@ PP(pp_iter)
     EXTEND(SP, 1);
     cx = &cxstack[cxstack_ix];
     if (!CxTYPE_is_LOOP(cx))
-       DIE(aTHX_ "panic: pp_iter");
+       DIE(aTHX_ "panic: pp_iter, type=%u", CxTYPE(cx));
 
     itersvp = CxITERVAR(cx);
     if (CxTYPE(cx) == CXt_LOOP_LAZYSV) {
@@ -2112,7 +2128,7 @@ PP(pp_subst)
 
   force_it:
     if (!pm || !s)
-       DIE(aTHX_ "panic: pp_subst");
+       DIE(aTHX_ "panic: pp_subst, pm=%p, s=%p", pm, s);
 
     strend = s + len;
     slen = RX_MATCH_UTF8(rx) ? utf8_length((U8*)s, (U8*)strend) : len;
@@ -2127,8 +2143,6 @@ PP(pp_subst)
     r_flags = (RX_NPARENS(rx) || SvTEMP(TARG) || PL_sawampersand
            || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY)) )
               ? REXEC_COPY_STR : 0;
-    if (SvSCREAM(TARG))
-       r_flags |= REXEC_SCREAM;
 
     orig = m = s;
     if (RX_EXTFLAGS(rx) & RXf_USE_INTUIT) {
@@ -2140,10 +2154,7 @@ PP(pp_subst)
        /* How to do it in subst? */
 /*     if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
             && !PL_sawampersand
-            && !(RX_EXTFLAGS(rx) & RXf_KEEPCOPY)
-            && ((RX_EXTFLAGS(rx) & RXf_NOSCAN)
-                || !((RX_EXTFLAGS(rx) & RXf_INTUIT_TAIL)
-                     && (r_flags & REXEC_SCREAM))))
+            && !(RX_EXTFLAGS(rx) & RXf_KEEPCOPY))
            goto yup;
 */
     }
@@ -2224,7 +2235,6 @@ PP(pp_subst)
        }
        d = s;
        PL_curpm = pm;
-       SvSCREAM_off(TARG);     /* disable possible screamer */
        if (once) {
            if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
                rxtainted |= SUBST_TAINT_PAT;
@@ -2491,7 +2501,8 @@ PP(pp_leavesub)
        MARK = newsp + 1;
        if (MARK <= SP) {
            if (cx->blk_sub.cv && CvDEPTH(cx->blk_sub.cv) > 1) {
-               if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1) {
+               if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1
+                    && !SvMAGICAL(TOPs)) {
                    *MARK = SvREFCNT_inc(TOPs);
                    FREETMPS;
                    sv_2mortal(*MARK);
@@ -2503,7 +2514,8 @@ PP(pp_leavesub)
                    SvREFCNT_dec(sv);
                }
            }
-           else if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1) {
+           else if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1
+                    && !SvMAGICAL(TOPs)) {
                *MARK = TOPs;
            }
            else
@@ -2517,7 +2529,8 @@ PP(pp_leavesub)
     }
     else if (gimme == G_ARRAY) {
        for (MARK = newsp + 1; MARK <= SP; MARK++) {
-           if (!SvTEMP(*MARK) || SvREFCNT(*MARK) != 1) {
+           if (!SvTEMP(*MARK) || SvREFCNT(*MARK) != 1
+                || SvMAGICAL(*MARK)) {
                *MARK = sv_mortalcopy(*MARK);
                TAINT_NOT;      /* Each item is independent */
            }
@@ -2666,11 +2679,6 @@ try_autoload:
        PUSHSUB(cx);
        cx->blk_sub.retop = PL_op->op_next;
        CvDEPTH(cv)++;
-       /* XXX This would be a natural place to set C<PL_compcv = cv> so
-        * that eval'' ops within this sub know the correct lexical space.
-        * Owing the speed considerations, we choose instead to search for
-        * the cv using find_runcv() when calling doeval().
-        */
        if (CvDEPTH(cv) >= 2) {
            PERL_STACK_OVERFLOW_CHECK();
            pad_push(padlist, CvDEPTH(cv));
@@ -2714,6 +2722,9 @@ try_autoload:
                MARK++;
            }
        }
+       if ((cx->blk_u16 & OPpENTERSUB_LVAL_MASK) == OPpLVAL_INTRO &&
+           !CvLVALUE(cv))
+           DIE(aTHX_ "Can't modify non-lvalue subroutine call");
        /* warning must come *after* we fully set up the context
         * stuff so that __WARN__ handlers can safely dounwind()
         * if they want to
@@ -2885,6 +2896,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
        }
        SvROK_on(sv);
        SvSETMAGIC(sv);
+       SvGETMAGIC(sv);
     }
     if (SvGMAGICAL(sv)) {
        /* copy the sv without magic to prevent magic from being
@@ -2931,7 +2943,11 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
     GV* gv;
     HV* stash;
     SV *packsv = NULL;
-    SV * const sv = *(PL_stack_base + TOPMARK + 1);
+    SV * const sv = PL_stack_base + TOPMARK == PL_stack_sp
+       ? (Perl_croak(aTHX_ "Can't call method \"%"SVf"\" without a "
+                           "package or object reference", SVfARG(meth)),
+          (SV *)NULL)
+       : *(PL_stack_base + TOPMARK + 1);
 
     PERL_ARGS_ASSERT_METHOD_COMMON;
 
@@ -2976,6 +2992,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
                    : !isIDFIRST_L1((U8)*packname)
                ))
            {
+               /* diag_listed_as: Can't call method "%s" without a package or object reference */
                Perl_croak(aTHX_ "Can't call method \"%"SVf"\" %s",
                           SVfARG(meth),
                           SvOK(sv) ? "without a package or object reference"
@@ -3039,8 +3056,8 @@ S_method_common(pTHX_ SV* meth, U32* hashp)
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
  * End:
  *
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
  */