Front page | perl.perl5.porters |
Postings from May 2003
Re: Proposal: include var name in 'use of undefined value' warning
Thread Previous
|
Thread Next
From:
Nick Ing-Simmons
Date:
May 10, 2003 15:27
Subject:
Re: Proposal: include var name in 'use of undefined value' warning
Message ID:
20030510222650.2454.10@bactrian.ni-s.u-net.com
Dave Mitchell <davem@fdgroup.com> writes:
>Currently, code like the following produces the warning shown:
>
> $ perl -wle 'my $x=1; my $y; print $x+$y'
> Use of uninitialized value in addition (+) at -e line 1.
> 1
>
>When the code is more complicated, it becomes very irritating that
>Perl doesn't tell you the name of the variable that had the undef value.
>
>I include a proof-of-concept patch below (not to be applied !!!!)
>that produces the following warning instead:
>
> Use of uninitialized variable $y in addition (+) at -e line 1.
>
>The idea is that in the case of printing out the warning when PL_op
>is valid, the children of PL_op are recursively examined to look
>for a pad/gv-type op whose varable's value is currently undefined, and if
>so, substitute the name of the var. If it can't be found, then it reverts
>to the old behaviour.
>
>Is this a good idea, and should I pursue it into a full patch?
>(The demo patch below only works for lexicals and +/-.)
>
>Any gotchas?
A. How deep do you search? - if expression is deep and involves lots
of closures or whatever this could take a while if 1st 100,000
variables are all defined.
B. IIRC geting names of pad variables at run-time is tricky - the names
are there in compile phase.
C. Rember to fully qualify name if it is not in current package.
>
>I suppose the biggest risk is that it gets the wrong var name - I won't
>have a feel for how likely this until I've implemented some more ops, and
>more levels or recursion.
Is this not going to get a complex as B:: stuff in the general case?
>
>Dave M.
>
>--
>Fire extinguisher (n) a device for holding open fire doors.
>
>
>--- sv.c- Fri May 9 22:50:04 2003
>+++ sv.c Fri May 9 23:20:42 2003
>@@ -562,6 +562,80 @@ Perl_sv_free_arenas(pTHX)
> PL_sv_root = 0;
> }
>
>+/* is the SV defined ? */
>+/* XXX lifted directly from pp_define; integrate */
>+int
>+S_isdef(pTHX_ SV* sv)
>+{
>+ if (!sv || !SvANY(sv))
>+ return 0;
>+ switch (SvTYPE(sv)) {
>+ case SVt_PVAV:
>+ if (AvMAX(sv) >= 0 || SvGMAGICAL(sv)
>+ || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
>+ return 1;
>+ break;
>+ case SVt_PVHV:
>+ if (HvARRAY(sv) || SvGMAGICAL(sv)
>+ || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
>+ return 1;
>+ break;
>+ case SVt_PVCV:
>+ if (CvROOT(sv) || CvXSUB(sv))
>+ return 1;
>+ break;
>+ default:
>+ if (SvGMAGICAL(sv))
>+ mg_get(sv);
>+ if (SvOK(sv))
>+ return 1;
>+ }
>+ return 0;
>+}
>+
>+/* XXX find the name of the undefined var (if any) associated with
>+ * this op */
>+
>+SV *
>+S_find_undef_var(pTHX_ OP* o)
>+{
>+ SV* sv;
>+ if (!o)
>+ return Nullsv;
>+ switch (o->op_type) {
>+ case OP_PADSV:
>+ case OP_PADAV:
>+ case OP_PADHV:
>+ {
>+ U32 dbseq;
>+ CV* cv = find_runcv(&dbseq);
>+ /* XXX this should be encapulated in pad.[ch] */
>+ if (cv && CvPADLIST(cv)) {
>+ AV* namepad = (AV*)(*av_fetch(CvPADLIST(cv), 0, FALSE));
>+ AV* pad = (AV*)(*av_fetch(CvPADLIST(cv), 1, FALSE));
>+ if (pad != PL_comppad)
>+ return Nullsv;
>+ sv = *av_fetch(pad, o->op_targ, FALSE);
>+ if (S_isdef(sv))
>+ return Nullsv;
>+ return *av_fetch(namepad, o->op_targ, FALSE);
>+ }
>+ }
>+ return Nullsv;
>+
>+ case OP_ADD:
>+ case OP_SUBTRACT:
>+ /* XXX more binops here */
>+
>+ sv = S_find_undef_var(cBINOPx(o)->op_first);
>+ if (sv)
>+ return sv;
>+ return S_find_undef_var(cBINOPx(o)->op_last);
>+ }
>+ return Nullsv;
>+}
>+
>+
> /*
> =for apidoc report_uninit
>
>@@ -573,13 +647,19 @@ Print appropriate "Use of uninitialized
> void
> Perl_report_uninit(pTHX)
> {
>- if (PL_op)
>- Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit,
>+ if (PL_op) {
>+ SV* varname = S_find_undef_var(PL_op);
>+ if (varname)
>+ Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED),
>+ "Use of uninitialized variable %s in %s",
>+ SvPV_nolen(varname), OP_DESC(PL_op));
>+ else
>+ Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit,
> " in ", OP_DESC(PL_op));
>+ }
> else
> Perl_warner(aTHX_ packWARN(WARN_UNINITIALIZED), PL_warn_uninit, "", "");
> }
>-
> /* grab a new IV body from the free list, allocating more if necessary */
>
> STATIC XPVIV*
--
Nick Ing-Simmons
http://www.ni-s.u-net.com/
Thread Previous
|
Thread Next