summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorBrandt Bucher <brandtbucher@microsoft.com>2022-08-19 19:33:44 (GMT)
committerGitHub <noreply@github.com>2022-08-19 19:33:44 (GMT)
commit5bfb3c372bda1113aea1385d4793f073a1d37155 (patch)
treea6b30a05ec2e5f59eadff759e47529ee76a6c132 /Python/ceval.c
parent2d9f252c0c08bce0e776b38906c3bbb59a3bd2c5 (diff)
downloadcpython-5bfb3c372bda1113aea1385d4793f073a1d37155.zip
cpython-5bfb3c372bda1113aea1385d4793f073a1d37155.tar.gz
cpython-5bfb3c372bda1113aea1385d4793f073a1d37155.tar.bz2
GH-90997: Wrap yield from/await in a virtual try/except StopIteration (GH-96010)
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 8c17e51..7024add 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2668,6 +2668,9 @@ handle_eval_breaker:
}
TARGET(YIELD_VALUE) {
+ // NOTE: It's important that YIELD_VALUE never raises an exception!
+ // The compiler treats any exception raised here as a failed close()
+ // or throw() call.
assert(oparg == STACK_LEVEL());
assert(frame->is_entry);
PyObject *retval = POP();
@@ -2746,6 +2749,26 @@ handle_eval_breaker:
}
}
+ TARGET(CLEANUP_THROW) {
+ assert(throwflag);
+ PyObject *exc_value = TOP();
+ assert(exc_value && PyExceptionInstance_Check(exc_value));
+ if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {
+ PyObject *value = ((PyStopIterationObject *)exc_value)->value;
+ Py_INCREF(value);
+ Py_DECREF(POP()); // The StopIteration.
+ Py_DECREF(POP()); // The last sent value.
+ Py_DECREF(POP()); // The delegated sub-iterator.
+ PUSH(value);
+ DISPATCH();
+ }
+ Py_INCREF(exc_value);
+ PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value));
+ PyObject *exc_traceback = PyException_GetTraceback(exc_value);
+ _PyErr_Restore(tstate, exc_type, exc_value, exc_traceback);
+ goto exception_unwind;
+ }
+
TARGET(LOAD_ASSERTION_ERROR) {
PyObject *value = PyExc_AssertionError;
Py_INCREF(value);