cpython: 5e50f1a0c985 (original) (raw)
Mercurial > cpython
changeset 84570:5e50f1a0c985
Issue #18408: In debug mode, PyCFunction_Call() now checks if an exception was raised if the result is NULL to help to find bugs in C mode (get the error earlier than the SystemError in ceval.c). [#18408]
Victor Stinner victor.stinner@gmail.com | |
---|---|
date | Thu, 11 Jul 2013 23:44:46 +0200 |
parents | 51eddca9dd6f |
children | 4975bcd67aa7 |
files | Objects/methodobject.c |
diffstat | 1 files changed, 23 insertions(+), 7 deletions(-)[+] [-] Objects/methodobject.c 30 |
line wrap: on
line diff
--- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -79,23 +79,34 @@ PyCFunction_GetFlags(PyObject *op) PyObject * PyCFunction_Call(PyObject *func, PyObject arg, PyObject kw) { +#define CHECK_RESULT(res) assert(res != NULL || PyErr_Occurred()) + PyCFunctionObject f = (PyCFunctionObject)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func);
- PyObject *res; Py_ssize_t size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS:
if (kw == NULL || PyDict_Size(kw) == 0)[](#l1.17)
return (*meth)(self, arg);[](#l1.18)
if (kw == NULL || PyDict_Size(kw) == 0) {[](#l1.19)
res = (*meth)(self, arg);[](#l1.20)
CHECK_RESULT(res);[](#l1.21)
return res;[](#l1.22)
case METH_VARARGS | METH_KEYWORDS:}[](#l1.23) break;[](#l1.24)
return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);[](#l1.26)
res = (*(PyCFunctionWithKeywords)meth)(self, arg, kw);[](#l1.27)
CHECK_RESULT(res);[](#l1.28)
case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg);return res;[](#l1.29)
if (size == 0)[](#l1.33)
return (*meth)(self, NULL);[](#l1.34)
if (size == 0) {[](#l1.35)
res = (*meth)(self, NULL);[](#l1.36)
CHECK_RESULT(res);[](#l1.37)
return res;[](#l1.38)
}[](#l1.39) PyErr_Format(PyExc_TypeError,[](#l1.40) "%.200s() takes no arguments (%zd given)",[](#l1.41) f->m_ml->ml_name, size);[](#l1.42)
@@ -105,8 +116,11 @@ PyCFunction_Call(PyObject *func, PyObjec case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg);
if (size == 1)[](#l1.47)
return (*meth)(self, PyTuple_GET_ITEM(arg, 0));[](#l1.48)
if (size == 1) {[](#l1.49)
res = (*meth)(self, PyTuple_GET_ITEM(arg, 0));[](#l1.50)
CHECK_RESULT(res);[](#l1.51)
return res;[](#l1.52)
}[](#l1.53) PyErr_Format(PyExc_TypeError,[](#l1.54) "%.200s() takes exactly one argument (%zd given)",[](#l1.55) f->m_ml->ml_name, size);[](#l1.56)
@@ -123,6 +137,8 @@ PyCFunction_Call(PyObject func, PyObjec PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; + +#undef CHECK_RESULT } / Methods (the standard built-in methods, that is) */