From f797c86c31f4bceabb386278f0d1686cb218da9b Mon Sep 17 00:00:00 2001 From: Philipp Wagner Date: Mon, 15 May 2023 20:51:07 +0200 Subject: Fix a signedness compiler warning in vector.to_py (GH-5438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling cythonized code which uses `std::vector` we get the following compiler warning on GCC 8 and Python 3.9 (which is turned into an error in our case): ``` my_file.cpp: In function ‘PyObject* __pyx_convert_vector_to_py_int(const std::vector&)’: my_file.cpp:4716:33: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare] for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { ~~~~~~~~~~^~~~~~~~~~~ ``` The generated code in question is as follows: ``` /* "vector.to_py":75 * cdef object item * * for i in range(v.size()): # <<<<<<<<<<<<<< * item = v[i] * Py_INCREF(item) */ __pyx_t_3 = __pyx_v_v.size(); __pyx_t_4 = __pyx_t_3; for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { __pyx_v_i = __pyx_t_5; ``` `__pyx_t_5` is of type `‘Py_ssize_t’` (signed), and `__pyx_t_4` aka `__pyx_t_3` is `size_t` (unsigned), causing GCC to rightfully complain. Fix the generated code by explicitly using the signed variant of the vector's size in the loop. This bug has been introduced in https://github.com/cython/cython/pull/4081, which also contains some discussion on the use of signed vs unsigned types. This patch chooses to keep the status quo and only fixes the compiler warning. --- Cython/Utility/CppConvert.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cython/Utility/CppConvert.pyx b/Cython/Utility/CppConvert.pyx index 35f4c50ef..1c6239b2b 100644 --- a/Cython/Utility/CppConvert.pyx +++ b/Cython/Utility/CppConvert.pyx @@ -66,13 +66,14 @@ cdef extern from "Python.h": cdef object {{cname}}(const vector[X]& v): if v.size() > PY_SSIZE_T_MAX: raise MemoryError() + v_size_signed = v.size() - o = PyList_New( v.size()) + o = PyList_New(v_size_signed) cdef Py_ssize_t i cdef object item - for i in range(v.size()): + for i in range(v_size_signed): item = v[i] Py_INCREF(item) PyList_SET_ITEM(o, i, item) -- cgit v1.2.1