From d4624c3331a54506b9c678ad096e56366b66f51d Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 24 Jan 2009 15:02:35 +0000 Subject: [PATCH] Some minor cleanups in PyLong_FromLong: - fast path wasn't being properly taken for negative ints; thanks Victor Stinner for pointing this out. - use Py_SAFE_DOWNCAST instead of direct casting to digit (it's safer, especially if we ever consider moving to 30-bit digits) - cleaner way to write negation --- Objects/longobject.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 46efe5f291e..a932df7edaa 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -175,7 +175,7 @@ PyObject * PyLong_FromLong(long ival) { PyLongObject *v; - unsigned long abs_ival; + unsigned long abs_ival; unsigned long t; /* unsigned so >> doesn't propagate sign bit */ int ndigits = 0; int sign = 1; @@ -183,33 +183,35 @@ PyLong_FromLong(long ival) CHECK_SMALL_INT(ival); if (ival < 0) { - /* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then - ANSI C says that the result of -ival is undefined when ival - == LONG_MIN. Hence the following workaround. */ - abs_ival = (unsigned long)(-1-ival) + 1; + /* negate: can't write this as abs_ival = -ival since that + invokes undefined behaviour when ival is LONG_MIN */ + abs_ival = 0U-(unsigned long)ival; sign = -1; } else { abs_ival = (unsigned long)ival; } - /* Fast path for single-digits ints */ - if (!(ival>>PyLong_SHIFT)) { + /* Fast path for single-digit ints */ + if (!(abs_ival >> PyLong_SHIFT)) { v = _PyLong_New(1); if (v) { Py_SIZE(v) = sign; - v->ob_digit[0] = (digit)ival; + v->ob_digit[0] = Py_SAFE_DOWNCAST( + abs_ival, unsigned long, digit); } return (PyObject*)v; } /* 2 digits */ - if (!(ival >> 2*PyLong_SHIFT)) { + if (!(abs_ival >> 2*PyLong_SHIFT)) { v = _PyLong_New(2); if (v) { Py_SIZE(v) = 2*sign; - v->ob_digit[0] = (digit)ival & PyLong_MASK; - v->ob_digit[1] = (digit)(ival >> PyLong_SHIFT); + v->ob_digit[0] = Py_SAFE_DOWNCAST( + abs_ival & PyLong_MASK, unsigned long, digit); + v->ob_digit[1] = Py_SAFE_DOWNCAST( + abs_ival >> PyLong_SHIFT, unsigned long, digit); } return (PyObject*)v; } @@ -226,7 +228,8 @@ PyLong_FromLong(long ival) Py_SIZE(v) = ndigits*sign; t = abs_ival; while (t) { - *p++ = (digit)(t & PyLong_MASK); + *p++ = Py_SAFE_DOWNCAST( + t & PyLong_MASK, unsigned long, digit); t >>= PyLong_SHIFT; } }