Skip to content

Commit 1ed296f

Browse files
committed
gh-121617: Include <string.h> for Py_CLEAR() macro
If the _Py_TYPEOF macro is not available, include <string.h> to get memcpy() for the Py_CLEAR() macro. The limited C API version 3.11 and newer doesn't include <string.h> anymore. Add a Py_CLEAR() test in test_cext. Modify also _Py_TYPEOF to use C23 typeof() if available.
1 parent b121dc4 commit 1ed296f

4 files changed

Lines changed: 18 additions & 2 deletions

File tree

Include/pyport.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,8 +567,11 @@ extern "C" {
567567
//
568568
// Example: _Py_TYPEOF(x) x_copy = (x);
569569
//
570-
// The macro is only defined if GCC or clang compiler is used.
571-
#if defined(__GNUC__) || defined(__clang__)
570+
// On C23, use typeof(). Otherwise, the macro is only defined
571+
// if GCC or clang compiler is used.
572+
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
573+
# define _Py_TYPEOF(expr) typeof(expr)
574+
#elif defined(__GNUC__) || defined(__clang__)
572575
# define _Py_TYPEOF(expr) __typeof__(expr)
573576
#endif
574577

Include/refcount.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
471471
* and so avoid type punning. Otherwise, use memcpy() which causes type erasure
472472
* and so prevents the compiler to reuse an old cached 'op' value after
473473
* Py_CLEAR().
474+
*
475+
* Include <string.h> if _Py_TYPEOF() is not available, since the limited C API
476+
* version 3.11 and newer doesn't include it.
474477
*/
475478
#ifdef _Py_TYPEOF
476479
#define Py_CLEAR(op) \
@@ -483,6 +486,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
483486
} \
484487
} while (0)
485488
#else
489+
#include <string.h> // memcpy()
486490
#define Py_CLEAR(op) \
487491
do { \
488492
PyObject **_tmp_op_ptr = _Py_CAST(PyObject**, &(op)); \

Lib/test/test_cext/extension.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ _testcext_exec(
6565
#endif
6666
)
6767
{
68+
PyObject *obj;
69+
6870
#ifdef __STDC_VERSION__
6971
if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) {
7072
return -1;
@@ -75,6 +77,10 @@ _testcext_exec(
7577
Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
7678
assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);
7779

80+
// Test Py_CLEAR()
81+
obj = NULL;
82+
Py_CLEAR(obj);
83+
7884
return 0;
7985
}
8086

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix the :c:macro:`Py_CLEAR` implementation in the limited C API version 3.11
2+
and newer: include ``<string.h>`` to get the ``memcpy()`` function. Patch by
3+
Victor Stinner.

0 commit comments

Comments
 (0)