diff --git a/include/memory b/include/memory index 014635234..8324d1c5f 100644 --- a/include/memory +++ b/include/memory @@ -4122,9 +4122,11 @@ private: { if (__e && __e->__weak_this_.expired()) { - __e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast(__e)); - __e->__weak_this_.__cntrl_ = __cntrl_; + weak_ptr<_Yp> __tmp; + __tmp.__ptr_ = const_cast<_Yp*>(static_cast(__e)); + __tmp.__cntrl_ = __cntrl_; __cntrl_->__add_weak(); + __e->__weak_this_.swap(__tmp); } } diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp index 669330406..6661e831a 100644 --- a/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp +++ b/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp @@ -26,6 +26,7 @@ #include #include "test_macros.h" +#include "count_new.hpp" struct T : public std::enable_shared_from_this @@ -62,7 +63,7 @@ int main() // * Using 'weak_from_this().expired()' in C++17. // * Using 'shared_from_this()' in all dialects. { - + assert(globalMemCounter.checkOutstandingNewEq(0)); T* ptr = new T; std::shared_ptr s(ptr); { @@ -87,6 +88,37 @@ int main() } } #endif + s.reset(); + assert(globalMemCounter.checkOutstandingNewEq(0)); + } + // Test LWG issue 2529 again. This time check that an expired pointer + // is replaced. + { + assert(globalMemCounter.checkOutstandingNewEq(0)); + T* ptr = new T; + std::weak_ptr weak; + { + std::shared_ptr s(ptr, &nullDeleter); + assert(ptr->shared_from_this() == s); + weak = s; + assert(!weak.expired()); + } + assert(weak.expired()); + weak.reset(); + +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + ptr->shared_from_this(); + assert(false); + } catch (std::bad_weak_ptr const&) { + } catch (...) { assert(false); } +#endif + { + std::shared_ptr s2(ptr, &nullDeleter); + assert(ptr->shared_from_this() == s2); + } + delete ptr; + assert(globalMemCounter.checkOutstandingNewEq(0)); } // Test weak_from_this_methods #if TEST_STD_VER > 14