From 649c173f8c6054f378a811701c168f02aba60e46 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Wed, 7 Aug 2013 08:46:52 -0700 Subject: [PATCH] =?utf8?q?Don=E2=80=99t=20stringify=20undef=20hash=20keys?= =?utf8?q?=20at=20compile=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit $ ./perl -wIlib -Mconstant' u=>undef' -e '()=$a{+u} if $a' Use of uninitialized value at -e line 1. Well, I didn’t even execute that hash lookup, so why is it warning me about an uninitialized value? This is a compile-time optimisation to turn hash keys into shared hash key scalars (containing precomputed hashes) to speed up key lookup. It stringifies the hash key at compile time as part of the process. The value should not be stringified if that would cause observable difference with tied hashes. Commit 04698ff67 fixed this for refs, globs and regexps, but missed undef scalars. This could be considered part of bug #79178. --- op.c | 2 +- t/op/hash.t | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/op.c b/op.c index d87396b..1d72f27 100644 --- a/op.c +++ b/op.c @@ -1823,7 +1823,7 @@ S_finalize_op(pTHX_ OP* o) /* Make the CONST have a shared SV */ svp = cSVOPx_svp(((BINOP*)o)->op_last); if ((!SvIsCOW(sv = *svp)) - && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) { + && SvTYPE(sv) < SVt_PVMG && SvOK(sv) && !SvROK(sv)) { key = SvPV_const(sv, keylen); lexname = newSVpvn_share(key, SvUTF8(sv) ? -(I32)keylen : (I32)keylen, diff --git a/t/op/hash.t b/t/op/hash.t index e0e8021..5f4c143 100644 --- a/t/op/hash.t +++ b/t/op/hash.t @@ -42,7 +42,12 @@ is($destroyed, 1, 'Timely hash destruction with lvalue keys'); tie my %h, "bar"; () = $h{\'foo'}; is ref $key, SCALAR => - 'hash keys are not stringified during compilation'; + 'ref hash keys are not stringified during compilation'; + use constant u => undef; + no warnings 'uninitialized'; # work around unfixed bug #105918 + () = $h{+u}; + is $key, undef, + 'undef hash keys are not stringified during compilation, either'; } # Part of RT #85026: Deleting the current iterator in void context does not -- 1.8.3.1