Skip to content

Commit 3a803bc

Browse files
authored
Revert "gh-98724: Fix Py_CLEAR() macro side effects" (#99737)
Revert "gh-98724: Fix Py_CLEAR() macro side effects (#99100)" This reverts commit c03e05c.
1 parent 0da7283 commit 3a803bc

File tree

5 files changed

+29
-172
lines changed

5 files changed

+29
-172
lines changed

Doc/c-api/refcounting.rst

+2-44
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
Reference Counting
88
******************
99

10-
The functions and macros in this section are used for managing reference counts
11-
of Python objects.
10+
The macros in this section are used for managing reference counts of Python
11+
objects.
1212

1313

1414
.. c:function:: Py_ssize_t Py_REFCNT(PyObject *o)
@@ -129,11 +129,6 @@ of Python objects.
129129
It is a good idea to use this macro whenever decrementing the reference
130130
count of an object that might be traversed during garbage collection.
131131
132-
.. versionchanged:: 3.12
133-
The macro argument is now only evaluated once. If the argument has side
134-
effects, these are no longer duplicated.
135-
136-
137132
.. c:function:: void Py_IncRef(PyObject *o)
138133
139134
Increment the reference count for object *o*. A function version of :c:func:`Py_XINCREF`.
@@ -144,40 +139,3 @@ of Python objects.
144139
145140
Decrement the reference count for object *o*. A function version of :c:func:`Py_XDECREF`.
146141
It can be used for runtime dynamic embedding of Python.
147-
148-
149-
.. c:macro:: Py_SETREF(dst, src)
150-
151-
Macro safely decrementing the `dst` reference count and setting `dst` to
152-
`src`.
153-
154-
As in case of :c:func:`Py_CLEAR`, "the obvious" code can be deadly::
155-
156-
Py_DECREF(dst);
157-
dst = src;
158-
159-
The safe way is::
160-
161-
Py_SETREF(dst, src);
162-
163-
That arranges to set `dst` to `src` _before_ decrementing reference count of
164-
*dst* old value, so that any code triggered as a side-effect of `dst`
165-
getting torn down no longer believes `dst` points to a valid object.
166-
167-
.. versionadded:: 3.6
168-
169-
.. versionchanged:: 3.12
170-
The macro arguments are now only evaluated once. If an argument has side
171-
effects, these are no longer duplicated.
172-
173-
174-
.. c:macro:: Py_XSETREF(dst, src)
175-
176-
Variant of :c:macro:`Py_SETREF` macro that uses :c:func:`Py_XDECREF` instead
177-
of :c:func:`Py_DECREF`.
178-
179-
.. versionadded:: 3.6
180-
181-
.. versionchanged:: 3.12
182-
The macro arguments are now only evaluated once. If an argument has side
183-
effects, these are no longer duplicated.

Doc/whatsnew/3.12.rst

-5
Original file line numberDiff line numberDiff line change
@@ -822,11 +822,6 @@ Porting to Python 3.12
822822
:class:`bytes` type is accepted for bytes strings.
823823
(Contributed by Victor Stinner in :gh:`98393`.)
824824

825-
* The :c:macro:`Py_CLEAR`, :c:macro:`Py_SETREF` and :c:macro:`Py_XSETREF`
826-
macros now only evaluate their argument once. If the argument has side
827-
effects, these side effects are no longer duplicated.
828-
(Contributed by Victor Stinner in :gh:`98724`.)
829-
830825
Deprecated
831826
----------
832827

Include/cpython/object.h

+20-24
Original file line numberDiff line numberDiff line change
@@ -305,41 +305,37 @@ _PyObject_GenericSetAttrWithDict(PyObject *, PyObject *,
305305

306306
PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
307307

308-
/* Safely decref `dst` and set `dst` to `src`.
308+
/* Safely decref `op` and set `op` to `op2`.
309309
*
310310
* As in case of Py_CLEAR "the obvious" code can be deadly:
311311
*
312-
* Py_DECREF(dst);
313-
* dst = src;
312+
* Py_DECREF(op);
313+
* op = op2;
314314
*
315315
* The safe way is:
316316
*
317-
* Py_SETREF(dst, src);
317+
* Py_SETREF(op, op2);
318318
*
319-
* That arranges to set `dst` to `src` _before_ decref'ing, so that any code
320-
* triggered as a side-effect of `dst` getting torn down no longer believes
321-
* `dst` points to a valid object.
319+
* That arranges to set `op` to `op2` _before_ decref'ing, so that any code
320+
* triggered as a side-effect of `op` getting torn down no longer believes
321+
* `op` points to a valid object.
322322
*
323-
* gh-98724: Use the _tmp_dst_ptr variable to evaluate the 'dst' macro argument
324-
* exactly once, to prevent the duplication of side effects in this macro.
323+
* Py_XSETREF is a variant of Py_SETREF that uses Py_XDECREF instead of
324+
* Py_DECREF.
325325
*/
326-
#define Py_SETREF(dst, src) \
327-
do { \
328-
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
329-
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
330-
*_tmp_dst_ptr = _PyObject_CAST(src); \
331-
Py_DECREF(_tmp_dst); \
326+
327+
#define Py_SETREF(op, op2) \
328+
do { \
329+
PyObject *_py_tmp = _PyObject_CAST(op); \
330+
(op) = (op2); \
331+
Py_DECREF(_py_tmp); \
332332
} while (0)
333333

334-
/* Py_XSETREF() is a variant of Py_SETREF() that uses Py_XDECREF() instead of
335-
* Py_DECREF().
336-
*/
337-
#define Py_XSETREF(dst, src) \
338-
do { \
339-
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
340-
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
341-
*_tmp_dst_ptr = _PyObject_CAST(src); \
342-
Py_XDECREF(_tmp_dst); \
334+
#define Py_XSETREF(op, op2) \
335+
do { \
336+
PyObject *_py_tmp = _PyObject_CAST(op); \
337+
(op) = (op2); \
338+
Py_XDECREF(_py_tmp); \
343339
} while (0)
344340

345341

Include/object.h

+7-12
Original file line numberDiff line numberDiff line change
@@ -598,21 +598,16 @@ static inline void Py_DECREF(PyObject *op)
598598
* one of those can't cause problems -- but in part that relies on that
599599
* Python integers aren't currently weakly referencable. Best practice is
600600
* to use Py_CLEAR() even if you can't think of a reason for why you need to.
601-
*
602-
* gh-98724: Use the _py_tmp_ptr variable to evaluate the macro argument
603-
* exactly once, to prevent the duplication of side effects in this macro.
604601
*/
605-
#define Py_CLEAR(op) \
606-
do { \
607-
PyObject **_py_tmp_ptr = _Py_CAST(PyObject**, &(op)); \
608-
if (*_py_tmp_ptr != NULL) { \
609-
PyObject* _py_tmp = (*_py_tmp_ptr); \
610-
*_py_tmp_ptr = NULL; \
611-
Py_DECREF(_py_tmp); \
612-
} \
602+
#define Py_CLEAR(op) \
603+
do { \
604+
PyObject *_py_tmp = _PyObject_CAST(op); \
605+
if (_py_tmp != NULL) { \
606+
(op) = NULL; \
607+
Py_DECREF(_py_tmp); \
608+
} \
613609
} while (0)
614610

615-
616611
/* Function to use in case the object pointer can be NULL: */
617612
static inline void Py_XINCREF(PyObject *op)
618613
{

Modules/_testcapimodule.c

-87
Original file line numberDiff line numberDiff line change
@@ -2589,91 +2589,6 @@ test_set_type_size(PyObject *self, PyObject *Py_UNUSED(ignored))
25892589
}
25902590

25912591

2592-
// Test Py_CLEAR() macro
2593-
static PyObject*
2594-
test_py_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
2595-
{
2596-
// simple case with a variable
2597-
PyObject *obj = PyList_New(0);
2598-
if (obj == NULL) {
2599-
return NULL;
2600-
}
2601-
Py_CLEAR(obj);
2602-
assert(obj == NULL);
2603-
2604-
// gh-98724: complex case, Py_CLEAR() argument has a side effect
2605-
PyObject* array[1];
2606-
array[0] = PyList_New(0);
2607-
if (array[0] == NULL) {
2608-
return NULL;
2609-
}
2610-
2611-
PyObject **p = array;
2612-
Py_CLEAR(*p++);
2613-
assert(array[0] == NULL);
2614-
assert(p == array + 1);
2615-
2616-
Py_RETURN_NONE;
2617-
}
2618-
2619-
2620-
// Test Py_SETREF() and Py_XSETREF() macros, similar to test_py_clear()
2621-
static PyObject*
2622-
test_py_setref(PyObject *self, PyObject *Py_UNUSED(ignored))
2623-
{
2624-
// Py_SETREF() simple case with a variable
2625-
PyObject *obj = PyList_New(0);
2626-
if (obj == NULL) {
2627-
return NULL;
2628-
}
2629-
Py_SETREF(obj, NULL);
2630-
assert(obj == NULL);
2631-
2632-
// Py_XSETREF() simple case with a variable
2633-
PyObject *obj2 = PyList_New(0);
2634-
if (obj2 == NULL) {
2635-
return NULL;
2636-
}
2637-
Py_XSETREF(obj2, NULL);
2638-
assert(obj2 == NULL);
2639-
// test Py_XSETREF() when the argument is NULL
2640-
Py_XSETREF(obj2, NULL);
2641-
assert(obj2 == NULL);
2642-
2643-
// gh-98724: complex case, Py_SETREF() argument has a side effect
2644-
PyObject* array[1];
2645-
array[0] = PyList_New(0);
2646-
if (array[0] == NULL) {
2647-
return NULL;
2648-
}
2649-
2650-
PyObject **p = array;
2651-
Py_SETREF(*p++, NULL);
2652-
assert(array[0] == NULL);
2653-
assert(p == array + 1);
2654-
2655-
// gh-98724: complex case, Py_XSETREF() argument has a side effect
2656-
PyObject* array2[1];
2657-
array2[0] = PyList_New(0);
2658-
if (array2[0] == NULL) {
2659-
return NULL;
2660-
}
2661-
2662-
PyObject **p2 = array2;
2663-
Py_XSETREF(*p2++, NULL);
2664-
assert(array2[0] == NULL);
2665-
assert(p2 == array2 + 1);
2666-
2667-
// test Py_XSETREF() when the argument is NULL
2668-
p2 = array2;
2669-
Py_XSETREF(*p2++, NULL);
2670-
assert(array2[0] == NULL);
2671-
assert(p2 == array2 + 1);
2672-
2673-
Py_RETURN_NONE;
2674-
}
2675-
2676-
26772592
#define TEST_REFCOUNT() \
26782593
do { \
26792594
PyObject *obj = PyList_New(0); \
@@ -3337,8 +3252,6 @@ static PyMethodDef TestMethods[] = {
33373252
{"pynumber_tobase", pynumber_tobase, METH_VARARGS},
33383253
{"without_gc", without_gc, METH_O},
33393254
{"test_set_type_size", test_set_type_size, METH_NOARGS},
3340-
{"test_py_clear", test_py_clear, METH_NOARGS},
3341-
{"test_py_setref", test_py_setref, METH_NOARGS},
33423255
{"test_refcount_macros", test_refcount_macros, METH_NOARGS},
33433256
{"test_refcount_funcs", test_refcount_funcs, METH_NOARGS},
33443257
{"test_py_is_macros", test_py_is_macros, METH_NOARGS},

0 commit comments

Comments
 (0)