@@ -20,12 +20,8 @@ them usable by Python extensions which cannot use macros or static
20
20
inline functions, like extensions written in a programming languages
21
21
other than C or C++.
22
22
23
- Remove the return value of macros having a return value, whereas they
24
- should not, to aid detecting bugs in C extensions when the C API is
25
- misused.
26
-
27
- Some function arguments are still cast to ``PyObject* `` to prevent
28
- emitting new compiler warnings.
23
+ Function arguments of pointer types are still cast and return types are
24
+ not changed to prevent emitting new compiler warnings.
29
25
30
26
Macros which can be used as l-value in an assignment are not converted
31
27
to functions to avoid introducing incompatible changes.
@@ -177,6 +173,7 @@ The following macros should not be converted:
177
173
* Macros which can be used as l-value in an assignment. This change is
178
174
an incompatible change and is out of the scope of this PEP.
179
175
Example: ``PyBytes_AS_STRING() ``.
176
+ * Macros having different return types depending on the code path.
180
177
181
178
182
179
Convert static inline functions to regular functions
@@ -196,74 +193,81 @@ Using static inline functions in the internal C API is fine: the
196
193
internal C API exposes implementation details by design and should not be
197
194
used outside Python.
198
195
199
- Cast to PyObject*
200
- -----------------
196
+ Cast pointer arguments
197
+ ----------------------
198
+
199
+ Existing cast
200
+ '''''''''''''
201
+
202
+ Currently, most macros accepting pointers cast pointer arguments to
203
+ their expected types. For example, in Python 3.6, the ``Py_TYPE() ``
204
+ macro casts its argument to ``PyObject* ``::
201
205
202
- When a macro is converted to a function and the macro casts its
203
- arguments to ``PyObject* ``, the new function comes with a new macro
204
- which cast arguments to ``PyObject* `` to prevent emitting new compiler
205
- warnings. This implies that a converted function will accept pointers to
206
- structures inheriting from ``PyObject `` (ex: ``PyTupleObject ``).
206
+ #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
207
207
208
- For example, the ``Py_TYPE(obj ) `` macro casts its ``obj `` argument to
209
- `` PyObject * ``::
208
+ The ``Py_TYPE() `` macro accepts the ``PyObject* `` type, but also any
209
+ pointer types, such as `` PyLongObject * `` and `` PyDictObject* ``.
210
210
211
- #define _PyObject_CAST_CONST(op) ((const PyObject*)(op))
211
+ Add a new macro to keep the cast
212
+ ''''''''''''''''''''''''''''''''
212
213
213
- static inline PyTypeObject* _Py_TYPE(const PyObject *ob) {
214
+ When a macro is converted to a function and the macro casts at least one
215
+ of its arguments, a new macro is added to keep the cast. The new macro
216
+ and the function have the same name. Example with the ``Py_TYPE() ``
217
+ macro converted to a static inline function::
218
+
219
+ static inline PyTypeObject* Py_TYPE(PyObject *ob) {
214
220
return ob->ob_type;
215
221
}
216
- #define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST (ob))
222
+ #define Py_TYPE(ob) Py_TYPE((PyObject*) (ob))
217
223
218
- The undocumented private ``_Py_TYPE() `` function must not be called
219
- directly. Only the documented public ``Py_TYPE() `` macro must be used.
224
+ The cast is kept for all pointer types, not only ``PyObject* ``.
220
225
221
- Later, the cast can be removed on a case by case basis, but that is out
222
- of scope for this PEP.
226
+ Removing a cast to ``void* `` would emit a new warning if the function is
227
+ called with a variable of ``const void* `` type. For example, the
228
+ ``PyUnicode_WRITE() `` macro casts its *data * argument to ``void* ``, and
229
+ so accepts ``const void* `` type, even if it writes into *data *.
223
230
224
- Remove the return value
225
- -----------------------
231
+ Avoid the cast in the limited C API version 3.11
232
+ ''''''''''''''''''''''''''''''''''''''''''''''''
226
233
227
- When a macro is implemented as an expression, it has an implicit return
228
- value. This return value can be misused in third party C extensions.
229
- See `bpo-30459 <https://bugs.python.org/issue30459 >`__ regarding the
230
- misuse of the ``PyList_SET_ITEM() `` and ``PyCell_SET() `` macros.
234
+ The cast is removed from the limited C API version 3.11 and newer: the
235
+ caller must pass the expected type, or perform the cast. An example with
236
+ the ``Py_TYPE() `` function::
231
237
232
- Such issue is hard to catch while reviewing macro code. Removing the
233
- return value aids detecting bugs in C extensions when the C API is
234
- misused.
238
+ static inline PyTypeObject* Py_TYPE(PyObject *ob) {
239
+ return ob->ob_type;
240
+ }
241
+ #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
242
+ # define Py_TYPE(ob) Py_TYPE((PyObject*)(ob))
243
+ #endif
235
244
236
- The issue has already been fixed in public C API macros by the
237
- `bpo-30459 <https://bugs.python.org/issue30459 >`__ in Python 3.10: add a
238
- ``(void) `` cast to the affected macros. Example of the
239
- ``PyTuple_SET_ITEM() `` macro::
240
245
241
- #define PyTuple_SET_ITEM(op, i, v) ((void)(_PyTuple_CAST(op)->ob_item[i] = v))
246
+ Return type is not changed
247
+ --------------------------
242
248
243
- Example of macros currently using a `` (void) `` cast to have no return
244
- value:
249
+ When a macro is converted to a function, its return type must not change
250
+ to prevent emitting new compiler warnings.
245
251
246
- * ``PyCell_SET() ``
247
- * ``PyList_SET_ITEM() ``
248
- * ``PyTuple_SET_ITEM() ``
249
- * ``Py_BUILD_ASSERT() ``
250
- * ``_PyGCHead_SET_FINALIZED() ``
251
- * ``_PyGCHead_SET_NEXT() ``
252
- * ``_PyObject_ASSERT_FROM() ``
253
- * ``_Py_atomic_signal_fence() ``
254
- * ``_Py_atomic_store_64bit() ``
255
- * ``asdl_seq_SET() ``
256
- * ``asdl_seq_SET_UNTYPED() ``
252
+ For example, Python 3.7 changed ``PyUnicode_AsUTF8() `` return type from
253
+ ``char* `` to ``const char* `` (`commit
254
+ <https://github.com/python/cpython/commit/2a404b63d48d73bbaa007d89efb7a01048475acd> `__).
255
+ The change emitted new compiler warnings when building C extensions
256
+ expecting ``char* ``. This PEP doesn't change the return type to prevent
257
+ this issue.
257
258
258
259
259
260
Backwards Compatibility
260
261
=======================
261
262
262
- Removing the return value of macros is an incompatible API change made
263
- on purpose: see the `Remove the return value `_ section.
263
+ The PEP is designed to avoid C API incompatible changes.
264
264
265
- Some function arguments are still cast to ``PyObject* `` to prevent
266
- emitting new compiler warnings.
265
+ Only C extensions explicitly targeting the limited C API version 3.11
266
+ must now pass the expected types to functions: pointer arguments are no
267
+ longer cast to the expected types.
268
+
269
+ Function arguments of pointer types are still cast and return types are
270
+ not changed to prevent emitting new compiler warnings.
267
271
268
272
Macros which can be used as l-value in an assignment are not modified by
269
273
this PEP to avoid incompatible changes.
@@ -275,10 +279,6 @@ Rejected Ideas
275
279
Keep macros, but fix some macro issues
276
280
--------------------------------------
277
281
278
- Converting macros to functions is not needed to `remove the return
279
- value `_: adding a ``(void) `` cast is enough. For example, the
280
- ``PyList_SET_ITEM() `` macro was already fixed like that.
281
-
282
282
Macros are always "inlined" with any C compiler.
283
283
284
284
The duplication of side effects can be worked around in the caller of
@@ -600,6 +600,14 @@ References
600
600
(March 2021).
601
601
602
602
603
+ Version History
604
+ ===============
605
+
606
+ * Version 2: No longer remove return values; remove argument casting
607
+ from the limited C API.
608
+ * Version 1: First public version
609
+
610
+
603
611
Copyright
604
612
=========
605
613
0 commit comments