Skip to content

Commit 61381d7

Browse files
authored
gh-89653: PEP 670: Functions don't cast pointers (#91697)
In the limited C API version 3.11 and newer, the following functions no longer cast their object pointer argument with _PyObject_CAST() or _PyObject_CAST_CONST(): * Py_REFCNT(), Py_TYPE(), Py_SIZE() * Py_SET_REFCNT(), Py_SET_TYPE(), Py_SET_SIZE() * Py_IS_TYPE() * Py_INCREF(), Py_DECREF() * Py_XINCREF(), Py_XDECREF() * Py_NewRef(), Py_XNewRef() * PyObject_TypeCheck() * PyType_Check() * PyType_CheckExact() Split Py_DECREF() implementation in 3 versions to make the code more readable. Update the xxlimited.c extension, which uses the limited C API version 3.11, to pass PyObject* to these functions.
1 parent 1cd8c29 commit 61381d7

File tree

3 files changed

+119
-56
lines changed

3 files changed

+119
-56
lines changed

Include/cpython/unicodeobject.h

+47-17
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,18 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
256256
static inline unsigned int PyUnicode_CHECK_INTERNED(PyObject *op) {
257257
return _PyASCIIObject_CAST(op)->state.interned;
258258
}
259-
#define PyUnicode_CHECK_INTERNED(op) PyUnicode_CHECK_INTERNED(_PyObject_CAST(op))
259+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
260+
# define PyUnicode_CHECK_INTERNED(op) PyUnicode_CHECK_INTERNED(_PyObject_CAST(op))
261+
#endif
260262

261263
/* Fast check to determine whether an object is ready. Equivalent to:
262264
PyUnicode_IS_COMPACT(op) || _PyUnicodeObject_CAST(op)->data.any */
263265
static inline unsigned int PyUnicode_IS_READY(PyObject *op) {
264266
return _PyASCIIObject_CAST(op)->state.ready;
265267
}
266-
#define PyUnicode_IS_READY(op) PyUnicode_IS_READY(_PyObject_CAST(op))
268+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
269+
# define PyUnicode_IS_READY(op) PyUnicode_IS_READY(_PyObject_CAST(op))
270+
#endif
267271

268272
/* Return true if the string contains only ASCII characters, or 0 if not. The
269273
string may be compact (PyUnicode_IS_COMPACT_ASCII) or not, but must be
@@ -272,21 +276,27 @@ static inline unsigned int PyUnicode_IS_ASCII(PyObject *op) {
272276
assert(PyUnicode_IS_READY(op));
273277
return _PyASCIIObject_CAST(op)->state.ascii;
274278
}
275-
#define PyUnicode_IS_ASCII(op) PyUnicode_IS_ASCII(_PyObject_CAST(op))
279+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
280+
# define PyUnicode_IS_ASCII(op) PyUnicode_IS_ASCII(_PyObject_CAST(op))
281+
#endif
276282

277283
/* Return true if the string is compact or 0 if not.
278284
No type checks or Ready calls are performed. */
279285
static inline unsigned int PyUnicode_IS_COMPACT(PyObject *op) {
280286
return _PyASCIIObject_CAST(op)->state.compact;
281287
}
282-
#define PyUnicode_IS_COMPACT(op) PyUnicode_IS_COMPACT(_PyObject_CAST(op))
288+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
289+
# define PyUnicode_IS_COMPACT(op) PyUnicode_IS_COMPACT(_PyObject_CAST(op))
290+
#endif
283291

284292
/* Return true if the string is a compact ASCII string (use PyASCIIObject
285293
structure), or 0 if not. No type checks or Ready calls are performed. */
286294
static inline int PyUnicode_IS_COMPACT_ASCII(PyObject *op) {
287295
return (_PyASCIIObject_CAST(op)->state.ascii && PyUnicode_IS_COMPACT(op));
288296
}
289-
#define PyUnicode_IS_COMPACT_ASCII(op) PyUnicode_IS_COMPACT_ASCII(_PyObject_CAST(op))
297+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
298+
# define PyUnicode_IS_COMPACT_ASCII(op) PyUnicode_IS_COMPACT_ASCII(_PyObject_CAST(op))
299+
#endif
290300

