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 'PyLong_AsDouble': >> 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 = _PyLong_AsScaledDouble(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 > PyLong_AsDouble(PyObject *vv) > { > int e; > double x; > > if (vv == NULL || !PyLong_Check(vv)) { > PyErr_BadInternalCall(); > return -1; > } > x = _PyLong_AsScaledDouble(vv, &e); > if (x == -1.0 && PyErr_Occurred()) > return -1.0; > if (e > INT_MAX / SHIFT) > goto overflow; Here's the beginning of _PyLong_AsScaledDouble: > _PyLong_AsScaledDouble(PyObject *vv, int *exponent) > { > #define NBITS_WANTED 57 > PyLongObject *v; > double x; > const double multiplier = (double)(1L << SHIFT); > int i, sign; > int nbitsneeded; > > if (vv == NULL || !PyLong_Check(vv)) { > PyErr_BadInternalCall(); > 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 _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com