From b2fdfd122827c1170c75702c05a4040997cf3bf5 Mon Sep 17 00:00:00 2001 From: Borja Zarco Date: Thu, 15 Aug 2019 07:42:43 -0400 Subject: [PATCH] Avoid use of lambda to work around a clang bug. (#1883) Clang has a bug [1] in x86 Windows that is exposed by the use of lambdas with "unforwardable" prototypes. The error is "error: cannot compile this forwarded non-trivially copyable parameter yet", and the message was introduced in [2] (used to be an assertion). [1] https://llvm.org/bugs/show_bug.cgi?id=28299 [2] https://github.com/microsoft/checkedc-clang/commit/feb1567e07573100ea14f9aea02f81463e791496 --- include/pybind11/detail/internals.h | 58 +++++++++++++++-------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 53d695ab8..2369d8fed 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -173,6 +173,34 @@ inline internals **&get_internals_pp() { return internals_pp; } +inline void translate_exception(std::exception_ptr p) { + try { + if (p) std::rethrow_exception(p); + } catch (error_already_set &e) { e.restore(); return; + } catch (const builtin_exception &e) { e.set_error(); return; + } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return; + } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; + } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; + } catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; + } catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return; + } catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; + } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return; + } catch (...) { + PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); + return; + } +} + +#if !defined(__GLIBCXX__) +inline void translate_local_exception(std::exception_ptr p) { + try { + if (p) std::rethrow_exception(p); + } catch (error_already_set &e) { e.restore(); return; + } catch (const builtin_exception &e) { e.set_error(); return; + } +} +#endif + /// Return a reference to the current `internals` data PYBIND11_NOINLINE inline internals &get_internals() { auto **&internals_pp = get_internals_pp(); @@ -198,15 +226,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { // // libstdc++ doesn't require this (types there are identified only by name) #if !defined(__GLIBCXX__) - (*internals_pp)->registered_exception_translators.push_front( - [](std::exception_ptr p) -> void { - try { - if (p) std::rethrow_exception(p); - } catch (error_already_set &e) { e.restore(); return; - } catch (const builtin_exception &e) { e.set_error(); return; - } - } - ); + (*internals_pp)->registered_exception_translators.push_front(&translate_local_exception); #endif } else { if (!internals_pp) internals_pp = new internals*(); @@ -229,25 +249,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { internals_ptr->istate = tstate->interp; #endif builtins[id] = capsule(internals_pp); - internals_ptr->registered_exception_translators.push_front( - [](std::exception_ptr p) -> void { - try { - if (p) std::rethrow_exception(p); - } catch (error_already_set &e) { e.restore(); return; - } catch (const builtin_exception &e) { e.set_error(); return; - } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return; - } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return; - } catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; - } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return; - } catch (...) { - PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); - return; - } - } - ); + internals_ptr->registered_exception_translators.push_front(&translate_exception); internals_ptr->static_property_type = make_static_property_type(); internals_ptr->default_metaclass = make_default_metaclass(); internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);