Re: [perl #21321] local ${"FOO"} does not work
Rafael Garcia-Suarez [Sun, 23 Feb 2003 00:03:27 +0000 (01:03 +0100)]
Message-Id: <20030223000327.6f0c11fa.rgarciasuarez@free.fr>

p4raw-id: //depot/perl@18774

MANIFEST
op.c
perl.h
pp.c
pp_hot.c
t/op/local.t

index 4695eb3..7ff5b2f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -2591,6 +2591,7 @@ t/op/lex_assign.t         See if ops involving lexicals or pad temps work
 t/op/lfs.t                     See if large files work for perlio
 t/op/list.t                    See if array lists work
 t/op/local.t                   See if local works
+t/op/localref.t                        See if local ${deref} works
 t/op/loopctl.t                 See if next/last/redo work
 t/op/lop.t                     See if logical operators work
 t/op/magic.t                   See if magic variables work
diff --git a/op.c b/op.c
index fd853ae..e4f22cc 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1053,8 +1053,6 @@ Perl_mod(pTHX_ OP *o, I32 type)
 
     case OP_RV2AV:
     case OP_RV2HV:
-       if (!type && cUNOPo->op_first->op_type != OP_GV)
-           Perl_croak(aTHX_ "Can't localize through a reference");
        if (type == OP_REFGEN && o->op_flags & OPf_PARENS) {
            PL_modcount = RETURN_UNLIMITED_NUMBER;
            return o;           /* Treat \(@foo) like ordinary list. */
@@ -1076,8 +1074,6 @@ Perl_mod(pTHX_ OP *o, I32 type)
        PL_modcount = RETURN_UNLIMITED_NUMBER;
        break;
     case OP_RV2SV:
-       if (!type && cUNOPo->op_first->op_type != OP_GV)
-           Perl_croak(aTHX_ "Can't localize through a reference");
        ref(cUNOPo->op_first, o->op_type);
        /* FALL THROUGH */
     case OP_GV:
diff --git a/perl.h b/perl.h
index d316734..f5a4d98 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -2933,6 +2933,8 @@ EXTCONST char PL_no_func[]
   INIT("The %s function is unimplemented");
 EXTCONST char PL_no_myglob[]
   INIT("\"my\" variable %s can't be in a package");
+EXTCONST char PL_no_localize_ref[]
+  INIT("Can't localize through a reference");
 
 EXTCONST char PL_uuemap[65]
   INIT("`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_");
diff --git a/pp.c b/pp.c
index cc6b5c3..2b15186 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -211,6 +211,7 @@ PP(pp_rv2gv)
 
 PP(pp_rv2sv)
 {
+    GV *gv = Nullgv;
     dSP; dTOPss;
 
     if (SvROK(sv)) {
@@ -226,9 +227,9 @@ PP(pp_rv2sv)
        }
     }
     else {
-       GV *gv = (GV*)sv;
        char *sym;
        STRLEN len;
+       gv = (GV*)sv;
 
        if (SvTYPE(gv) != SVt_PVGV) {
            if (SvGMAGICAL(sv)) {
@@ -265,8 +266,14 @@ PP(pp_rv2sv)
        sv = GvSV(gv);
     }
     if (PL_op->op_flags & OPf_MOD) {
-       if (PL_op->op_private & OPpLVAL_INTRO)
-           sv = save_scalar((GV*)TOPs);
+       if (PL_op->op_private & OPpLVAL_INTRO) {
+           if (cUNOP->op_first->op_type == OP_NULL)
+               sv = save_scalar((GV*)TOPs);
+           else if (gv)
+               sv = save_scalar(gv);
+           else
+               Perl_croak(aTHX_ PL_no_localize_ref);
+       }
        else if (PL_op->op_private & OPpDEREF)
            vivify_ref(sv, PL_op->op_private & OPpDEREF);
     }
index 2991900..c82b2df 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -685,6 +685,9 @@ PP(pp_rv2av)
            SETs((SV*)av);
            RETURN;
        }
+       else if (PL_op->op_flags & OPf_MOD
+               && PL_op->op_private & OPpLVAL_INTRO)
+           Perl_croak(aTHX_ PL_no_localize_ref);
     }
     else {
        if (SvTYPE(sv) == SVt_PVAV) {
@@ -809,6 +812,9 @@ PP(pp_rv2hv)
            SETs((SV*)hv);
            RETURN;
        }
+       else if (PL_op->op_flags & OPf_MOD
+               && PL_op->op_private & OPpLVAL_INTRO)
+           Perl_croak(aTHX_ PL_no_localize_ref);
     }
     else {
        if (SvTYPE(sv) == SVt_PVHV) {
index 6da0391..1bb8b8a 100755 (executable)
@@ -45,10 +45,10 @@ print $a,@b,@c,%d,$x,$y;
 eval 'local($$e)';
 print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 21\n";
 
-eval 'local(@$e)';
+eval '$e = []; local(@$e)';
 print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 22\n";
 
-eval 'local(%$e)';
+eval '$e = {}; local(%$e)';
 print +($@ =~ /Can't localize through a reference/) ? "" : "not ", "ok 23\n";
 
 # Array and hash elements