Skip to content

Commit fe2978b

Browse files
authored
bpo-39573: Convert Py_REFCNT and Py_SIZE to functions (GH-20429)
Convert Py_REFCNT() and Py_SIZE() macros to static inline functions. They cannot be used as l-value anymore: use Py_SET_REFCNT() and Py_SET_SIZE() to set an object reference count and size. Replace &Py_SIZE(self) with &((PyVarObject*)self)->ob_size in arraymodule.c. This change is backward incompatible on purpose, to prepare the C API for an opaque PyObject structure.
1 parent 20941de commit fe2978b

File tree

6 files changed

+44
-14
lines changed

6 files changed

+44
-14
lines changed

Doc/c-api/structures.rst

+10-9
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ the definition of all other Python objects.
8888
.. versionadded:: 3.9
8989
9090
91-
.. c:macro:: Py_REFCNT(o)
91+
.. c:function:: Py_ssize_t Py_REFCNT(const PyObject *o)
9292
93-
This macro is used to access the :attr:`ob_refcnt` member of a Python
94-
object.
95-
It expands to::
93+
Get the reference count of the Python object *o*.
9694
97-
(((PyObject*)(o))->ob_refcnt)
95+
.. versionchanged:: 3.10
96+
:c:func:`Py_REFCNT()` is changed to the inline static function.
97+
Use :c:func:`Py_SET_REFCNT()` to set an object reference count.
9898
9999
100100
.. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)
@@ -104,12 +104,13 @@ the definition of all other Python objects.
104104
.. versionadded:: 3.9
105105
106106
107-
.. c:macro:: Py_SIZE(o)
107+
.. c:function:: Py_ssize_t Py_SIZE(const PyVarObject *o)
108108
109-
This macro is used to access the :attr:`ob_size` member of a Python object.
110-
It expands to::
109+
Get the size of the Python object *o*.
111110
112-
(((PyVarObject*)(o))->ob_size)
111+
.. versionchanged:: 3.10
112+
:c:func:`Py_SIZE()` is changed to the inline static function.
113+
Use :c:func:`Py_SET_SIZE()` to set an object size.
113114
114115
115116
.. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)

Doc/whatsnew/3.10.rst

+9
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ Porting to Python 3.10
138138
see :c:func:`Py_SET_TYPE()` (available since Python 3.9).
139139
(Contributed by Dong-hee Na in :issue:`39573`.)
140140

141+
* Since :c:func:`Py_REFCNT()` is changed to the inline static function,
142+
``Py_REFCNT(obj) = new_refcnt`` must be replaced with ``Py_SET_REFCNT(obj, new_refcnt)``:
143+
see :c:func:`Py_SET_REFCNT()` (available since Python 3.9).
144+
(Contributed by Victor Stinner in :issue:`39573`.)
145+
146+
* Since :c:func:`Py_SIZE()` is changed to the inline static function,
147+
``Py_SIZE(obj) = new_size`` must be replaced with ``Py_SET_SIZE(obj, new_size)``:
148+
see :c:func:`Py_SET_SIZE()` (available since Python 3.9).
149+
(Contributed by Victor Stinner in :issue:`39573`.)
141150

142151
Removed
143152
-------

Include/object.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -119,30 +119,45 @@ typedef struct {
119119

120120
/* Cast argument to PyVarObject* type. */
121121
#define _PyVarObject_CAST(op) ((PyVarObject*)(op))
122+
#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op))
123+
124+
125+
static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) {
126+
return ob->ob_refcnt;
127+
}
128+
#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob))
129+
130+
131+
static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) {
132+
return ob->ob_size;
133+
}
134+
#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob))
122135

123-
#define Py_REFCNT(ob) (_PyObject_CAST(ob)->ob_refcnt)
124-
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
125136

126137
static inline PyTypeObject* _Py_TYPE(const PyObject *ob) {
127138
return ob->ob_type;
128139
}
129140
#define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob))
130141

142+
131143
static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
132144
return ob->ob_type == type;
133145
}
134146
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
135147

148+
136149
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
137150
ob->ob_refcnt = refcnt;
138151
}
139152
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
140153

154+
141155
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
142156
ob->ob_type = type;
143157
}
144158
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
145159

160+
146161
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
147162
ob->ob_size = size;
148163
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Convert :c:func:`Py_REFCNT` and :c:func:`Py_SIZE` macros to static inline
2+
functions. They cannot be used as l-value anymore: use
3+
:c:func:`Py_SET_REFCNT` and :c:func:`Py_SET_SIZE` to set an object reference
4+
count and size. This change is backward incompatible on purpose, to prepare
5+
the C API for an opaque :c:type:`PyObject` structure.

Modules/arraymodule.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2525,14 +2525,14 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
25252525
Py_INCREF(self);
25262526
if (view->buf == NULL)
25272527
view->buf = (void *)emptybuf;
2528-
view->len = (Py_SIZE(self)) * self->ob_descr->itemsize;
2528+
view->len = Py_SIZE(self) * self->ob_descr->itemsize;
25292529
view->readonly = 0;
25302530
view->ndim = 1;
25312531
view->itemsize = self->ob_descr->itemsize;
25322532
view->suboffsets = NULL;
25332533
view->shape = NULL;
25342534
if ((flags & PyBUF_ND)==PyBUF_ND) {
2535-
view->shape = &((Py_SIZE(self)));
2535+
view->shape = &((PyVarObject*)self)->ob_size;
25362536
}
25372537
view->strides = NULL;
25382538
if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES)

Objects/tupleobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ tuple_alloc(Py_ssize_t size)
8282
numfree[size]--;
8383
/* Inline PyObject_InitVar */
8484
#ifdef Py_TRACE_REFS
85-
Py_SIZE(op) = size;
85+
Py_SET_SIZE(op, size);
8686
Py_SET_TYPE(op, &PyTuple_Type);
8787
#endif
8888
_Py_NewReference((PyObject *)op);

0 commit comments

Comments
 (0)