@@ -1650,6 +1650,7 @@ void register_exception_translator(ExceptionTranslator&& translator) {
1650
1650
template <typename type>
1651
1651
class exception : public object {
1652
1652
public:
1653
+ exception () = default ;
1653
1654
exception (handle scope, const char *name, PyObject *base = PyExc_Exception) {
1654
1655
std::string full_name = scope.attr (" __name__" ).cast <std::string>() +
1655
1656
std::string (" ." ) + name;
@@ -1666,6 +1667,14 @@ class exception : public object {
1666
1667
}
1667
1668
};
1668
1669
1670
+ NAMESPACE_BEGIN (detail)
1671
+ // Returns a reference to a function-local static exception object used in the simple
1672
+ // register_exception approach below. (It would be simpler to have the static local variable
1673
+ // directly in register_exception, but that makes clang <3.5 segfault - issue #1349).
1674
+ template <typename CppException>
1675
+ exception<CppException> &get_exception_object() { static exception<CppException> ex; return ex; }
1676
+ NAMESPACE_END (detail)
1677
+
1669
1678
/* *
1670
1679
* Registers a Python exception in `m` of the given `name` and installs an exception translator to
1671
1680
* translate the C++ exception to the created Python exception using the exceptions what() method.
@@ -1676,13 +1685,15 @@ template <typename CppException>
1676
1685
exception<CppException> ®ister_exception(handle scope,
1677
1686
const char *name,
1678
1687
PyObject *base = PyExc_Exception) {
1679
- static exception<CppException> ex (scope, name, base);
1688
+ auto &ex = detail::get_exception_object<CppException>();
1689
+ if (!ex) ex = exception<CppException>(scope, name, base);
1690
+
1680
1691
register_exception_translator ([](std::exception_ptr p) {
1681
1692
if (!p) return ;
1682
1693
try {
1683
1694
std::rethrow_exception (p);
1684
1695
} catch (const CppException &e) {
1685
- ex (e.what ());
1696
+ detail::get_exception_object<CppException>() (e.what ());
1686
1697
}
1687
1698
});
1688
1699
return ex;
0 commit comments