diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 5535f42ac12..b2392fa5e19 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -88,13 +88,13 @@ the definition of all other Python objects. .. versionadded:: 3.9 -.. c:macro:: Py_REFCNT(o) +.. c:function:: Py_ssize_t Py_REFCNT(const PyObject *o) - This macro is used to access the :attr:`ob_refcnt` member of a Python - object. - It expands to:: + Get the reference count of the Python object *o*. - (((PyObject*)(o))->ob_refcnt) + .. versionchanged:: 3.10 + :c:func:`Py_REFCNT()` is changed to the inline static function. + Use :c:func:`Py_SET_REFCNT()` to set an object reference count. .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt) @@ -104,12 +104,13 @@ the definition of all other Python objects. .. versionadded:: 3.9 -.. c:macro:: Py_SIZE(o) +.. c:function:: Py_ssize_t Py_SIZE(const PyVarObject *o) - This macro is used to access the :attr:`ob_size` member of a Python object. - It expands to:: + Get the size of the Python object *o*. - (((PyVarObject*)(o))->ob_size) + .. versionchanged:: 3.10 + :c:func:`Py_SIZE()` is changed to the inline static function. + Use :c:func:`Py_SET_SIZE()` to set an object size. .. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index fabd9a2463e..9edef1ed87b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -138,6 +138,15 @@ Porting to Python 3.10 see :c:func:`Py_SET_TYPE()` (available since Python 3.9). (Contributed by Dong-hee Na in :issue:`39573`.) +* Since :c:func:`Py_REFCNT()` is changed to the inline static function, + ``Py_REFCNT(obj) = new_refcnt`` must be replaced with ``Py_SET_REFCNT(obj, new_refcnt)``: + see :c:func:`Py_SET_REFCNT()` (available since Python 3.9). + (Contributed by Victor Stinner in :issue:`39573`.) + +* Since :c:func:`Py_SIZE()` is changed to the inline static function, + ``Py_SIZE(obj) = new_size`` must be replaced with ``Py_SET_SIZE(obj, new_size)``: + see :c:func:`Py_SET_SIZE()` (available since Python 3.9). + (Contributed by Victor Stinner in :issue:`39573`.) Removed ------- diff --git a/Include/object.h b/Include/object.h index 5ad05699bb4..537567040f9 100644 --- a/Include/object.h +++ b/Include/object.h @@ -119,30 +119,45 @@ typedef struct { /* Cast argument to PyVarObject* type. */ #define _PyVarObject_CAST(op) ((PyVarObject*)(op)) +#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op)) + + +static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { + return ob->ob_refcnt; +} +#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob)) + + +static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) { + return ob->ob_size; +} +#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob)) -#define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt) -#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size) static inline PyTypeObject* _Py_TYPE(const PyObject *ob) { return ob->ob_type; } #define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob)) + static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { return ob->ob_type == type; } #define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) + static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; } #define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) + static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; } #define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) + static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; } diff --git a/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst b/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst new file mode 100644 index 00000000000..f8f675cebca --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst @@ -0,0 +1,5 @@ +Convert :c:func:`Py_REFCNT` and :c:func:`Py_SIZE` macros to static inline +functions. They cannot be used as l-value anymore: use +:c:func:`Py_SET_REFCNT` and :c:func:`Py_SET_SIZE` to set an object reference +count and size. This change is backward incompatible on purpose, to prepare +the C API for an opaque :c:type:`PyObject` structure. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index fb1b82cd6a6..4c3ddc3ac24 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2525,14 +2525,14 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags) Py_INCREF(self); if (view->buf == NULL) view->buf = (void *)emptybuf; - view->len = (Py_SIZE(self)) * self->ob_descr->itemsize; + view->len = Py_SIZE(self) * self->ob_descr->itemsize; view->readonly = 0; view->ndim = 1; view->itemsize = self->ob_descr->itemsize; view->suboffsets = NULL; view->shape = NULL; if ((flags & PyBUF_ND)==PyBUF_ND) { - view->shape = &((Py_SIZE(self))); + view->shape = &((PyVarObject*)self)->ob_size; } view->strides = NULL; if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index e4c0c91cfe8..43706c22b92 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -82,7 +82,7 @@ tuple_alloc(Py_ssize_t size) numfree[size]--; /* Inline PyObject_InitVar */ #ifdef Py_TRACE_REFS - Py_SIZE(op) = size; + Py_SET_SIZE(op, size); Py_SET_TYPE(op, &PyTuple_Type); #endif _Py_NewReference((PyObject *)op);