[Martin v. Löwis]
It inlines the function to make this determination.
Very cool! Is this a new(ish) behavior?
Now, it's not true that e can be uninitialized then, but there the gcc logic fails:
That's fine -- there are any number of ways a compiler can reach a wrong conclusion by making conservative assumptions, and so long as it's actually staring at code I don't mind that at all. What I would mind is griping about some_func(&a) possibly not setting `a` in the _absence_ of staring at `some_func`'s internals.
If you take the
if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; }
case in _PyLong_AsScaledDouble, *exponent won't be initialized.
Certainly, and I don't expect a compiler to realize that this branch is impossible when _PyLong_AsScaledDouble is invoked from the call sites where gcc is complaining.
Then, in PyLong_AsDouble, with
x = _PyLong_AsScaledDouble(vv, &e); if (x == -1.0 && PyErr_Occurred()) return -1.0;
it looks like the return would not be taken if PyErr_Occurred returns false. Of course, it won't, but that is difficult to analyse.
PyLong_AsDouble already did: if (vv == NULL || !PyLong_Check(vv)) { PyErr_BadInternalCall(); return -1; } before calling _PyLong_AsScaledDouble(), and the latter's `x` is the former's `vv`. That is, the check you showed above from _PyLong_AsScaledDouble() is exactly the same as the check PyLong_AsDouble already made. To exploit that, gcc would have to realize PyLong_Check() is a "pure enough" function, and I don't expect gcc to be able to figure that out.
I don't know. Is this version of gcc broken in some way relative to other gcc versions, or newer, or ... ? We certainly don't want to see warnings under gcc, since it's heavily used, but I'm not clear on why other versions of gcc aren't producing these warnings (or are they, and people have been ignoring that?).
gcc 4 does inlining in far more cases now.
OK then. Thomas, for these _PyLong_AsScaledDouble()-caller cases, I suggest doing whatever obvious thing manages to silence the warning. For example, in PyLong_AsDouble: int e = -1; /* silence gcc warning */ and then add: assert(e >= 0); after the call.