[Python-Dev] Compiler warnings (original) (raw)

James Y Knight foom at fuhm.net
Wed Feb 1 04:27:01 CET 2006


On Jan 31, 2006, at 8:16 PM, Tim Peters wrote:

[Thomas Wouters]

I noticed a few compiler warnings, when I compile Python on my amd64 with gcc 4.0.3:

Objects/longobject.c: In function 'PyLongAsDouble': Objects/longobject.c:655: warning: 'e' may be used uninitialized in this function Well, that's pretty bizarre. There's obviously no way to get to a reference to e without going through x = PyLongAsScaledDouble(vv, &e); first. That isn't a useful warning.

Look closer, and it's not quite so obvious. Here's the beginning of
PyLong_AsDouble:

double PyLongAsDouble(PyObject *vv) { int e; double x;

if (vv == NULL || !PyLongCheck(vv)) { PyErrBadInternalCall(); return -1; } x = PyLongAsScaledDouble(vv, &e); if (x == -1.0 && PyErrOccurred()) return -1.0; if (e > INTMAX / SHIFT) goto overflow;

Here's the beginning of _PyLong_AsScaledDouble:

PyLongAsScaledDouble(PyObject *vv, int *exponent) { #define NBITSWANTED 57 PyLongObject *v; double x; const double multiplier = (double)(1L << SHIFT); int i, sign; int nbitsneeded;

if (vv == NULL || !PyLongCheck(vv)) { PyErrBadInternalCall(); return -1; }

Now here's the thing: _PyLong_AsScaledDouble doesn't set exponent
before returning -1 there, which is where the warning comes from.
Now, you might protest, it's impossible to go down that code path,
because of two reasons:

  1. PyLong_AsDouble has an identical "(vv == NULL || !PyLong_Check (vv))" check, so that codepath in _PyLong_AsScaledDouble cannot
    possibly be gone down. However, PyLong_Check is a macro which expands
    to a function call to an external function, "PyType_IsSubtype((vv)-

    ob_type, (&PyLong_Type)))", so GCC has no idea it cannot return an
    error the second time. This is the kind of thing C++'s const

  2. There's a guard "(x == -1.0 && PyErr_Occurred())" before "e" is
    used in PyLong_AsDouble, which checks the conditions that
    _PyLong_AsScaledDouble set. Thus, e cannot possibly be used, even if
    the previous codepath was possible to go down. However, again,
    PyErr_BadInternalCall() is an external function, so the compiler has
    no way of knowing that PyErr_BadInternalCall() causes PyErr_Occurred () to return true.

So in conclusion, from all the information the compiler has available
to it, it is giving a correct diagnostic.

James



More information about the Python-Dev mailing list