https://github.com/python/cpython/commit/bba99f2b3272cbe47af9bee05a294961c0528829
commit: bba99f2b3272cbe47af9bee05a294961c0528829
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-10T21:10:46Z
summary:
gh-121647: Fix _Py_TYPEOF() on C++ (#157267)
Using MSVC (on Windows), _Py_TYPEOF() prefers decltype()
over __typeof__() on C++.
Fix also _Py_TYPEOF() usage in Py_CLEAR() and Py_SETREF() macros.
Replace "_Py_TYPEOF(dst)*" with "_Py_TYPEOF(&(dst))". In C++,
"_Py_TYPEOF(dst)*" can fail with a compiler error.
files:
M Include/cpython/object.h
M Include/pyport.h
M Include/refcount.h
diff --git a/Include/cpython/object.h b/Include/cpython/object.h
index 4c5a677e5543ece..0ef52d4d2bc7b4b 100644
--- a/Include/cpython/object.h
+++ b/Include/cpython/object.h
@@ -352,7 +352,7 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
#ifdef _Py_TYPEOF
#define Py_SETREF(dst, src) \
do { \
- _Py_TYPEOF(dst)* _tmp_dst_ptr = &(dst); \
+ _Py_TYPEOF(&(dst)) _tmp_dst_ptr = &(dst); \
_Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
Py_DECREF(_tmp_old_dst); \
@@ -374,7 +374,7 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
#ifdef _Py_TYPEOF
#define Py_XSETREF(dst, src) \
do { \
- _Py_TYPEOF(dst)* _tmp_dst_ptr = &(dst); \
+ _Py_TYPEOF(&(dst)) _tmp_dst_ptr = &(dst); \
_Py_TYPEOF(dst) _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
Py_XDECREF(_tmp_old_dst); \
diff --git a/Include/pyport.h b/Include/pyport.h
index 03f9b869bc82b55..744bae6c57e299e 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -538,15 +538,18 @@ extern "C" {
//
// Example: _Py_TYPEOF(x) x_copy = (x);
//
-// On C23, use typeof(). Otherwise __typeof__() if on GCC, clang or
-// MSVC 17.9 and newer. Else if on C++11 or newer, decltype() is used.
+// On C23, use typeof(). On C++11, use decltype(). Otherwise, use __typeof__()
+// if on GCC, clang or MSVC 17.9 and newer.
+//
+// On MSVC, check also _MSVC_LANG since __cplusplus is 199711L unless
+// the /Zc:__cplusplus flag is used.
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
# define _Py_TYPEOF(expr) typeof(expr)
+#elif defined(__cplusplus) && (__cplusplus >= 201103L || _MSVC_LANG >=
201103L)
+# define _Py_TYPEOF(expr) decltype(expr)
#elif defined(__GNUC__) || defined(__clang__) || \
(defined(_MSC_VER) && _MSC_VER >= 1939)
# define _Py_TYPEOF(expr) __typeof__(expr)
-#elif defined(__cplusplus) && __cplusplus >= 201103L
-# define _Py_TYPEOF(expr) decltype(expr)
#endif
diff --git a/Include/refcount.h b/Include/refcount.h
index b21697ae1780fa8..d96c75421aef337 100644
--- a/Include/refcount.h
+++ b/Include/refcount.h
@@ -482,7 +482,7 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
#ifdef _Py_TYPEOF
#define Py_CLEAR(op) \
do { \
- _Py_TYPEOF(op)* _tmp_op_ptr = &(op); \
+ _Py_TYPEOF(&(op)) _tmp_op_ptr = &(op); \
_Py_TYPEOF(op) _tmp_old_op = (*_tmp_op_ptr); \
if (_tmp_old_op != _Py_NULL) { \
*_tmp_op_ptr = _Py_NULL; \
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]