291301
enum PyUnicode_Kind {
292302
/* String contains only wstr byte characters. This is only possible
@@ -326,7 +336,9 @@ static inline void* PyUnicode_DATA(PyObject *op) {
326336
}
327337
return _PyUnicode_NONCOMPACT_DATA(op);
328338
}
329-
#define PyUnicode_DATA(op) PyUnicode_DATA(_PyObject_CAST(op))
339+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
340+
# define PyUnicode_DATA(op) PyUnicode_DATA(_PyObject_CAST(op))
341+
#endif
330342

331343
/* Return pointers to the canonical representation cast to unsigned char,
332344
Py_UCS2, or Py_UCS4 for direct character access.
@@ -344,7 +356,9 @@ static inline Py_ssize_t PyUnicode_GET_LENGTH(PyObject *op) {
344356
assert(PyUnicode_IS_READY(op));
345357
return _PyASCIIObject_CAST(op)->length;
346358
}
347-
#define PyUnicode_GET_LENGTH(op) PyUnicode_GET_LENGTH(_PyObject_CAST(op))
359+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
360+
# define PyUnicode_GET_LENGTH(op) PyUnicode_GET_LENGTH(_PyObject_CAST(op))
361+
#endif
348362

349363
/* Write into the canonical representation, this function does not do any sanity
350364
checks and is intended for usage in loops. The caller should cache the
@@ -405,8 +419,10 @@ static inline Py_UCS4 PyUnicode_READ_CHAR(PyObject *unicode, Py_ssize_t index)
405419
assert(kind == PyUnicode_4BYTE_KIND);
406420
return PyUnicode_4BYTE_DATA(unicode)[index];
407421
}
408-
#define PyUnicode_READ_CHAR(unicode, index) \
409-
PyUnicode_READ_CHAR(_PyObject_CAST(unicode), (index))
422+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
423+
# define PyUnicode_READ_CHAR(unicode, index) \
424+
PyUnicode_READ_CHAR(_PyObject_CAST(unicode), (index))
425+
#endif
410426

411427
/* Return a maximum character value which is suitable for creating another
412428
string based on op. This is always an approximation but more efficient
@@ -428,8 +444,10 @@ static inline Py_UCS4 PyUnicode_MAX_CHAR_VALUE(PyObject *op)
428444
assert(kind == PyUnicode_4BYTE_KIND);
429445
return 0x10ffffU;
430446
}
431-
#define PyUnicode_MAX_CHAR_VALUE(op) \
432-
PyUnicode_MAX_CHAR_VALUE(_PyObject_CAST(op))
447+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
448+
# define PyUnicode_MAX_CHAR_VALUE(op) \
449+
PyUnicode_MAX_CHAR_VALUE(_PyObject_CAST(op))
450+
#endif
433451

434452
/* === Public API ========================================================= */
435453

@@ -465,7 +483,9 @@ static inline int PyUnicode_READY(PyObject *op)
465483
}
466484
return _PyUnicode_Ready(op);
467485
}
468-
#define PyUnicode_READY(op) PyUnicode_READY(_PyObject_CAST(op))
486+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
487+
# define PyUnicode_READY(op) PyUnicode_READY(_PyObject_CAST(op))
488+
#endif
469489

470490
/* Get a copy of a Unicode string. */
471491
PyAPI_FUNC(PyObject*) _PyUnicode_Copy(
@@ -606,7 +626,9 @@ static inline Py_ssize_t PyUnicode_WSTR_LENGTH(PyObject *op)
606626
return _PyCompactUnicodeObject_CAST(op)->wstr_length;
607627
}
608628
}
609-
#define PyUnicode_WSTR_LENGTH(op) PyUnicode_WSTR_LENGTH(_PyObject_CAST(op))
629+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
630+
# define PyUnicode_WSTR_LENGTH(op) PyUnicode_WSTR_LENGTH(_PyObject_CAST(op))
631+
#endif
610632

611633
/* Returns the deprecated Py_UNICODE representation's size in code units
612634
(this includes surrogate pairs as 2 units).
@@ -625,7 +647,9 @@ static inline Py_ssize_t PyUnicode_GET_SIZE(PyObject *op)
625647
return PyUnicode_WSTR_LENGTH(op);
626648
_Py_COMP_DIAG_POP
627649
}
628-
#define PyUnicode_GET_SIZE(op) PyUnicode_GET_SIZE(_PyObject_CAST(op))
650+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
651+
# define PyUnicode_GET_SIZE(op) PyUnicode_GET_SIZE(_PyObject_CAST(op))
652+
#endif
629653

630654
Py_DEPRECATED(3.3)
631655
static inline Py_ssize_t PyUnicode_GET_DATA_SIZE(PyObject *op)
@@ -635,7 +659,9 @@ static inline Py_ssize_t PyUnicode_GET_DATA_SIZE(PyObject *op)
635659
return PyUnicode_GET_SIZE(op) * Py_UNICODE_SIZE;
636660
_Py_COMP_DIAG_POP
637661
}
638-
#define PyUnicode_GET_DATA_SIZE(op) PyUnicode_GET_DATA_SIZE(_PyObject_CAST(op))
662+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
663+
# define PyUnicode_GET_DATA_SIZE(op) PyUnicode_GET_DATA_SIZE(_PyObject_CAST(op))
664+
#endif
639665

640666
/* Alias for PyUnicode_AsUnicode(). This will create a wchar_t/Py_UNICODE
641667
representation on demand. Using this macro is very inefficient now,
@@ -655,7 +681,9 @@ static inline Py_UNICODE* PyUnicode_AS_UNICODE(PyObject *op)
655681
return PyUnicode_AsUnicode(op);
656682
_Py_COMP_DIAG_POP
657683
}
658-
#define PyUnicode_AS_UNICODE(op) PyUnicode_AS_UNICODE(_PyObject_CAST(op))
684+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
685+
# define PyUnicode_AS_UNICODE(op) PyUnicode_AS_UNICODE(_PyObject_CAST(op))
686+
#endif
659687

660688
Py_DEPRECATED(3.3)
661689
static inline const char* PyUnicode_AS_DATA(PyObject *op)
@@ -665,7 +693,9 @@ static inline const char* PyUnicode_AS_DATA(PyObject *op)
665693
return (const char *)PyUnicode_AS_UNICODE(op);
666694
_Py_COMP_DIAG_POP
667695
}
668-
#define PyUnicode_AS_DATA(op) PyUnicode_AS_DATA(_PyObject_CAST(op))
696+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
697+
# define PyUnicode_AS_DATA(op) PyUnicode_AS_DATA(_PyObject_CAST(op))
698+
#endif
669699

670700

671701
/* --- _PyUnicodeWriter API ----------------------------------------------- */

