Front page | perl.perl5.porters |
Postings from May 2003
Proposal: include var name in 'use of undefined value' warning
Thread Next
From:
Dave Mitchell
Date:
May 9, 2003 15:40
Subject:
Proposal: include var name in 'use of undefined value' warning
Message ID:
20030509224103.GB20871@fdgroup.com
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?
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.
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*
Thread Next
-
Proposal: include var name in 'use of undefined value' warning
by Dave Mitchell