Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.4k
Description
When I convertedPy_REFCNT()
,Py_TYPE()
andPy_SIZE()
macros to static inline functions (issue#83754), I choseconst PyObject*
for their argument because these macros don't modify any member of the PyObject structure. When the Py_IS_TYPE() function was added, it followed the trend (commit8767ce9). The_PyObject_CAST_CONST()
macro was added to easily convert any pointer toconst PyObject*
for these macros expectingconst PyObject*
.
The problem is that passingPyObject*
to one of these functions emits a compiler warning usinggcc -Wcast-qual
. The_PyObject_CAST_CONST()
doesn't make the warning quiet.
Example explaining the issue:
staticinlineintvalue(int*p) {return*p; }#definevalue(p) value((int*)(p))intmain(){intx=1;constint*p=&x;returnvalue(p);}
Output:
$ gcc x.c -Wcast-qual -o x&& ./x;echo$?x.c: Infunction'main':x.c:2:24: warning: cast discards'const' qualifier from pointer targettype [-Wcast-qual] 2|#define value(p) value((int*)(p))| ^x.c:8:12: note:in expansion of macro'value' 8|return value(p);| ^~~~~1
In practice, the problem was that building a C extension (which includes<Python.h>
) withgcc -Wcast-qual -Werror
on Python 3.10 failed with an error on Py_IS_TYPE() implemented as:
staticinlineintPy_IS_TYPE(constPyObject*ob,constPyTypeObject*type) {returnPy_TYPE(ob)==type;}#definePy_IS_TYPE(ob,type) Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
See the issue#88544 for the compiler error. I removed the Py_TYPE() call in Py_IS_TYPE() to work around the issue:
staticinlineintPy_IS_TYPE(constPyObject*ob,constPyTypeObject*type) {// bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const// object.returnob->ob_type==type;}#definePy_IS_TYPE(ob,type) Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
But this problem strikes back when I try to convert unicodeobject.h macros to static inline functions for PEP 670 which removes the cast toPyObject*
in the limited C API version 3.11: see PR#91696 and PR#91705. For example, _Py_strhex_with_sep() and _Py_strhex_bytes_with_sep() function get aconst PyObject*
argument and use PyUnicode C functions like PyUnicode_READY(), PyUnicode_KIND() and PyUnicode_READ_CHAR(), but these PyUnicode functions expectPyObject*
: theconst
qualifier is lost. If Python/pystrhex.c is built withgcc -Wcast-qual
, gcc emits warnings on PyUnicode_KIND() and PyUnicode_READ_CHAR() calls. That's just an example of problem which can happen in C extensions as well.
To avoid these problems, I propose to avoidconst PyObject*
in Python: only usePyObject*
.