Skip to content

Commit 7cb779e

Browse files
committed
gh-105059: In C++, Py_INCREF() uses a function call
In C++, Py_INCREF() and Py_DECREF() are now implemented as function calls. Moreover, in C++, PyObject.ob_refcnt type is just Py_ssize_t: don't use an anonymous union to avoid compiler warnings (anonymous unions were added to C11).
1 parent b542972 commit 7cb779e

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

Include/object.h

+33-9
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,21 @@ check by comparing the reference count field to the immortality reference count.
134134
{ _Py_IMMORTAL_REFCNT }, \
135135
(type) \
136136
},
137-
#else
137+
#elif !defined(__cplusplus)
138138
#define PyObject_HEAD_INIT(type) \
139139
{ \
140140
_PyObject_EXTRA_INIT \
141141
{ 1 }, \
142142
(type) \
143143
},
144+
#else
145+
// gh-105059: In C++, ob_refcnt type is Py_ssize_t
146+
#define PyObject_HEAD_INIT(type) \
147+
{ \
148+
_PyObject_EXTRA_INIT \
149+
1, \
150+
(type) \
151+
},
144152
#endif /* Py_BUILD_CORE */
145153

146154
#define PyVarObject_HEAD_INIT(type, size) \
@@ -165,12 +173,18 @@ check by comparing the reference count field to the immortality reference count.
165173
*/
166174
struct _object {
167175
_PyObject_HEAD_EXTRA
176+
#ifndef __cplusplus
168177
union {
169178
Py_ssize_t ob_refcnt;
170179
#if SIZEOF_VOID_P > 4
171180
PY_UINT32_T ob_refcnt_split[2];
172181
#endif
173182
};
183+
#else
184+
// gh-105059: In C++, avoid anonymous union for ob_refcnt.
185+
// C++ uses opaque function calls for Py_INCREF() and Py_DECREF().
186+
Py_ssize_t ob_refcnt;
187+
#endif
174188
PyTypeObject *ob_type;
175189
};
176190

@@ -611,15 +625,18 @@ PyAPI_FUNC(void) _Py_DecRef(PyObject *);
611625
static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
612626
{
613627
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
614-
// Stable ABI implements Py_INCREF() as a function call on limited C API
615-
// version 3.12 and newer, and on Python built in debug mode. _Py_IncRef()
616-
// was added to Python 3.10.0a7, use Py_IncRef() on older Python versions.
617-
// Py_IncRef() accepts NULL whereas _Py_IncRef() doesn't.
628+
// In limited C API version 3.12 and newer and on Python built in debug
629+
// mode, Py_INCREF() is implemented as a function call. _Py_IncRef() was
630+
// added to Python 3.10.0a7, use Py_IncRef() on older Python versions.
631+
// Py_IncRef() accepts NULL, whereas _Py_IncRef() doesn't.
618632
# if Py_LIMITED_API+0 >= 0x030a00A7
619633
_Py_IncRef(op);
620634
# else
621635
Py_IncRef(op);
622636
# endif
637+
#elif defined(__cplusplus)
638+
// gh-105059: In C++, Py_INCREF() is implemented as a function call
639+
_Py_IncRef(op);
623640
#else
624641
// Non-limited C API and limited C API for Python 3.9 and older access
625642
// directly PyObject.ob_refcnt.
@@ -649,10 +666,10 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
649666
#endif
650667

651668
#if defined(Py_LIMITED_API) && (Py_LIMITED_API+0 >= 0x030c0000 || defined(Py_REF_DEBUG))
652-
// Stable ABI implements Py_DECREF() as a function call on limited C API
653-
// version 3.12 and newer, and on Python built in debug mode. _Py_DecRef() was
654-
// added to Python 3.10.0a7, use Py_DecRef() on older Python versions.
655-
// Py_DecRef() accepts NULL whereas _Py_IncRef() doesn't.
669+
// In limited C API version 3.12 and newer and on Python built in debug mode,
670+
// Py_DECREF() is implemented as a function call. _Py_DecRef() was added to
671+
// Python 3.10.0a7, use Py_DecRef() on older Python versions. Py_DecRef()
672+
// accepts NULL, whereas _Py_DecRef() doesn't.
656673
static inline void Py_DECREF(PyObject *op) {
657674
# if Py_LIMITED_API+0 >= 0x030a00A7
658675
_Py_DecRef(op);
@@ -662,6 +679,13 @@ static inline void Py_DECREF(PyObject *op) {
662679
}
663680
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
664681

682+
#elif defined(__cplusplus)
683+
// gh-105059: In C++, Py_DECREF() is implemented as a function call
684+
static inline void Py_DECREF(PyObject *op) {
685+
_Py_DecRef(op);
686+
}
687+
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
688+
665689
#elif defined(Py_REF_DEBUG)
666690
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
667691
{

0 commit comments

Comments
 (0)