summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2022-03-31 08:02:34 (GMT)
committerGitHub <noreply@github.com>2022-03-31 08:02:34 (GMT)
commitf0bc69485677ae8973685866ada0982976d3878f (patch)
tree0d64ad8e39f8e7ad7835d87416b8f6bf9c3d4460
parentc14d7e4b816134b8e93ece4066a86d229631ce96 (diff)
downloadcpython-f0bc69485677ae8973685866ada0982976d3878f.zip
cpython-f0bc69485677ae8973685866ada0982976d3878f.tar.gz
cpython-f0bc69485677ae8973685866ada0982976d3878f.tar.bz2
bpo-47164: Add _PyCFunction_CAST() macro (GH-32192)
Use the macro in C files of the Python/ directory.
-rw-r--r--Doc/c-api/structures.rst3
-rw-r--r--Include/methodobject.h18
-rw-r--r--Python/_warnings.c6
-rw-r--r--Python/bltinmodule.c26
-rw-r--r--Python/context.c2
-rw-r--r--Python/hamt.c18
-rw-r--r--Python/sysmodule.c18
-rw-r--r--Python/traceback.c2
8 files changed, 57 insertions, 36 deletions
diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst
index 49f2a61..3270d7d 100644
--- a/Doc/c-api/structures.rst
+++ b/Doc/c-api/structures.rst
@@ -342,6 +342,9 @@ There are these calling conventions:
hold a reference to the module or object instance. In all cases the second
parameter will be ``NULL``.
+ The function must have 2 parameters. Since the second parameter is unused,
+ :c:macro:`Py_UNUSED` can be used to prevent a compiler warning.
+
.. data:: METH_O
diff --git a/Include/methodobject.h b/Include/methodobject.h
index 5d2e06c..959e775 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -26,6 +26,24 @@ typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *,
typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *,
size_t, PyObject *);
+// Cast an 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
+// calling conventions).
+//
+// The macro can also be used for METH_FASTCALL and METH_VARARGS|METH_KEYWORDS
+// calling conventions to avoid compiler warnings because the function has more
+// than 2 parameters. The macro first casts the function to the
+// "void func(void)" type to prevent compiler warnings.
+//
+// If a function is declared with the METH_NOARGS calling convention, it must
+// have 2 parameters. Since the second parameter is unused, Py_UNUSED() can be
+// 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) ((PyCFunction)(void(*)(void))(func))
+
PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *);
PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *);
PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *);
diff --git a/Python/_warnings.c b/Python/_warnings.c
index be962e7..942308b 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -1078,7 +1078,7 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
}
static PyObject *
-warnings_filters_mutated(PyObject *self, PyObject *args)
+warnings_filters_mutated(PyObject *self, PyObject *Py_UNUSED(args))
{
PyInterpreterState *interp = get_current_interp();
if (interp == NULL) {
@@ -1353,9 +1353,9 @@ PyDoc_STRVAR(warn_explicit_doc,
static PyMethodDef warnings_functions[] = {
WARNINGS_WARN_METHODDEF
- {"warn_explicit", (PyCFunction)(void(*)(void))warnings_warn_explicit,
+ {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit),
METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
- {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS,
+ {"_filters_mutated", _PyCFunction_CAST(warnings_filters_mutated), METH_NOARGS,
NULL},
/* XXX(brett.cannon): add showwarning? */
/* XXX(brett.cannon): Reasonable to add formatwarning? */
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 332f4cb..9cfecc5 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -613,7 +613,7 @@ filter_reduce(filterobject *lz, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyMethodDef filter_methods[] = {
- {"__reduce__", (PyCFunction)filter_reduce, METH_NOARGS, reduce_doc},
+ {"__reduce__", _PyCFunction_CAST(filter_reduce), METH_NOARGS, reduce_doc},
{NULL, NULL} /* sentinel */
};
@@ -1354,7 +1354,7 @@ map_reduce(mapobject *lz, PyObject *Py_UNUSED(ignored))
}
static PyMethodDef map_methods[] = {
- {"__reduce__", (PyCFunction)map_reduce, METH_NOARGS, reduce_doc},
+ {"__reduce__", _PyCFunction_CAST(map_reduce), METH_NOARGS, reduce_doc},
{NULL, NULL} /* sentinel */
};
@@ -2321,7 +2321,7 @@ PyDoc_STRVAR(builtin_sorted__doc__,
"reverse flag can be set to request the result in descending order.");
#define BUILTIN_SORTED_METHODDEF \
- {"sorted", (PyCFunction)(void(*)(void))builtin_sorted, METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},
+ {"sorted", _PyCFunction_CAST(builtin_sorted), METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},
static PyObject *
builtin_sorted(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -2839,8 +2839,8 @@ zip_setstate(zipobject *lz, PyObject *state)
}
static PyMethodDef zip_methods[] = {
- {"__reduce__", (PyCFunction)zip_reduce, METH_NOARGS, reduce_doc},
- {"__setstate__", (PyCFunction)zip_setstate, METH_O, setstate_doc},
+ {"__reduce__", _PyCFunction_CAST(zip_reduce), METH_NOARGS, reduce_doc},
+ {"__setstate__", _PyCFunction_CAST(zip_setstate), METH_O, setstate_doc},
{NULL} /* sentinel */
};
@@ -2904,7 +2904,7 @@ PyTypeObject PyZip_Type = {
static PyMethodDef builtin_methods[] = {
- {"__build_class__", (PyCFunction)(void(*)(void))builtin___build_class__,
+ {"__build_class__", _PyCFunction_CAST(builtin___build_class__),
METH_FASTCALL | METH_KEYWORDS, build_class_doc},
BUILTIN___IMPORT___METHODDEF
BUILTIN_ABS_METHODDEF
@@ -2912,17 +2912,17 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_ANY_METHODDEF
BUILTIN_ASCII_METHODDEF
BUILTIN_BIN_METHODDEF
- {"breakpoint", (PyCFunction)(void(*)(void))builtin_breakpoint, METH_FASTCALL | METH_KEYWORDS, breakpoint_doc},
+ {"breakpoint", _PyCFunction_CAST(builtin_breakpoint), METH_FASTCALL | METH_KEYWORDS, breakpoint_doc},
BUILTIN_CALLABLE_METHODDEF
BUILTIN_CHR_METHODDEF
BUILTIN_COMPILE_METHODDEF
BUILTIN_DELATTR_METHODDEF
- {"dir", builtin_dir, METH_VARARGS, dir_doc},
+ {"dir", builtin_dir, METH_VARARGS, dir_doc},
BUILTIN_DIVMOD_METHODDEF
BUILTIN_EVAL_METHODDEF
BUILTIN_EXEC_METHODDEF
BUILTIN_FORMAT_METHODDEF
- {"getattr", (PyCFunction)(void(*)(void))builtin_getattr, METH_FASTCALL, getattr_doc},
+ {"getattr", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, getattr_doc},
BUILTIN_GLOBALS_METHODDEF
BUILTIN_HASATTR_METHODDEF
BUILTIN_HASH_METHODDEF
@@ -2931,13 +2931,13 @@ static PyMethodDef builtin_methods[] = {
BUILTIN_INPUT_METHODDEF
BUILTIN_ISINSTANCE_METHODDEF
BUILTIN_ISSUBCLASS_METHODDEF
- {"iter", (PyCFunction)(void(*)(void))builtin_iter, METH_FASTCALL, iter_doc},
+ {"iter", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, iter_doc},
BUILTIN_AITER_METHODDEF
BUILTIN_LEN_METHODDEF
BUILTIN_LOCALS_METHODDEF
- {"max", (PyCFunction)(void(*)(void))builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},
- {"min", (PyCFunction)(void(*)(void))builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc},
- {"next", (PyCFunction)(void(*)(void))builtin_next, METH_FASTCALL, next_doc},
+ {"max", _PyCFunction_CAST(builtin_max), METH_VARARGS | METH_KEYWORDS, max_doc},
+ {"min", _PyCFunction_CAST(builtin_min), METH_VARARGS | METH_KEYWORDS, min_doc},
+ {"next", _PyCFunction_CAST(builtin_next), METH_FASTCALL, next_doc},
BUILTIN_ANEXT_METHODDEF
BUILTIN_OCT_METHODDEF
BUILTIN_ORD_METHODDEF
diff --git a/Python/context.c b/Python/context.c
index f3033d9..a77cd14 100644
--- a/Python/context.c
+++ b/Python/context.c
@@ -685,7 +685,7 @@ static PyMethodDef PyContext_methods[] = {
_CONTEXTVARS_CONTEXT_KEYS_METHODDEF
_CONTEXTVARS_CONTEXT_VALUES_METHODDEF
_CONTEXTVARS_CONTEXT_COPY_METHODDEF
- {"run", (PyCFunction)(void(*)(void))context_run, METH_FASTCALL | METH_KEYWORDS, NULL},
+ {"run", _PyCFunction_CAST(context_run), METH_FASTCALL | METH_KEYWORDS, NULL},
{NULL, NULL}
};
diff --git a/Python/hamt.c b/Python/hamt.c
index cbfe445..c3cb4e6 100644
--- a/Python/hamt.c
+++ b/Python/hamt.c
@@ -2845,14 +2845,14 @@ hamt_py_values(PyHamtObject *self, PyObject *args)
}
static PyObject *
-hamt_py_keys(PyHamtObject *self, PyObject *args)
+hamt_py_keys(PyHamtObject *self, PyObject *Py_UNUSED(args))
{
return _PyHamt_NewIterKeys(self);
}
#ifdef Py_DEBUG
static PyObject *
-hamt_py_dump(PyHamtObject *self, PyObject *args)
+hamt_py_dump(PyHamtObject *self, PyObject *Py_UNUSED(args))
{
return hamt_dump(self);
}
@@ -2860,14 +2860,14 @@ hamt_py_dump(PyHamtObject *self, PyObject *args)
static PyMethodDef PyHamt_methods[] = {
- {"set", (PyCFunction)hamt_py_set, METH_VARARGS, NULL},
- {"get", (PyCFunction)hamt_py_get, METH_VARARGS, NULL},
- {"delete", (PyCFunction)hamt_py_delete, METH_O, NULL},
- {"items", (PyCFunction)hamt_py_items, METH_NOARGS, NULL},
- {"keys", (PyCFunction)hamt_py_keys, METH_NOARGS, NULL},
- {"values", (PyCFunction)hamt_py_values, METH_NOARGS, NULL},
+ {"set", _PyCFunction_CAST(hamt_py_set), METH_VARARGS, NULL},
+ {"get", _PyCFunction_CAST(hamt_py_get), METH_VARARGS, NULL},
+ {"delete", _PyCFunction_CAST(hamt_py_delete), METH_O, NULL},
+ {"items", _PyCFunction_CAST(hamt_py_items), METH_NOARGS, NULL},
+ {"keys", _PyCFunction_CAST(hamt_py_keys), METH_NOARGS, NULL},
+ {"values", _PyCFunction_CAST(hamt_py_values), METH_NOARGS, NULL},
#ifdef Py_DEBUG
- {"__dump__", (PyCFunction)hamt_py_dump, METH_NOARGS, NULL},
+ {"__dump__", _PyCFunction_CAST(hamt_py_dump), METH_NOARGS, NULL},
#endif
{NULL, NULL}
};
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 6322af5..5765e9e 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1929,8 +1929,8 @@ sys_getandroidapilevel_impl(PyObject *module)
static PyMethodDef sys_methods[] = {
/* Might as well keep this in alphabetic order */
SYS_ADDAUDITHOOK_METHODDEF
- {"audit", (PyCFunction)(void(*)(void))sys_audit, METH_FASTCALL, audit_doc },
- {"breakpointhook", (PyCFunction)(void(*)(void))sys_breakpointhook,
+ {"audit", _PyCFunction_CAST(sys_audit), METH_FASTCALL, audit_doc },
+ {"breakpointhook", _PyCFunction_CAST(sys_breakpointhook),
METH_FASTCALL | METH_KEYWORDS, breakpointhook_doc},
SYS__CLEAR_TYPE_CACHE_METHODDEF
SYS__CURRENT_FRAMES_METHODDEF
@@ -1944,18 +1944,18 @@ static PyMethodDef sys_methods[] = {
SYS_GETDLOPENFLAGS_METHODDEF
SYS_GETALLOCATEDBLOCKS_METHODDEF
#ifdef Py_STATS
- {"getdxp", _Py_GetDXProfile, METH_VARARGS},
+ {"getdxp", _Py_GetDXProfile, METH_VARARGS},
#endif
SYS_GETFILESYSTEMENCODING_METHODDEF
SYS_GETFILESYSTEMENCODEERRORS_METHODDEF
SYS__GETQUICKENEDCOUNT_METHODDEF
#ifdef Py_TRACE_REFS
- {"getobjects", _Py_GetObjects, METH_VARARGS},
+ {"getobjects", _Py_GetObjects, METH_VARARGS},
#endif
SYS_GETTOTALREFCOUNT_METHODDEF
SYS_GETREFCOUNT_METHODDEF
SYS_GETRECURSIONLIMIT_METHODDEF
- {"getsizeof", (PyCFunction)(void(*)(void))sys_getsizeof,
+ {"getsizeof", _PyCFunction_CAST(sys_getsizeof),
METH_VARARGS | METH_KEYWORDS, getsizeof_doc},
SYS__GETFRAME_METHODDEF
SYS_GETWINDOWSVERSION_METHODDEF
@@ -1966,21 +1966,21 @@ static PyMethodDef sys_methods[] = {
SYS_SETSWITCHINTERVAL_METHODDEF
SYS_GETSWITCHINTERVAL_METHODDEF
SYS_SETDLOPENFLAGS_METHODDEF
- {"setprofile", sys_setprofile, METH_O, setprofile_doc},
+ {"setprofile", sys_setprofile, METH_O, setprofile_doc},
SYS_GETPROFILE_METHODDEF
SYS_SETRECURSIONLIMIT_METHODDEF
- {"settrace", sys_settrace, METH_O, settrace_doc},
+ {"settrace", sys_settrace, METH_O, settrace_doc},
SYS_GETTRACE_METHODDEF
SYS_CALL_TRACING_METHODDEF
SYS__DEBUGMALLOCSTATS_METHODDEF
SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
- {"set_asyncgen_hooks", (PyCFunction)(void(*)(void))sys_set_asyncgen_hooks,
+ {"set_asyncgen_hooks", _PyCFunction_CAST(sys_set_asyncgen_hooks),
METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc},
SYS_GET_ASYNCGEN_HOOKS_METHODDEF
SYS_GETANDROIDAPILEVEL_METHODDEF
SYS_UNRAISABLEHOOK_METHODDEF
- {NULL, NULL} /* sentinel */
+ {NULL, NULL} // sentinel
};
diff --git a/Python/traceback.c b/Python/traceback.c
index f5c1849..0d0eb95 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -149,7 +149,7 @@ tb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))
static PyMethodDef tb_methods[] = {
- {"__dir__", (PyCFunction)tb_dir, METH_NOARGS},
+ {"__dir__", _PyCFunction_CAST(tb_dir), METH_NOARGS},
{NULL, NULL, 0, NULL},
};