This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Make keys $scalar an lvalue
authorFather Chrysostomos <sprout@cpan.org>
Tue, 19 Apr 2011 04:29:11 +0000 (21:29 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 19 Apr 2011 04:29:32 +0000 (21:29 -0700)
This does a run-time check to see whether $scalar is a hash ref, and
dies if it is not.

This is to keep keys \@_ consistent with keys @_.

I cannot simply use OPf_MOD, since that indicates *potential* lvalue
context (including subroutine args).

So, instead, I take advantage of the fact that OPf_SPECIAL is always
set on the LHS of an assignment (usually to indicate that local()
should not erase the value).

op.c
pp.c
t/op/smartkve.t

diff --git a/op.c b/op.c
index f22f888..e21b9a4 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1690,6 +1690,7 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type)
        break;
 
     case OP_KEYS:
+    case OP_RKEYS:
        if (type != OP_SASSIGN)
            goto nomod;
        goto lvalue_func;
diff --git a/pp.c b/pp.c
index 5b32daf..4c88270 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -4850,6 +4850,12 @@ PP(pp_rkeys)
            PL_op_desc[PL_op->op_type] );
     }
 
+    if (PL_op->op_flags & OPf_SPECIAL && SvTYPE(sv) == SVt_PVAV)
+       DIE(aTHX_
+          "Can't modify %s in %s",
+           PL_op_desc[PL_op->op_type], PL_op_desc[PL_op->op_next->op_type]
+       );
+
     /* Delegate to correct function for op type */
     PUSHs(sv);
     if (PL_op->op_type == OP_RKEYS || PL_op->op_type == OP_RVALUES) {
index 7c57e7b..ad56e6a 100644 (file)
@@ -131,6 +131,14 @@ ok(defined $empty,
   'Vivify: $empty (after keys $empty->{hash}) is HASHREF');
 ok(!defined $empty->{hash}      ,   'Vivify: $empty->{hash} is undef');
 
+# Keys -- lvalue
+$_{foo} = "bar";
+keys \%_ = 65;
+is scalar %_, '1/128', 'keys $hashref as lvalue';
+eval 'keys \@_ = 65';
+like $@, qr/Can't modify keys on reference in scalar assignment/,
+  'keys $arrayref as lvalue dies';
+
 # Keys -- errors
 $errpat = qr/
  (?-x:Type of argument to keys on reference must be unblessed hashref or)