summaryrefslogtreecommitdiff
path: root/Objects/methodobject.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2013-07-11 23:44:46 +0200
committerVictor Stinner <victor.stinner@gmail.com>2013-07-11 23:44:46 +0200
commite822e9e9c1a27846eb90b5357d2692b01abe1599 (patch)
treec620ad00aa5d9b1703df28b86e187091344716e8 /Objects/methodobject.c
parent77ec13e47fdd3aede81f701096bb759fd17be4d9 (diff)
downloadcpython-e822e9e9c1a27846eb90b5357d2692b01abe1599.tar.gz
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).
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r--Objects/methodobject.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 9944fade10..11c8b6e9c1 100644
--- 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)
- return (*meth)(self, arg);
+ if (kw == NULL || PyDict_Size(kw) == 0) {
+ res = (*meth)(self, arg);
+ CHECK_RESULT(res);
+ return res;
+ }
break;
case METH_VARARGS | METH_KEYWORDS:
- return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
+ res = (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
+ CHECK_RESULT(res);
+ return res;
case METH_NOARGS:
if (kw == NULL || PyDict_Size(kw) == 0) {
size = PyTuple_GET_SIZE(arg);
- if (size == 0)
- return (*meth)(self, NULL);
+ if (size == 0) {
+ res = (*meth)(self, NULL);
+ CHECK_RESULT(res);
+ return res;
+ }
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
f->m_ml->ml_name, size);
@@ -105,8 +116,11 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
case METH_O:
if (kw == NULL || PyDict_Size(kw) == 0) {
size = PyTuple_GET_SIZE(arg);
- if (size == 1)
- return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
+ if (size == 1) {
+ res = (*meth)(self, PyTuple_GET_ITEM(arg, 0));
+ CHECK_RESULT(res);
+ return res;
+ }
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
f->m_ml->ml_name, size);
@@ -123,6 +137,8 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
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) */