@@ -2213,15 +2213,6 @@ shift_guard(PyObject *lhs, PyObject *rhs)
22132213 return (is_compactlong (lhs ) && is_compactnonnegativelong (rhs ) && (_PyLong_CompactValue ((PyLongObject * )rhs ) <= 16 ) );
22142214}
22152215
2216- #define BITWISE_LONGS_ACTION_STWODIGITS (NAME , OP ) \
2217- static PyObject * \
2218- (NAME)(PyObject *lhs, PyObject *rhs) \
2219- { \
2220- stwodigits rhs_val = (stwodigits)_PyLong_CompactValue((PyLongObject *)rhs); \
2221- stwodigits lhs_val = (stwodigits) _PyLong_CompactValue((PyLongObject *)lhs); \
2222- return PyLong_FromLongLong(lhs_val OP rhs_val); \
2223- }
2224-
22252216#define BITWISE_LONGS_ACTION (NAME , OP ) \
22262217 static PyObject * \
22272218 (NAME)(PyObject *lhs, PyObject *rhs) \
@@ -2233,11 +2224,22 @@ shift_guard(PyObject *lhs, PyObject *rhs)
22332224BITWISE_LONGS_ACTION (compactlongs_or , |)
22342225BITWISE_LONGS_ACTION (compactlongs_and , & )
22352226BITWISE_LONGS_ACTION (compactlongs_xor , ^)
2236- BITWISE_LONGS_ACTION_STWODIGITS (compactlongs_lshift , <<)
22372227BITWISE_LONGS_ACTION (compactlongs_rshift , >>)
2238- #undef BITWISE_LONGS_ACTION_STWODIGITS
22392228#undef BITWISE_LONGS_ACTION
22402229
2230+ static PyObject *
2231+ compactlongs_lshift (PyObject * lhs , PyObject * rhs )
2232+ {
2233+ // Left-shifting a negative signed value is undefined behavior in C, so
2234+ // perform the shift in unsigned arithmetic and reinterpret. The guard
2235+ // limits rhs_val to [0, 16] and compact long magnitudes fit comfortably
2236+ // in stwodigits with that headroom, so no overflow occurs.
2237+ Py_ssize_t rhs_val = _PyLong_CompactValue ((PyLongObject * )rhs );
2238+ Py_ssize_t lhs_val = _PyLong_CompactValue ((PyLongObject * )lhs );
2239+ stwodigits result = (stwodigits )((unsigned long long )lhs_val << rhs_val );
2240+ return PyLong_FromLongLong (result );
2241+ }
2242+
22412243/* float-long */
22422244
22432245static inline int
0 commit comments