mirror of
https://github.com/python/cpython.git
synced 2025-07-07 11:25:30 +00:00
gh-132097: use a macro for semantically casting function pointers (#132406)
This commit is contained in:
parent
f3d877a27a
commit
379352620c
9 changed files with 47 additions and 31 deletions
|
@ -37,17 +37,18 @@ _PyEM_TrampolineCall(PyCFunctionWithKeywords func,
|
|||
PyObject* kw);
|
||||
|
||||
#define _PyCFunction_TrampolineCall(meth, self, args) \
|
||||
_PyEM_TrampolineCall( \
|
||||
(*(PyCFunctionWithKeywords)(void(*)(void))(meth)), (self), (args), NULL)
|
||||
_PyEM_TrampolineCall(*_PyCFunctionWithKeywords_CAST(meth), (self), (args), NULL)
|
||||
|
||||
#define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \
|
||||
_PyEM_TrampolineCall((meth), (self), (args), (kw))
|
||||
|
||||
#define descr_set_trampoline_call(set, obj, value, closure) \
|
||||
((int)_PyEM_TrampolineCall((PyCFunctionWithKeywords)(set), (obj), (value), (PyObject*)(closure)))
|
||||
#define descr_set_trampoline_call(set, obj, value, closure) \
|
||||
((int)_PyEM_TrampolineCall(_PyCFunctionWithKeywords_CAST(set), (obj), \
|
||||
(value), (PyObject*)(closure)))
|
||||
|
||||
#define descr_get_trampoline_call(get, obj, closure) \
|
||||
_PyEM_TrampolineCall((PyCFunctionWithKeywords)(get), (obj), (PyObject*)(closure), NULL)
|
||||
#define descr_get_trampoline_call(get, obj, closure) \
|
||||
_PyEM_TrampolineCall(_PyCFunctionWithKeywords_CAST(get), (obj), \
|
||||
(PyObject*)(closure), NULL)
|
||||
|
||||
|
||||
#else // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *,
|
|||
typedef PyCFunctionFast _PyCFunctionFast;
|
||||
typedef PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords;
|
||||
|
||||
// Cast an function to the PyCFunction type to use it with PyMethodDef.
|
||||
// Cast a function to the PyCFunction type to use it with PyMethodDef.
|
||||
//
|
||||
// This macro can be used to prevent compiler warnings if the first parameter
|
||||
// uses a different pointer type than PyObject* (ex: METH_VARARGS and METH_O
|
||||
|
@ -49,8 +49,17 @@ typedef PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords;
|
|||
// used to prevent a compiler warning. If the function has a single parameter,
|
||||
// it triggers an undefined behavior when Python calls it with 2 parameters
|
||||
// (bpo-33012).
|
||||
#define _PyCFunction_CAST(func) \
|
||||
_Py_CAST(PyCFunction, _Py_CAST(void(*)(void), (func)))
|
||||
#define _PyCFunction_CAST(func) \
|
||||
_Py_FUNC_CAST(PyCFunction, func)
|
||||
// The macros below are given for semantic convenience, allowing users
|
||||
// to see whether a cast to suppress an undefined behavior is necessary.
|
||||
// Note: At runtime, the original function signature must be respected.
|
||||
#define _PyCFunctionFast_CAST(func) \
|
||||
_Py_FUNC_CAST(PyCFunctionFast, func)
|
||||
#define _PyCFunctionWithKeywords_CAST(func) \
|
||||
_Py_FUNC_CAST(PyCFunctionWithKeywords, func)
|
||||
#define _PyCFunctionFastWithKeywords_CAST(func) \
|
||||
_Py_FUNC_CAST(PyCFunctionFastWithKeywords, func)
|
||||
|
||||
PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *);
|
||||
|
|
|
@ -36,6 +36,16 @@
|
|||
// Macro to use the more powerful/dangerous C-style cast even in C++.
|
||||
#define _Py_CAST(type, expr) ((type)(expr))
|
||||
|
||||
// Cast a function to another function type T.
|
||||
//
|
||||
// The macro first casts the function to the "void func(void)" type
|
||||
// to prevent compiler warnings.
|
||||
//
|
||||
// Note that using this cast only prevents the compiler from emitting
|
||||
// warnings, but does not prevent an undefined behavior at runtime if
|
||||
// the original function signature is not respected.
|
||||
#define _Py_FUNC_CAST(T, func) _Py_CAST(T, _Py_CAST(void(*)(void), (func)))
|
||||
|
||||
// Static inline functions should use _Py_NULL rather than using directly NULL
|
||||
// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer,
|
||||
// _Py_NULL is defined as nullptr.
|
||||
|
|
|
@ -519,7 +519,7 @@ wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
|
|||
wrapperfunc wrapper = descr->d_base->wrapper;
|
||||
|
||||
if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
|
||||
wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
|
||||
wrapperfunc_kwds wk = _Py_FUNC_CAST(wrapperfunc_kwds, wrapper);
|
||||
return (*wk)(self, args, descr->d_wrapped, kwds);
|
||||
}
|
||||
|
||||
|
|
|
@ -567,7 +567,7 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
|
|||
PyObject *result;
|
||||
if (flags & METH_KEYWORDS) {
|
||||
result = _PyCFunctionWithKeywords_TrampolineCall(
|
||||
(*(PyCFunctionWithKeywords)(void(*)(void))meth),
|
||||
*_PyCFunctionWithKeywords_CAST(meth),
|
||||
self, args, kwargs);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -10807,7 +10807,8 @@ static pytype_slotdef slotdefs[] = {
|
|||
"__repr__($self, /)\n--\n\nReturn repr(self)."),
|
||||
TPSLOT(__hash__, tp_hash, slot_tp_hash, wrap_hashfunc,
|
||||
"__hash__($self, /)\n--\n\nReturn hash(self)."),
|
||||
FLSLOT(__call__, tp_call, slot_tp_call, (wrapperfunc)(void(*)(void))wrap_call,
|
||||
FLSLOT(__call__, tp_call, slot_tp_call,
|
||||
_Py_FUNC_CAST(wrapperfunc, wrap_call),
|
||||
"__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.",
|
||||
PyWrapperFlag_KEYWORDS),
|
||||
TPSLOT(__str__, tp_str, slot_tp_str, wrap_unaryfunc,
|
||||
|
@ -10844,7 +10845,8 @@ static pytype_slotdef slotdefs[] = {
|
|||
TPSLOT(__delete__, tp_descr_set, slot_tp_descr_set,
|
||||
wrap_descr_delete,
|
||||
"__delete__($self, instance, /)\n--\n\nDelete an attribute of instance."),
|
||||
FLSLOT(__init__, tp_init, slot_tp_init, (wrapperfunc)(void(*)(void))wrap_init,
|
||||
FLSLOT(__init__, tp_init, slot_tp_init,
|
||||
_Py_FUNC_CAST(wrapperfunc, wrap_init),
|
||||
"__init__($self, /, *args, **kwargs)\n--\n\n"
|
||||
"Initialize self. See help(type(self)) for accurate signature.",
|
||||
PyWrapperFlag_KEYWORDS),
|
||||
|
|
|
@ -4170,7 +4170,7 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
PyObject *res_o = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyObject *res_o = _PyCFunctionFast_CAST(cfunc)(
|
||||
PyCFunction_GET_SELF(callable_o),
|
||||
args_o,
|
||||
total_args);
|
||||
|
@ -4202,8 +4202,7 @@ dummy_func(
|
|||
STAT_INC(CALL, hit);
|
||||
/* res = func(self, arguments, nargs, kwnames) */
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable_o);
|
||||
_PyCFunctionFastWithKeywords_CAST(PyCFunction_GET_FUNCTION(callable_o));
|
||||
|
||||
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
|
||||
if (CONVERSION_FAILED(args_o)) {
|
||||
|
@ -4371,7 +4370,7 @@ dummy_func(
|
|||
ERROR_IF(true, error);
|
||||
}
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
_PyCFunctionFastWithKeywords_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
@ -4450,8 +4449,7 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
|
10
Python/executor_cases.c.h
generated
10
Python/executor_cases.c.h
generated
|
@ -5507,7 +5507,7 @@
|
|||
JUMP_TO_ERROR();
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyObject *res_o = _PyCFunctionFast_CAST(cfunc)(
|
||||
PyCFunction_GET_SELF(callable_o),
|
||||
args_o,
|
||||
total_args);
|
||||
|
@ -5567,8 +5567,7 @@
|
|||
STAT_INC(CALL, hit);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable_o);
|
||||
_PyCFunctionFastWithKeywords_CAST(PyCFunction_GET_FUNCTION(callable_o));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
|
||||
if (CONVERSION_FAILED(args_o)) {
|
||||
|
@ -5918,7 +5917,7 @@
|
|||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
_PyCFunctionFastWithKeywords_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
|
@ -6073,8 +6072,7 @@
|
|||
JUMP_TO_ERROR();
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
|
|
10
Python/generated_cases.c.h
generated
10
Python/generated_cases.c.h
generated
|
@ -2060,7 +2060,7 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *res_o = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyObject *res_o = _PyCFunctionFast_CAST(cfunc)(
|
||||
PyCFunction_GET_SELF(callable_o),
|
||||
args_o,
|
||||
total_args);
|
||||
|
@ -2153,8 +2153,7 @@
|
|||
STAT_INC(CALL, hit);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable_o);
|
||||
_PyCFunctionFastWithKeywords_CAST(PyCFunction_GET_FUNCTION(callable_o));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
|
||||
if (CONVERSION_FAILED(args_o)) {
|
||||
|
@ -3377,8 +3376,7 @@
|
|||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
|
@ -3505,7 +3503,7 @@
|
|||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
_PyCFunctionFastWithKeywords_CAST(meth->ml_meth);
|
||||
PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue