Skip to content

Commit 6862cb9

Browse files
committed
Add workaround for clang 3.3/3.4
As reported in #1349, clang before 3.5 can segfault on a function-local variable referenced inside a lambda. This moves the function-local static into a separate function that the lambda can invoke to avoid the issue. Fixes #1349
1 parent 6c62d27 commit 6862cb9

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

include/pybind11/pybind11.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,7 @@ void register_exception_translator(ExceptionTranslator&& translator) {
16501650
template <typename type>
16511651
class exception : public object {
16521652
public:
1653+
exception() = default;
16531654
exception(handle scope, const char *name, PyObject *base = PyExc_Exception) {
16541655
std::string full_name = scope.attr("__name__").cast<std::string>() +
16551656
std::string(".") + name;
@@ -1666,6 +1667,14 @@ class exception : public object {
16661667
}
16671668
};
16681669

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+
16691678
/**
16701679
* Registers a Python exception in `m` of the given `name` and installs an exception translator to
16711680
* translate the C++ exception to the created Python exception using the exceptions what() method.
@@ -1676,13 +1685,15 @@ template <typename CppException>
16761685
exception<CppException> &register_exception(handle scope,
16771686
const char *name,
16781687
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+
16801691
register_exception_translator([](std::exception_ptr p) {
16811692
if (!p) return;
16821693
try {
16831694
std::rethrow_exception(p);
16841695
} catch (const CppException &e) {
1685-
ex(e.what());
1696+
detail::get_exception_object<CppException>()(e.what());
16861697
}
16871698
});
16881699
return ex;

0 commit comments

Comments
 (0)