Issue #23571: _Py_CheckFunctionResult() now gives the name of the function
which returned an invalid result (result+error or no result without error) in
the exception message.

Add also unit test to check that the exception contains the name of the
function.

Special case: the final _PyEval_EvalFrameEx() check doesn't mention the
function since it didn't execute a single function but a whole frame.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 50d893d..a19d28c 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2074,10 +2074,12 @@
 }
 
 PyObject*
-_Py_CheckFunctionResult(PyObject *result, const char *func_name)
+_Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
 {
     int err_occurred = (PyErr_Occurred() != NULL);
 
+    assert((func != NULL) ^ (where != NULL));
+
 #ifndef NDEBUG
     /* In debug mode: abort() with an assertion error. Use two different
        assertions, so if an assertion fails, it's possible to know
@@ -2090,8 +2092,14 @@
 
     if (result == NULL) {
         if (!err_occurred) {
-            PyErr_Format(PyExc_SystemError,
-                         "NULL result without error in %s", func_name);
+            if (func)
+                PyErr_Format(PyExc_SystemError,
+                             "%R returned NULL without setting an error",
+                             func);
+            else
+                PyErr_Format(PyExc_SystemError,
+                             "%s returned NULL without setting an error",
+                             where);
             return NULL;
         }
     }
@@ -2102,8 +2110,14 @@
 
             Py_DECREF(result);
 
-            PyErr_Format(PyExc_SystemError,
-                         "result with error in %s", func_name);
+            if (func)
+                PyErr_Format(PyExc_SystemError,
+                             "%R returned a result with an error set",
+                             func);
+            else
+                PyErr_Format(PyExc_SystemError,
+                             "%s returned a result with an error set",
+                             where);
             _PyErr_ChainExceptions(exc, val, tb);
             return NULL;
         }
@@ -2136,7 +2150,7 @@
 
     Py_LeaveRecursiveCall();
 
-    return _Py_CheckFunctionResult(result, "PyObject_Call");
+    return _Py_CheckFunctionResult(func, result, NULL);
 }
 
 static PyObject*
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 85b413f..b5467a4 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -142,7 +142,7 @@
         }
     }
 
-    return _Py_CheckFunctionResult(res, "PyCFunction_Call");
+    return _Py_CheckFunctionResult(func, res, NULL);
 }
 
 /* Methods (the standard built-in methods, that is) */