https://github.com/python/cpython/commit/50e518e886e6dde5542a2372d5b04acbdda4fc7d commit: 50e518e886e6dde5542a2372d5b04acbdda4fc7d branch: main author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-04-18T10:15:40+02:00 summary:
gh-132097: allow AC to disable fastcall convention to avoid UBSan failures (#131605) files: M Modules/_testclinic.c M Modules/clinic/_testclinic.c.h M Tools/clinic/libclinic/dsl_parser.py M Tools/clinic/libclinic/function.py M Tools/clinic/libclinic/parse_args.py diff --git a/Modules/_testclinic.c b/Modules/_testclinic.c index a5c4a4c40b3949..0a1f13db6ca204 100644 --- a/Modules/_testclinic.c +++ b/Modules/_testclinic.c @@ -1443,25 +1443,69 @@ _testclinic_TestClass_defclass_posonly_varpos_impl(PyObject *self, } -/*[clinic input] +/* + * # Do NOT use __new__ to generate this method. Compare: + * + * [1] With __new__ (METH_KEYWORDS must be added even if we don't want to) + * + * varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) + * varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args) + * no auto-generated METHODDEF macro + * + * [2] Without __new__ (automatically METH_FASTCALL, not good for this test) + * + * varpos_no_fastcall_impl(PyObject *type, PyObject *args) + * varpos_no_fastcall(PyObject *type, PyObject *const *args, Py_ssize_t nargs) + * flags = METH_FASTCALL|METH_CLASS + * + * [3] Without __new__ + "@disable fastcall" (what we want) + * + * varpos_no_fastcall(PyObject *type, PyObject *args) + * varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args) + * flags = METH_VARARGS|METH_CLASS + * + * We want to test a non-fastcall class method but without triggering an + * undefined behaviour at runtime in cfunction_call(). + * + * At runtime, a METH_VARARGS method called in cfunction_call() must be: + * + * (PyObject *, PyObject *) -> PyObject * + * (PyObject *, PyObject *, PyObject *) -> PyObject * + * + * depending on whether METH_KEYWORDS is present or not. + * + * AC determines whether a method is a __new__-like method solely bsaed + * on the method name, and not on its usage or its c_basename, and those + * methods must always be used with METH_VARARGS|METH_KEYWORDS|METH_CLASS. + * + * In particular, using [1] forces us to add METH_KEYWORDS even though + * the test shouldn't be expecting keyword arguments. Using [2] is also + * not possible since we want to test non-fastcalls. This is the reason + * why we need to be able to disable the METH_FASTCALL flag. + */ + +/*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as varpos_no_fastcall +_testclinic.TestClass.varpos_no_fastcall *args: tuple [clinic start generated code]*/ static PyObject * -varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args) -/*[clinic end generated code: output=04e94f2898bb2dde input=c5d3d30a6589f97f]*/ +_testclinic_TestClass_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *args) +/*[clinic end generated code: output=edfacec733aeb9c5 input=3f298d143aa98048]*/ { return Py_NewRef(args); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_varpos_no_fastcall +_testclinic.TestClass.posonly_varpos_no_fastcall a: object b: object @@ -1471,17 +1515,20 @@ _testclinic.TestClass.__new__ as posonly_varpos_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b, - PyObject *args) -/*[clinic end generated code: output=b0a0425719f69f5a input=10f29f2c2c6bfdc4]*/ +_testclinic_TestClass_posonly_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args) +/*[clinic end generated code: output=2c5184aebe020085 input=3621dd172c5193d8]*/ { return pack_arguments_newref(3, a, b, args); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_req_opt_varpos_no_fastcall +_testclinic.TestClass.posonly_req_opt_varpos_no_fastcall a: object b: object = False @@ -1491,17 +1538,20 @@ _testclinic.TestClass.__new__ as posonly_req_opt_varpos_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject *args) -/*[clinic end generated code: output=3c44915b1a554e2d input=d319302a8748147c]*/ +_testclinic_TestClass_posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args) +/*[clinic end generated code: output=08e533d59bceadf6 input=922fa7851b32e2dd]*/ { return pack_arguments_newref(3, a, b, args); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_poskw_varpos_no_fastcall +_testclinic.TestClass.posonly_poskw_varpos_no_fastcall a: object / @@ -1511,34 +1561,39 @@ _testclinic.TestClass.__new__ as posonly_poskw_varpos_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject *args) -/*[clinic end generated code: output=6ad74bed4bdc7f96 input=1f8c113e749414a3]*/ +_testclinic_TestClass_posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args) +/*[clinic end generated code: output=8ecfda20850e689f input=60443fe0bb8fe3e0]*/ { return pack_arguments_newref(3, a, b, args); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as varpos_array_no_fastcall +_testclinic.TestClass.varpos_array_no_fastcall *args: array [clinic start generated code]*/ static PyObject * -varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args, - Py_ssize_t args_length) -/*[clinic end generated code: output=f99d984346c60d42 input=368d8eea6de48c12]*/ +_testclinic_TestClass_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject * const *args, + Py_ssize_t args_length) +/*[clinic end generated code: output=27c9da663e942617 input=9ba5ae1f1eb58777]*/ { return _PyTuple_FromArray(args, args_length); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_varpos_array_no_fastcall +_testclinic.TestClass.posonly_varpos_array_no_fastcall a: object b: object @@ -1548,18 +1603,21 @@ _testclinic.TestClass.__new__ as posonly_varpos_array_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject * const *args, - Py_ssize_t args_length) -/*[clinic end generated code: output=1eec4da1fb5b5978 input=7330c8d819a23548]*/ +_testclinic_TestClass_posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length) +/*[clinic end generated code: output=71e676f1870b5a7e input=18eadf4c6eaab613]*/ { return pack_arguments_2pos_varpos(a, b, args, args_length); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_req_opt_varpos_array_no_fastcall +_testclinic.TestClass.posonly_req_opt_varpos_array_no_fastcall a: object b: object = False @@ -1569,19 +1627,21 @@ _testclinic.TestClass.__new__ as posonly_req_opt_varpos_array_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type, - PyObject *a, PyObject *b, - PyObject * const *args, - Py_ssize_t args_length) -/*[clinic end generated code: output=88041c2176135218 input=7f5fd34ee5f9e0bf]*/ +_testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length) +/*[clinic end generated code: output=abb395cae91d48ac input=5bf791fdad70b480]*/ { return pack_arguments_2pos_varpos(a, b, args, args_length); } /*[clinic input] +@disable fastcall @classmethod -_testclinic.TestClass.__new__ as posonly_poskw_varpos_array_no_fastcall +_testclinic.TestClass.posonly_poskw_varpos_array_no_fastcall a: object / @@ -1591,11 +1651,12 @@ _testclinic.TestClass.__new__ as posonly_poskw_varpos_array_no_fastcall [clinic start generated code]*/ static PyObject * -posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, - PyObject * const *args, - Py_ssize_t args_length) -/*[clinic end generated code: output=70eda18c3667681e input=2b0fcd7bd9bb865c]*/ +_testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length) +/*[clinic end generated code: output=aaddd9530048b229 input=9ed3842f4d472d45]*/ { return pack_arguments_2pos_varpos(a, b, args, args_length); } @@ -1606,27 +1667,15 @@ static struct PyMethodDef test_class_methods[] = { _TESTCLINIC_TESTCLASS_DEFCLASS_VARPOS_METHODDEF _TESTCLINIC_TESTCLASS_DEFCLASS_POSONLY_VARPOS_METHODDEF - {"varpos_no_fastcall", _PyCFunction_CAST(varpos_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_varpos_no_fastcall", _PyCFunction_CAST(posonly_varpos_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_req_opt_varpos_no_fastcall", _PyCFunction_CAST(posonly_req_opt_varpos_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_poskw_varpos_no_fastcall", _PyCFunction_CAST(posonly_poskw_varpos_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - - {"varpos_array_no_fastcall", - _PyCFunction_CAST(varpos_array_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_varpos_array_no_fastcall", - _PyCFunction_CAST(posonly_varpos_array_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_req_opt_varpos_array_no_fastcall", - _PyCFunction_CAST(posonly_req_opt_varpos_array_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, - {"posonly_poskw_varpos_array_no_fastcall", - _PyCFunction_CAST(posonly_poskw_varpos_array_no_fastcall), - METH_VARARGS|METH_KEYWORDS|METH_CLASS, ""}, + _TESTCLINIC_TESTCLASS_VARPOS_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_VARPOS_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_REQ_OPT_VARPOS_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_POSKW_VARPOS_NO_FASTCALL_METHODDEF + + _TESTCLINIC_TESTCLASS_VARPOS_ARRAY_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_VARPOS_ARRAY_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_REQ_OPT_VARPOS_ARRAY_NO_FASTCALL_METHODDEF + _TESTCLINIC_TESTCLASS_POSONLY_POSKW_VARPOS_ARRAY_NO_FASTCALL_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_testclinic.c.h b/Modules/clinic/_testclinic.c.h index f378e95cd6b2d8..56b0ca316d4952 100644 --- a/Modules/clinic/_testclinic.c.h +++ b/Modules/clinic/_testclinic.c.h @@ -4067,48 +4067,56 @@ _testclinic_TestClass_defclass_posonly_varpos(PyObject *self, PyTypeObject *cls, return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_varpos_no_fastcall__doc__, +"varpos_no_fastcall($type, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_VARPOS_NO_FASTCALL_METHODDEF \ + {"varpos_no_fastcall", (PyCFunction)_testclinic_TestClass_varpos_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_varpos_no_fastcall__doc__}, + static PyObject * -varpos_no_fastcall_impl(PyTypeObject *type, PyObject *args); +_testclinic_TestClass_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *args); static PyObject * -varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_varpos_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject *__clinic_args = NULL; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } __clinic_args = Py_NewRef(args); - return_value = varpos_no_fastcall_impl(type, __clinic_args); + return_value = _testclinic_TestClass_varpos_no_fastcall_impl((PyTypeObject *)type, __clinic_args); -exit: /* Cleanup for args */ Py_XDECREF(__clinic_args); return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_varpos_no_fastcall__doc__, +"posonly_varpos_no_fastcall($type, a, b, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_VARPOS_NO_FASTCALL_METHODDEF \ + {"posonly_varpos_no_fastcall", (PyCFunction)_testclinic_TestClass_posonly_varpos_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_posonly_varpos_no_fastcall__doc__}, + static PyObject * -posonly_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, PyObject *b, - PyObject *args); +_testclinic_TestClass_posonly_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args); static PyObject * -posonly_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_varpos_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject *a; PyObject *b; PyObject *__clinic_args = NULL; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } - if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("posonly_varpos_no_fastcall", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) { goto exit; } a = PyTuple_GET_ITEM(args, 0); @@ -4117,7 +4125,7 @@ posonly_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!__clinic_args) { goto exit; } - return_value = posonly_varpos_no_fastcall_impl(type, a, b, __clinic_args); + return_value = _testclinic_TestClass_posonly_varpos_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args); exit: /* Cleanup for args */ @@ -4126,24 +4134,29 @@ posonly_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_req_opt_varpos_no_fastcall__doc__, +"posonly_req_opt_varpos_no_fastcall($type, a, b=False, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_REQ_OPT_VARPOS_NO_FASTCALL_METHODDEF \ + {"posonly_req_opt_varpos_no_fastcall", (PyCFunction)_testclinic_TestClass_posonly_req_opt_varpos_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_posonly_req_opt_varpos_no_fastcall__doc__}, + static PyObject * -posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject *args); +_testclinic_TestClass_posonly_req_opt_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args); static PyObject * -posonly_req_opt_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_req_opt_varpos_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject *a; PyObject *b = Py_False; PyObject *__clinic_args = NULL; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } - if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("posonly_req_opt_varpos_no_fastcall", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) { goto exit; } a = PyTuple_GET_ITEM(args, 0); @@ -4156,7 +4169,7 @@ posonly_req_opt_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject if (!__clinic_args) { goto exit; } - return_value = posonly_req_opt_varpos_no_fastcall_impl(type, a, b, __clinic_args); + return_value = _testclinic_TestClass_posonly_req_opt_varpos_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args); exit: /* Cleanup for args */ @@ -4165,12 +4178,22 @@ posonly_req_opt_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_poskw_varpos_no_fastcall__doc__, +"posonly_poskw_varpos_no_fastcall($type, a, /, b, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_POSKW_VARPOS_NO_FASTCALL_METHODDEF \ + {"posonly_poskw_varpos_no_fastcall", _PyCFunction_CAST(_testclinic_TestClass_posonly_poskw_varpos_no_fastcall), METH_VARARGS|METH_KEYWORDS|METH_CLASS, _testclinic_TestClass_posonly_poskw_varpos_no_fastcall__doc__}, + static PyObject * -posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject *args); +_testclinic_TestClass_posonly_poskw_varpos_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject *args); static PyObject * -posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_poskw_varpos_no_fastcall(PyObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) @@ -4196,7 +4219,7 @@ posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *k static const char * const _keywords[] = {"", "b", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .fname = "TestClass", + .fname = "posonly_poskw_varpos_no_fastcall", .kwtuple = KWTUPLE, }; #undef KWTUPLE @@ -4218,7 +4241,7 @@ posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *k if (!__clinic_args) { goto exit; } - return_value = posonly_poskw_varpos_no_fastcall_impl(type, a, b, __clinic_args); + return_value = _testclinic_TestClass_posonly_poskw_varpos_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args); exit: /* Cleanup for args */ @@ -4227,83 +4250,95 @@ posonly_poskw_varpos_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *k return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_varpos_array_no_fastcall__doc__, +"varpos_array_no_fastcall($type, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_VARPOS_ARRAY_NO_FASTCALL_METHODDEF \ + {"varpos_array_no_fastcall", (PyCFunction)_testclinic_TestClass_varpos_array_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_varpos_array_no_fastcall__doc__}, + static PyObject * -varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject * const *args, - Py_ssize_t args_length); +_testclinic_TestClass_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject * const *args, + Py_ssize_t args_length); static PyObject * -varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_varpos_array_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject * const *__clinic_args; Py_ssize_t args_length; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } __clinic_args = _PyTuple_ITEMS(args); args_length = PyTuple_GET_SIZE(args); - return_value = varpos_array_no_fastcall_impl(type, __clinic_args, args_length); + return_value = _testclinic_TestClass_varpos_array_no_fastcall_impl((PyTypeObject *)type, __clinic_args, args_length); -exit: return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_varpos_array_no_fastcall__doc__, +"posonly_varpos_array_no_fastcall($type, a, b, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_VARPOS_ARRAY_NO_FASTCALL_METHODDEF \ + {"posonly_varpos_array_no_fastcall", (PyCFunction)_testclinic_TestClass_posonly_varpos_array_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_posonly_varpos_array_no_fastcall__doc__}, + static PyObject * -posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, PyObject * const *args, - Py_ssize_t args_length); +_testclinic_TestClass_posonly_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length); static PyObject * -posonly_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_varpos_array_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject *a; PyObject *b; PyObject * const *__clinic_args; Py_ssize_t args_length; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } - if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("posonly_varpos_array_no_fastcall", PyTuple_GET_SIZE(args), 2, PY_SSIZE_T_MAX)) { goto exit; } a = PyTuple_GET_ITEM(args, 0); b = PyTuple_GET_ITEM(args, 1); __clinic_args = _PyTuple_ITEMS(args) + 2; args_length = PyTuple_GET_SIZE(args) - 2; - return_value = posonly_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length); + return_value = _testclinic_TestClass_posonly_varpos_array_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args, args_length); exit: return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall__doc__, +"posonly_req_opt_varpos_array_no_fastcall($type, a, b=False, /, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_REQ_OPT_VARPOS_ARRAY_NO_FASTCALL_METHODDEF \ + {"posonly_req_opt_varpos_array_no_fastcall", (PyCFunction)_testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall, METH_VARARGS|METH_CLASS, _testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall__doc__}, + static PyObject * -posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type, - PyObject *a, PyObject *b, - PyObject * const *args, - Py_ssize_t args_length); +_testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length); static PyObject * -posonly_req_opt_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall(PyObject *type, PyObject *args) { PyObject *return_value = NULL; - PyTypeObject *base_tp = &PyBaseObject_Type; PyObject *a; PyObject *b = Py_False; PyObject * const *__clinic_args; Py_ssize_t args_length; - if ((type == base_tp || type->tp_init == base_tp->tp_init) && - !_PyArg_NoKeywords("TestClass", kwargs)) { - goto exit; - } - if (!_PyArg_CheckPositional("TestClass", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("posonly_req_opt_varpos_array_no_fastcall", PyTuple_GET_SIZE(args), 1, PY_SSIZE_T_MAX)) { goto exit; } a = PyTuple_GET_ITEM(args, 0); @@ -4314,20 +4349,29 @@ posonly_req_opt_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyO skip_optional: __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args); args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2); - return_value = posonly_req_opt_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length); + return_value = _testclinic_TestClass_posonly_req_opt_varpos_array_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args, args_length); exit: return return_value; } +PyDoc_STRVAR(_testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall__doc__, +"posonly_poskw_varpos_array_no_fastcall($type, a, /, b, *args)\n" +"--\n" +"\n"); + +#define _TESTCLINIC_TESTCLASS_POSONLY_POSKW_VARPOS_ARRAY_NO_FASTCALL_METHODDEF \ + {"posonly_poskw_varpos_array_no_fastcall", _PyCFunction_CAST(_testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall), METH_VARARGS|METH_KEYWORDS|METH_CLASS, _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall__doc__}, + static PyObject * -posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, PyObject *a, - PyObject *b, - PyObject * const *args, - Py_ssize_t args_length); +_testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall_impl(PyTypeObject *type, + PyObject *a, + PyObject *b, + PyObject * const *args, + Py_ssize_t args_length); static PyObject * -posonly_poskw_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObject *kwargs) +_testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall(PyObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) @@ -4353,7 +4397,7 @@ posonly_poskw_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObj static const char * const _keywords[] = {"", "b", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, - .fname = "TestClass", + .fname = "posonly_poskw_varpos_array_no_fastcall", .kwtuple = KWTUPLE, }; #undef KWTUPLE @@ -4374,9 +4418,9 @@ posonly_poskw_varpos_array_no_fastcall(PyTypeObject *type, PyObject *args, PyObj b = fastargs[1]; __clinic_args = PyTuple_GET_SIZE(args) > 2 ? _PyTuple_ITEMS(args) + 2 : _PyTuple_ITEMS(args); args_length = Py_MAX(0, PyTuple_GET_SIZE(args) - 2); - return_value = posonly_poskw_varpos_array_no_fastcall_impl(type, a, b, __clinic_args, args_length); + return_value = _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall_impl((PyTypeObject *)type, a, b, __clinic_args, args_length); exit: return return_value; } -/*[clinic end generated code: output=a3726ee0a94090d1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ea0b8fb0949fa49f input=a9049054013a1b77]*/ diff --git a/Tools/clinic/libclinic/dsl_parser.py b/Tools/clinic/libclinic/dsl_parser.py index 4b4a8b9969d142..282ff64cd33089 100644 --- a/Tools/clinic/libclinic/dsl_parser.py +++ b/Tools/clinic/libclinic/dsl_parser.py @@ -260,6 +260,7 @@ class DSLParser: preserve_output: bool critical_section: bool target_critical_section: list[str] + disable_fastcall: bool from_version_re = re.compile(r'([*/]) +\[from +(.+)\]') def __init__(self, clinic: Clinic) -> None: @@ -296,6 +297,7 @@ def reset(self) -> None: self.preserve_output = False self.critical_section = False self.target_critical_section = [] + self.disable_fastcall = False def directive_module(self, name: str) -> None: fields = name.split('.')[:-1] @@ -423,6 +425,18 @@ def at_critical_section(self, *args: str) -> None: self.target_critical_section.extend(args) self.critical_section = True + def at_disable(self, *args: str) -> None: + if self.kind is not CALLABLE: + fail("Can't set @disable, function is not a normal callable") + if not args: + fail("@disable expects at least one argument") + features = list(args) + if 'fastcall' in features: + features.remove('fastcall') + self.disable_fastcall = True + if features: + fail("invalid argument for @disable:", features[0]) + def at_getter(self) -> None: match self.kind: case FunctionKind.GETTER: @@ -691,6 +705,7 @@ def state_modulename_name(self, line: str) -> None: kind=self.kind, coexist=self.coexist, critical_section=self.critical_section, + disable_fastcall=self.disable_fastcall, target_critical_section=self.target_critical_section, forced_text_signature=self.forced_text_signature ) diff --git a/Tools/clinic/libclinic/function.py b/Tools/clinic/libclinic/function.py index 93901263e44c04..e80e2f5f13f648 100644 --- a/Tools/clinic/libclinic/function.py +++ b/Tools/clinic/libclinic/function.py @@ -109,6 +109,7 @@ class Function: docstring_only: bool = False forced_text_signature: str | None = None critical_section: bool = False + disable_fastcall: bool = False target_critical_section: list[str] = dc.field(default_factory=list) def __post_init__(self) -> None: diff --git a/Tools/clinic/libclinic/parse_args.py b/Tools/clinic/libclinic/parse_args.py index 978e2f4263b74a..0e15d2f163b816 100644 --- a/Tools/clinic/libclinic/parse_args.py +++ b/Tools/clinic/libclinic/parse_args.py @@ -260,7 +260,10 @@ def __init__(self, func: Function, codegen: CodeGen) -> None: if self.func.critical_section: self.codegen.add_include('pycore_critical_section.h', 'Py_BEGIN_CRITICAL_SECTION()') - self.fastcall = not self.is_new_or_init() + if self.func.disable_fastcall: + self.fastcall = False + else: + self.fastcall = not self.is_new_or_init() self.pos_only = 0 self.min_pos = 0 _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com