Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ System includes
* ``<stdlib.h>``
* ``<string.h>``

The ``<string.h>`` header is also included when using :ref:`Limited API
<limited-c-api>` 3.11 or newer if Python is unable to get a ``typeof()``
implementation.

.. note::

Since Python may define some pre-processor definitions which affect the standard
Expand Down
7 changes: 5 additions & 2 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,11 @@ extern "C" {
//
// Example: _Py_TYPEOF(x) x_copy = (x);
//
// The macro is only defined if GCC or clang compiler is used.
#if defined(__GNUC__) || defined(__clang__)
// On C23, use typeof(). Otherwise, the macro is only defined
// if GCC or clang compiler is used.
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
# define _Py_TYPEOF(expr) typeof(expr)
#elif defined(__GNUC__) || defined(__clang__)
# define _Py_TYPEOF(expr) __typeof__(expr)
#endif

Expand Down
4 changes: 4 additions & 0 deletions Include/refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
* and so avoid type punning. Otherwise, use memcpy() which causes type erasure
* and so prevents the compiler to reuse an old cached 'op' value after
* Py_CLEAR().
*
* Include <string.h> if _Py_TYPEOF() is not available, since the limited C API
* version 3.11 and newer doesn't include it.
*/
#ifdef _Py_TYPEOF
#define Py_CLEAR(op) \
Expand All @@ -483,6 +486,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
} \
} while (0)
#else
#include <string.h> // memcpy()
#define Py_CLEAR(op) \
do { \
PyObject **_tmp_op_ptr = _Py_CAST(PyObject**, &(op)); \
Expand Down
6 changes: 5 additions & 1 deletion Lib/test/test_cext/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ _testcext_exec(
#endif
)
{
PyObject *result;
PyObject *result, *obj;

#ifdef __STDC_VERSION__
if (PyModule_AddIntMacro(module, __STDC_VERSION__) < 0) {
Expand All @@ -98,6 +98,10 @@ _testcext_exec(
Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);

// Test Py_CLEAR()
obj = NULL;
Py_CLEAR(obj);

return 0;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix the :c:macro:`Py_CLEAR` implementation in the limited C API version 3.11
and newer: include ``<string.h>`` to get the ``memcpy()`` function. Patch by
Victor Stinner.
Loading