Here is very basic code:
#include <memory>
class foo
{
public:
~foo() noexcept(false) { }
};
int main()
{
auto x = std::make_shared<foo>();
return 0;
}
Compiled as follows:
g++ -std=c++11 test.cpp <-- OK
clang++ -std=c++11 test.cpp <-- OK
clang++ -std=c++11 -stdlib=libc++ test.cpp <-- FAIL
When compiling with libc++, it failes with:
/usr/bin/../include/c++/v1/memory:3793:7: error: exception specification of overriding function is more lax than base version
class __shared_ptr_emplace
^
/usr/bin/../include/c++/v1/memory:4423:26: note: in instantiation of template class 'std::__1::__shared_ptr_emplace<foo,
std::__1::allocator<foo> >' requested here
::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...);
^
/usr/bin/../include/c++/v1/memory:4787:29: note: in instantiation of function template specialization
'std::__1::shared_ptr<foo>::make_shared<>' requested here
return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
^
exc.cpp:11:19: note: in instantiation of function template specialization 'std::__1::make_shared<foo>' requested here
auto x = std::make_shared<foo>();
^
/usr/bin/../include/c++/v1/memory:3719:13: note: overridden virtual function is here
virtual ~__shared_weak_count();
I thought it might be a bug in libc++, but wanted to check here before I file a bug.
the question(s) boil down to:
AS @T.C. says, [res.on.functions]/2 states:
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this International Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
[skip]
-- if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
Standard-ese aside, throwing from a destructor has been a bad idea for a long, long time (at least since C++98). If there is an exception in flight, and you throw another exception during stack unwinding, that's a quick trip to std::terminate()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With