diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-07-16 22:56:44 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-08-21 00:03:55 -0700 |
commit | bbfdc870734e1313430ade6e6bd6d8ee2b720413 (patch) | |
tree | ce4190735fd46ebdaf7db844ee9f4bc338ad3a0e /sv.h | |
parent | b2d74da6dac4b0c1c9ebf65c8d96a3ee53f5232f (diff) | |
download | perl-bbfdc870734e1313430ade6e6bd6d8ee2b720413.tar.gz |
[perl #118691] Allow defelem magic with neg indices
When a nonexistent array element is passed to a subroutine, a special
‘deferred element’ scalar (implemented using something called defelem
magic) is passed to the subroutine instead, which delegates to the
array element. This allows some_benign_function($array[$nonexistent])
to avoid autovivifying unnecessarily.
Whether this magic would be triggered was based on whether the element
was within the range 0..$#array. Since arrays can contain nonexistent
elements before $#array, this logic is incorrect. It also makes sense
to allow $array[$neg] where the negative number points before the
beginning of the array to create a deferred element and only croak if
it is assigned to.
This commit fixes the logic for when deferred elements are created
and implements these deferred negative elements.
Since we have to be able to store negative values in xlv_targoff, it
is convenient to make it a union (with two types--signed and unsigned)
and use LvSTARGOFF for defelem array indices.
Diffstat (limited to 'sv.h')
-rw-r--r-- | sv.h | 8 |
1 files changed, 7 insertions, 1 deletions
@@ -528,7 +528,10 @@ struct xpvlv { _XPV_HEAD; union _xivu xiv_u; union _xnvu xnv_u; - STRLEN xlv_targoff; + union { + STRLEN xlvu_targoff; + SSize_t xlvu_stargoff; + } xlv_targoff_u; STRLEN xlv_targlen; SV* xlv_targ; char xlv_type; /* k=keys .=pos x=substr v=vec /=join/re @@ -536,6 +539,8 @@ struct xpvlv { char xlv_flags; /* 1 = negative offset 2 = negative len */ }; +#define xlv_targoff xlv_targoff_u.xlvu_targoff + struct xpvinvlist { _XPV_HEAD; IV prev_index; @@ -1403,6 +1408,7 @@ sv_force_normal does nothing. #define LvTYPE(sv) ((XPVLV*) SvANY(sv))->xlv_type #define LvTARG(sv) ((XPVLV*) SvANY(sv))->xlv_targ #define LvTARGOFF(sv) ((XPVLV*) SvANY(sv))->xlv_targoff +#define LvSTARGOFF(sv) ((XPVLV*) SvANY(sv))->xlv_targoff_u.xlvu_stargoff #define LvTARGLEN(sv) ((XPVLV*) SvANY(sv))->xlv_targlen #define LvFLAGS(sv) ((XPVLV*) SvANY(sv))->xlv_flags |