This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
fix ($lex = index(....)) == -1
authorDavid Mitchell <davem@iabyn.com>
Tue, 1 Aug 2017 07:19:42 +0000 (08:19 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 1 Aug 2017 07:19:42 +0000 (08:19 +0100)
RT #131823

My recent commit v5.27.2-56-g7e8d786 optimised index() == -1 and similar.
It asserted that in such an expression, the index op's OPpTARGET_MY
flag couldn't be set. This was an incorrect assumption, obvious in
hindsight:

    ($lex = index(....)) == -1

gets compiled as

    <@> index[$r:2,3] sKP/TARGMY,2 ->c
       <0> ex-pushmark s ->9
       <0> padsv[$s:1,3] s ->a
       <$> const[PVMG "a"] s ->b
    <$> const[IV -1] s/FOLD ->d

The fix is simple: skip the optimisation if OPpTARGET_MY is present,
rather than assert failing.

op.c
t/op/index.t

diff --git a/op.c b/op.c
index ff78e95..a72dd13 100644 (file)
--- a/op.c
+++ b/op.c
@@ -9848,7 +9848,10 @@ Perl_ck_eq(pTHX_ OP *o)
     if (!(sv && SvIOK_notUV(sv) && SvIVX(sv) == -1))
         return o;
 
-    assert(!(indexop->op_private & OPpTARGET_MY));
+    /* ($lex = index(....)) == -1 */
+    if (indexop->op_private & OPpTARGET_MY)
+        return o;
+
     indexop->op_flags &= ~OPf_PARENS;
     indexop->op_flags |= (o->op_flags & OPf_PARENS);
     indexop->op_private |= OPpTRUEBOOL;
index a28ca65..cf165de 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
 }
 
 use strict;
-plan( tests => 170 );
+plan( tests => 172 );
 
 run_tests() unless caller;
 
@@ -260,7 +260,7 @@ is index($substr, 'a'), 1, 'index reply reflects characters not octets';
 # op_eq, op_const optimised away in (index() == -1) and variants
 
 {
-    my $s = "ab";
+    my $s = "abxyz";
     ok(!(index($s,"a") == -1),  "index(a) == -1");
     ok( (index($s,"a") != -1),  "index(a) != -1");
     ok( (index($s,"c") == -1),  "index(c) == -1");
@@ -320,4 +320,12 @@ is index($substr, 'a'), 1, 'index reply reflects characters not octets';
     ok( $r,                         "r = -1 == rindex(c) - r value");
     ok(!($r = -1 != rindex($s,"c")), "r = -1 != rindex(c)");
     ok(!$r,                         "r = -1 != rindex(c) - r value");
+
+    # RT #131823
+    # index with OPpTARGET_MY shouldn't do the '== -1' optimisation
+
+    ok(!(($r = index($s,"z")) == -1),  "(r = index(a)) == -1");
+    is($r, 4,                          "(r = index(a)) == -1 - r value");
+
+
 }