Include/object.h

+66-35
Original file line numberDiff line numberDiff line change
@@ -123,44 +123,58 @@ PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
123123
static inline Py_ssize_t Py_REFCNT(PyObject *ob) {
124124
return ob->ob_refcnt;
125125
}
126-
#define Py_REFCNT(ob) Py_REFCNT(_PyObject_CAST(ob))
126+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
127+
# define Py_REFCNT(ob) Py_REFCNT(_PyObject_CAST(ob))
128+
#endif
127129

128130

129131
// bpo-39573: The Py_SET_TYPE() function must be used to set an object type.
130132
static inline PyTypeObject* Py_TYPE(PyObject *ob) {
131133
return ob->ob_type;
132134
}
133-
#define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob))
135+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
136+
# define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob))
137+
#endif
134138

135139
// bpo-39573: The Py_SET_SIZE() function must be used to set an object size.
136140
static inline Py_ssize_t Py_SIZE(PyVarObject *ob) {
137141
return ob->ob_size;
138142
}
139-
#define Py_SIZE(ob) Py_SIZE(_PyVarObject_CAST(ob))
143+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
144+
# define Py_SIZE(ob) Py_SIZE(_PyVarObject_CAST(ob))
145+
#endif
140146

141147

142148
static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
143149
return Py_TYPE(ob) == type;
144150
}
145-
#define Py_IS_TYPE(ob, type) Py_IS_TYPE(_PyObject_CAST(ob), type)
151+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
152+
# define Py_IS_TYPE(ob, type) Py_IS_TYPE(_PyObject_CAST(ob), type)
153+
#endif
146154

147155

148156
static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
149157
ob->ob_refcnt = refcnt;
150158
}
151-
#define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
159+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
160+
# define Py_SET_REFCNT(ob, refcnt) Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
161+
#endif
152162

153163

154164
static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
155165
ob->ob_type = type;
156166
}
157-
#define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
167+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
168+
# define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
169+
#endif
158170

159171

160172
static inline void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
161173
ob->ob_size = size;
162174
}
163-
#define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), size)
175+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
176+
# define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), size)
177+
#endif
164178

165179

