Stop creating defelems for undef in foreach(@_)
authorFather Chrysostomos <sprout@cpan.org>
Thu, 29 Aug 2013 01:20:41 +0000 (18:20 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 29 Aug 2013 05:26:14 +0000 (22:26 -0700)
This is part of ticket #119433.  This particular bug is triggered by
Data::Dump’s test suite.

Commit ce0d59f changed arrays to use NULL for nonexistent elements,
instead of &PL_sv_undef (the special scalar returned by Perl’s ‘undef’
operator).

‘foreach’ was not updated to account.  It was still treating
&PL_sv_undef as a nonexistent element.  This was causing ‘Modifica-
tion of non-creatable array value attempted, subscript 0’, due to a
similar bug in vivify_defelem, which the next commit will fix.

(Fixing vivify_defelem without fixing foreach will make the test pass,
but for foreach to create a defelem to begin with is inefficient and
should be addressed anyway.)

pp_hot.c
t/op/for.t

index 82c8e12..4faa738 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1918,10 +1918,7 @@ PP(pp_iter)
                 SvREFCNT_inc_simple_void_NN(sv);
             }
         }
-        else
-            sv = &PL_sv_undef;
-
-        if (!av_is_stack && sv == &PL_sv_undef) {
+        else if (!av_is_stack) {
             SV *lv = newSV_type(SVt_PVLV);
             LvTYPE(lv) = 'y';
             sv_magic(lv, NULL, PERL_MAGIC_defelem, NULL, 0);
@@ -1930,6 +1927,8 @@ PP(pp_iter)
             LvTARGLEN(lv) = (STRLEN)UV_MAX;
             sv = lv;
         }
+        else
+            sv = &PL_sv_undef;
 
         oldsv = *itersvp;
         *itersvp = sv;
index 0571380..6cd0224 100644 (file)
@@ -4,7 +4,7 @@ BEGIN {
     require "test.pl";
 }
 
-plan(104);
+plan(105);
 
 # A lot of tests to check that reversed for works.
 
@@ -562,3 +562,9 @@ TODO: {
         todo_skip("RT #2166: foreach spuriously autovivifies");
     }
 }
+
+sub {
+    foreach (@_) {
+        is eval { \$_ }, \undef, 'foreach (@array_containing_undef)'
+    }
+}->(undef);