From db388df1d9aff02f791fe01c7c2b28d73982dce6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 May 2022 11:49:56 +0200 Subject: [PATCH] gh-89653: PEP 670: Convert PyUnicode_KIND() macro to function (#92705) In the limited C API version 3.12, PyUnicode_KIND() is now implemented as a static inline function. Keep the macro for the regular C API and for the limited C API version 3.11 and older to prevent introducing new compiler warnings. Update _decimal.c and stringlib/eq.h for PyUnicode_KIND(). --- Include/cpython/unicodeobject.h | 16 +++++++++++++++- Modules/_decimal/_decimal.c | 12 ++++++------ Objects/stringlib/eq.h | 3 --- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h index 8c53962437b..030614e2633 100644 --- a/Include/cpython/unicodeobject.h +++ b/Include/cpython/unicodeobject.h @@ -242,9 +242,23 @@ enum PyUnicode_Kind { PyUnicode_4BYTE_KIND = 4 }; -/* Return one of the PyUnicode_*_KIND values defined above. */ +// PyUnicode_KIND(): Return one of the PyUnicode_*_KIND values defined above. +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030c0000 +// gh-89653: Converting this macro to a static inline function would introduce +// new compiler warnings on "kind < PyUnicode_KIND(str)" (compare signed and +// unsigned numbers) where kind type is an int or on +// "unsigned int kind = PyUnicode_KIND(str)" (cast signed to unsigned). +// Only declare the function as static inline function in the limited C API +// version 3.12 which is stricter. #define PyUnicode_KIND(op) \ (_PyASCIIObject_CAST(op)->state.kind) +#else +// Limited C API 3.12 and newer +static inline int PyUnicode_KIND(PyObject *op) { + assert(PyUnicode_IS_READY(op)); + return _PyASCIIObject_CAST(op)->state.kind; +} +#endif /* Return a void pointer to the raw unicode buffer. */ static inline void* _PyUnicode_COMPACT_DATA(PyObject *op) { diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 65885965ff0..5cbddac6232 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1933,7 +1933,7 @@ is_space(enum PyUnicode_Kind kind, const void *data, Py_ssize_t pos) Return NULL if malloc fails and an empty string if invalid characters are found. */ static char * -numeric_as_ascii(const PyObject *u, int strip_ws, int ignore_underscores) +numeric_as_ascii(PyObject *u, int strip_ws, int ignore_underscores) { enum PyUnicode_Kind kind; const void *data; @@ -2047,7 +2047,7 @@ PyDecType_FromCStringExact(PyTypeObject *type, const char *s, /* Return a new PyDecObject or a subtype from a PyUnicodeObject. */ static PyObject * -PyDecType_FromUnicode(PyTypeObject *type, const PyObject *u, +PyDecType_FromUnicode(PyTypeObject *type, PyObject *u, PyObject *context) { PyObject *dec; @@ -2067,7 +2067,7 @@ PyDecType_FromUnicode(PyTypeObject *type, const PyObject *u, * conversion. If the conversion is not exact, fail with InvalidOperation. * Allow leading and trailing whitespace in the input operand. */ static PyObject * -PyDecType_FromUnicodeExactWS(PyTypeObject *type, const PyObject *u, +PyDecType_FromUnicodeExactWS(PyTypeObject *type, PyObject *u, PyObject *context) { PyObject *dec; @@ -2150,7 +2150,7 @@ PyDecType_FromSsizeExact(PyTypeObject *type, mpd_ssize_t v, PyObject *context) /* Convert from a PyLongObject. The context is not modified; flags set during conversion are accumulated in the status parameter. */ static PyObject * -dec_from_long(PyTypeObject *type, const PyObject *v, +dec_from_long(PyTypeObject *type, PyObject *v, const mpd_context_t *ctx, uint32_t *status) { PyObject *dec; @@ -2201,7 +2201,7 @@ dec_from_long(PyTypeObject *type, const PyObject *v, /* Return a new PyDecObject from a PyLongObject. Use the context for conversion. */ static PyObject * -PyDecType_FromLong(PyTypeObject *type, const PyObject *v, PyObject *context) +PyDecType_FromLong(PyTypeObject *type, PyObject *v, PyObject *context) { PyObject *dec; uint32_t status = 0; @@ -2227,7 +2227,7 @@ PyDecType_FromLong(PyTypeObject *type, const PyObject *v, PyObject *context) /* Return a new PyDecObject from a PyLongObject. Use a maximum context for conversion. If the conversion is not exact, set InvalidOperation. */ static PyObject * -PyDecType_FromLongExact(PyTypeObject *type, const PyObject *v, +PyDecType_FromLongExact(PyTypeObject *type, PyObject *v, PyObject *context) { PyObject *dec; diff --git a/Objects/stringlib/eq.h b/Objects/stringlib/eq.h index 2f2438845a6..2eac4baf5ca 100644 --- a/Objects/stringlib/eq.h +++ b/Objects/stringlib/eq.h @@ -6,9 +6,6 @@ Py_LOCAL_INLINE(int) unicode_eq(PyObject *a, PyObject *b) { - assert(PyUnicode_Check(a)); - assert(PyUnicode_Check(b)); - if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b)) return 0; if (PyUnicode_GET_LENGTH(a) == 0)