166180
/*
@@ -247,7 +261,9 @@ PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
247261
static inline int PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) {
248262
return Py_IS_TYPE(ob, type) || PyType_IsSubtype(Py_TYPE(ob), type);
249263
}
250-
#define PyObject_TypeCheck(ob, type) PyObject_TypeCheck(_PyObject_CAST(ob), type)
264+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
265+
# define PyObject_TypeCheck(ob, type) PyObject_TypeCheck(_PyObject_CAST(ob), type)
266+
#endif
251267

252268
PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */
253269
PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */
@@ -485,39 +501,43 @@ static inline void Py_INCREF(PyObject *op)
485501
op->ob_refcnt++;
486502
#endif
487503
}
488-
#define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
489-
490-
static inline void Py_DECREF(
491-
#if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000)
492-
const char *filename, int lineno,
504+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
505+
# define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
493506
#endif
494-
PyObject *op)
495-
{
507+
508+
496509
#if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000
497-
// Stable ABI for Python 3.10 built in debug mode.
510+
// Stable ABI for limited C API version 3.10 of Python debug build
511+
static inline void Py_DECREF(PyObject *op) {
498512
_Py_DecRef(op);
499-
#else
500-
// Non-limited C API and limited C API for Python 3.9 and older access
501-
// directly PyObject.ob_refcnt.
502-
#ifdef Py_REF_DEBUG
513+
}
514+
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
515+
516+
#elif defined(Py_REF_DEBUG)
517+
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
518+
{
503519
_Py_RefTotal--;
504-
#endif
505520
if (--op->ob_refcnt != 0) {
506-
#ifdef Py_REF_DEBUG
507521
if (op->ob_refcnt < 0) {
508522
_Py_NegativeRefcount(filename, lineno, op);
509523
}
510-
#endif
511524
}
512525
else {
513526
_Py_Dealloc(op);
514527
}
515-
#endif
516528
}
517-
#if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000)
518-
# define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
529+
#define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
530+
519531
#else
520-
# define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
532+
static inline void Py_DECREF(PyObject *op)
533+
{
534+
// Non-limited C API and limited C API for Python 3.9 and older access
535+
// directly PyObject.ob_refcnt.
536+
if (--op->ob_refcnt == 0) {
537+
_Py_Dealloc(op);
538+
}
539+
}
540+
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
521541
#endif
522542

523543

@@ -571,17 +591,19 @@ static inline void Py_XINCREF(PyObject *op)
571591
Py_INCREF(op);
572592
}
573593
}
574-
575-
#define Py_XINCREF(op) Py_XINCREF(_PyObject_CAST(op))
594+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
595+
# define Py_XINCREF(op) Py_XINCREF(_PyObject_CAST(op))
596+
#endif
576597

577598
static inline void Py_XDECREF(PyObject *op)
578599
{
579600
if (op != NULL) {
580601
Py_DECREF(op);
581602
}
582603
}
583-
584-
#define Py_XDECREF(op) Py_XDECREF(_PyObject_CAST(op))
604+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
605+
# define Py_XDECREF(op) Py_XDECREF(_PyObject_CAST(op))
606+
#endif
585607

586608
// Create a new strong reference to an object:
587609
// increment the reference count of the object and return the object.
@@ -605,8 +627,13 @@ static inline PyObject* _Py_XNewRef(PyObject *obj)
605627
// Py_NewRef() and Py_XNewRef() are exported as functions for the stable ABI.
606628
// Names overridden with macros by static inline functions for best
607629
// performances.
608-
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
609-
#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
630+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
631+
# define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
632+
# define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
633+
#else
634+
# define Py_NewRef(obj) _Py_NewRef(obj)
635+
# define Py_XNewRef(obj) _Py_XNewRef(obj)
636+
#endif
610637

611638

612639
/*
@@ -749,14 +776,18 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature)
749776
static inline int PyType_Check(PyObject *op) {
750777
return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS);
751778
}
752-
#define PyType_Check(op) PyType_Check(_PyObject_CAST(op))
779+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
780+
# define PyType_Check(op) PyType_Check(_PyObject_CAST(op))
781+
#endif
753782

754783
#define _PyType_CAST(op) (assert(PyType_Check(op)), (PyTypeObject*)(op))
755784

756785
static inline int PyType_CheckExact(PyObject *op) {
757786
return Py_IS_TYPE(op, &PyType_Type);
758787
}
759-
#define PyType_CheckExact(op) PyType_CheckExact(_PyObject_CAST(op))
788+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
789+
# define PyType_CheckExact(op) PyType_CheckExact(_PyObject_CAST(op))
790+
#endif
760791

761792
#ifdef __cplusplus
762793
}

Modules/xxlimited.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,13 @@ newXxoObject(PyObject *module)
110110
/* Xxo finalization */
111111

112112
static int
113-
Xxo_traverse(XxoObject *self, visitproc visit, void *arg)
113+
Xxo_traverse(PyObject *self_obj, visitproc visit, void *arg)
114114
{
115115
// Visit the type
116-
Py_VISIT(Py_TYPE(self));
116+
Py_VISIT(Py_TYPE(self_obj));
117117

118118
// Visit the attribute dict
119+
XxoObject *self = (XxoObject *)self_obj;
119120
Py_VISIT(self->x_attr);
120121
return 0;
121122
}
@@ -128,13 +129,14 @@ Xxo_clear(XxoObject *self)
128129
}
129130

130131
static void
131-
Xxo_finalize(XxoObject *self)
132+
Xxo_finalize(PyObject *self_obj)
132133
{
134+
XxoObject *self = (XxoObject *)self_obj;
133135
Py_CLEAR(self->x_attr);
134136
}
135137

136138
static void
137-
Xxo_dealloc(XxoObject *self)
139+
Xxo_dealloc(PyObject *self)
138140
{
139141
Xxo_finalize(self);
140142
PyTypeObject *tp = Py_TYPE(self);

0 commit comments

Comments
 (0)