https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85813
--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Mathias Stearn from comment #3) > My assumption was that if E(...) throws and it can't be caught, it should be > treated as any other case when an -fno-exceptions TU calls a throwing > function. In this case that would mean calling terminate() due to the > noexcept, which seems better than returning a null exception_ptr. Unfortunately, if E(...) throws and std::make_exception_ptr<E> was compiled with -fno-exceptions, the noexcept on that function is ignored and the exception propagates to the caller of std::make_exception_ptr. So exceptions can propagate out of a noexcept function compiled with -fno-exceptions, which is pretty counterintuitive because that's the last kind of function you'd expect to throw when you call it! But that's not unique to std::make_exception_ptr, it's true for any noexcept function compiled with -fno-exceptions that calls that could throw. (In reply to Mathias Stearn from comment #7) > Silently dropping errors always skeeves me out. I'm not sure if anyone is > well served by the current behavior. If it were up to me (and I know it > isn't) I'd make that case call std::terminate() or similar rather than > returning the "no error" value. That seems consistent with the behavior of > the __throw* functions, but it is a breaking change. Or even better, since > gcc seems fine throwing through functions marked noexcept in -fno-exceptions > TUs, maybe in the (very rare) case where copying/moving an exception throws > inside an -fno-exceptions TU, just let it bubble out. I'm persuaded that if constructing the E throws, we should just let it bubble out. We can't really do anything else. But we still have the case of -fno-rtti -fno-exceptions case where we can't use the newer non-throwing implementation of make_exception_ptr (because it uses typeid) and we can't use the original throwing one (because it uses throw). So that either has to terminate or return an empty exception_ptr, and either case is a problem if you mix'n'match, so ... > Do you think this case warrants a [[gnu::always_inline]]? I now think the -fno-rtti -fno-exceptions case should be always_inline. Here's what I'm considering ... /// Obtain an exception_ptr pointing to a copy of the supplied object. #if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions template<typename _Ex> exception_ptr make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT { #if __cplusplus >= 201103L && __cpp_rtti using _Ex2 = typename decay<_Ex>::type; void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex)); (void) __cxxabiv1::__cxa_init_primary_exception( __e, const_cast<std::type_info*>(&typeid(_Ex)), __exception_ptr::__dest_thunk<_Ex2>); __try { ::new (__e) _Ex2(__ex); return exception_ptr(__e); } __catch(...) { __cxxabiv1::__cxa_free_exception(__e); return current_exception(); } #else try { throw __ex; } catch(...) { return current_exception(); } #endif } #else // no RTTI and no exceptions // This is always_inline so the linker will never use this useless definition // instead of a working one compiled with RTTI and/or exceptions enabled. template<typename _Ex> __attribute__ ((__always_inline)) exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT { return exception_ptr(); } #endif Because only the no-op implementation is always_inline, there won't be any bloat caused by inlining the working implementation into a hot path.