Commit 6291a297 authored by Lars Buitinck's avatar Lars Buitinck

Translate C++ std::bad_cast exception to Python TypeError

parent 2731cebc
...@@ -8228,6 +8228,8 @@ static void __Pyx_CppExn2PyErr() { ...@@ -8228,6 +8228,8 @@ static void __Pyx_CppExn2PyErr() {
PyErr_SetString(PyExc_ValueError, exn.what()); PyErr_SetString(PyExc_ValueError, exn.what());
} catch (const std::bad_alloc& exn) { } catch (const std::bad_alloc& exn) {
PyErr_SetString(PyExc_MemoryError, exn.what()); PyErr_SetString(PyExc_MemoryError, exn.what());
} catch (const std::bad_cast& exn) {
PyErr_SetString(PyExc_TypeError, exn.what());
} catch (const std::ios_base::failure& exn) { } catch (const std::ios_base::failure& exn) {
// Unfortunately, in standard C++ we have no way of distinguishing EOF // Unfortunately, in standard C++ we have no way of distinguishing EOF
// from other errors here; be careful with the exception mask // from other errors here; be careful with the exception mask
......
...@@ -580,6 +580,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -580,6 +580,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
env.add_include_file('ios') # for std::ios_base::failure env.add_include_file('ios') # for std::ios_base::failure
env.add_include_file('new') # for std::bad_alloc env.add_include_file('new') # for std::bad_alloc
env.add_include_file('stdexcept') env.add_include_file('stdexcept')
env.add_include_file('typeinfo') # for std::bad_cast
if return_type.is_pyobject \ if return_type.is_pyobject \
and (self.exception_value or self.exception_check) \ and (self.exception_value or self.exception_check) \
and self.exception_check != '+': and self.exception_check != '+':
......
...@@ -16,6 +16,7 @@ cdef extern from "cpp_exceptions_helper.h": ...@@ -16,6 +16,7 @@ cdef extern from "cpp_exceptions_helper.h":
cdef void raise_memory "raise_memory"() except + cdef void raise_memory "raise_memory"() except +
cdef void raise_overflow "raise_overflow"() except + cdef void raise_overflow "raise_overflow"() except +
cdef void raise_range_error "raise_range_error"() except + cdef void raise_range_error "raise_range_error"() except +
cdef void raise_typeerror "raise_typeerror"() except +
cdef void raise_underflow "raise_underflow"() except + cdef void raise_underflow "raise_underflow"() except +
cdef cppclass Foo: cdef cppclass Foo:
...@@ -65,6 +66,20 @@ def test_range_error(): ...@@ -65,6 +66,20 @@ def test_range_error():
""" """
raise_range_error() raise_range_error()
def test_typeerror():
"""
>>> test_typeerror()
Traceback (most recent call last):
...
TypeError
"""
# Re-raise the exception without a description string because we can't
# rely on the implementation-defined value of what() in the doctest.
try:
raise_typeerror()
except TypeError:
raise TypeError
def test_underflow(): def test_underflow():
""" """
>>> test_underflow() >>> test_underflow()
......
...@@ -44,6 +44,16 @@ void raise_range_error() { ...@@ -44,6 +44,16 @@ void raise_range_error() {
throw std::range_error("range_error"); throw std::range_error("range_error");
} }
struct Base { virtual ~Base() {} };
struct Derived : Base { void use() const { abort(); } };
void raise_typeerror() {
Base foo;
Base &bar = foo; // prevents "dynamic_cast can never succeed" warning
Derived &baz = dynamic_cast<Derived &>(bar);
baz.use(); // not reached; prevents "unused variable" warning
}
void raise_underflow() { void raise_underflow() {
throw std::underflow_error("underflow_error"); throw std::underflow_error("underflow_error");
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment