]> git.vpit.fr Git - perl/modules/autovivification.git/commitdiff
Make sure gv ops seen by multideref are cleaned from the global table
authorVincent Pit <vince@profvince.com>
Thu, 14 May 2015 15:38:01 +0000 (17:38 +0200)
committerVincent Pit <vince@profvince.com>
Thu, 14 May 2015 15:44:30 +0000 (17:44 +0200)
Since they are created in the peephole optimizer, multideref ops have to
rely on getting the lexical scope hints from their first kid. It might have
happened that the kid of one such op was a gv op compiled in the scope of
the pragma, and was then reused outside of the scope of the pragma again
as the first kid of another multideref op. In that case, the multideref op
was wrongly replaced. This is solved by always clearing gv ops entries in
ck_rv2xv() from the global op map.

This solves random failures of test 12 from t/40-scope.t.

autovivification.xs

index e038c73130bb25d40902274004a8de83bd831584..eb1cbbcad762d48e209de8f40048ef578ba6f24a 100644 (file)
@@ -1258,14 +1258,19 @@ static OP *a_ck_deref(pTHX_ OP *o) {
  }
  o = old_ck(aTHX_ o);
 
- if (hint & A_HINT_DO) {
 #if A_HAS_MULTIDEREF
-  if (old_ck == a_old_ck_rv2sv && o->op_flags & OPf_KIDS) {
-   OP *kid = cUNOPo->op_first;
-   if (kid && kid->op_type == OP_GV)
+ if (old_ck == a_old_ck_rv2sv && o->op_flags & OPf_KIDS) {
+  OP *kid = cUNOPo->op_first;
+  if (kid && kid->op_type == OP_GV) {
+   if (hint & A_HINT_DO)
     a_map_store(kid, kid->op_ppaddr, NULL, hint);
+   else
+    a_map_delete(kid);
   }
+ }
 #endif
+
+ if (hint & A_HINT_DO) {
   a_map_store_root(o, o->op_ppaddr, hint);
   o->op_ppaddr = a_pp_deref;
  } else