summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorDoug MacEachern <dougm@covalent.net>2002-06-03 01:27:56 -0700
committerJarkko Hietaniemi <jhi@iki.fi>2002-06-05 20:48:18 +0000
commiteb85dfd35868e4b09d07b81ae578cef99fbf8150 (patch)
tree9c452f8d8ef6c9849abd5afd3fee39ba6a9d6390 /pp.c
parent12b2c10f3f6560f07280f9e95bf5147601ef6195 (diff)
downloadperl-eb85dfd35868e4b09d07b81ae578cef99fbf8150.tar.gz
Re: local tied hash slices & stray keys (was Re: Cwd breakage)
Message-ID: <Pine.LNX.4.33.0206030822330.2695-100000@mako.covalent.net> (plus a test expanded from Schwern's [ID 20020602.006]) p4raw-id: //depot/perl@17022
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/pp.c b/pp.c
index 531516b2d1..08cb9cff8b 100644
--- a/pp.c
+++ b/pp.c
@@ -3825,17 +3825,38 @@ PP(pp_hslice)
register HV *hv = (HV*)POPs;
register I32 lval = (PL_op->op_flags & OPf_MOD || LVRET);
I32 realhv = (SvTYPE(hv) == SVt_PVHV);
+ bool localizing = PL_op->op_private & OPpLVAL_INTRO ? TRUE : FALSE;
+ bool other_magic = FALSE;
- if (!realhv && PL_op->op_private & OPpLVAL_INTRO)
+ if (localizing) {
+ MAGIC *mg;
+ HV *stash;
+
+ other_magic = mg_find((SV*)hv, PERL_MAGIC_env) ||
+ ((mg = mg_find((SV*)hv, PERL_MAGIC_tied))
+ /* Try to preserve the existenceness of a tied hash
+ * element by using EXISTS and DELETE if possible.
+ * Fallback to FETCH and STORE otherwise */
+ && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg))))
+ && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
+ && gv_fetchmethod_autoload(stash, "DELETE", TRUE));
+ }
+
+ if (!realhv && localizing)
DIE(aTHX_ "Can't localize pseudo-hash element");
if (realhv || SvTYPE(hv) == SVt_PVAV) {
while (++MARK <= SP) {
SV *keysv = *MARK;
SV **svp;
- I32 preeminent = SvRMAGICAL(hv) ? 1 :
- realhv ? hv_exists_ent(hv, keysv, 0)
- : avhv_exists_ent((AV*)hv, keysv, 0);
+ I32 preeminent;
+
+ if (localizing) {
+ preeminent = SvRMAGICAL(hv) && !other_magic ? 1 :
+ realhv ? hv_exists_ent(hv, keysv, 0)
+ : avhv_exists_ent((AV*)hv, keysv, 0);
+ }
+
if (realhv) {
HE *he = hv_fetch_ent(hv, keysv, lval, 0);
svp = he ? &HeVAL(he) : 0;
@@ -3848,7 +3869,7 @@ PP(pp_hslice)
STRLEN n_a;
DIE(aTHX_ PL_no_helem, SvPV(keysv, n_a));
}
- if (PL_op->op_private & OPpLVAL_INTRO) {
+ if (localizing) {
if (preeminent)
save_helem(hv, keysv, svp);
else {