Fix leak in __enable_weak_this(). Thanks to Arthur O'Dwyer for finding it.
llvm-svn: 271487
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 7cf29e3468f7de38399abc756727f826ec6c6475
diff --git a/include/memory b/include/memory
index 0146352..8324d1c 100644
--- a/include/memory
+++ b/include/memory
@@ -4122,9 +4122,11 @@
{
if (__e && __e->__weak_this_.expired())
{
- __e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__e));
- __e->__weak_this_.__cntrl_ = __cntrl_;
+ weak_ptr<_Yp> __tmp;
+ __tmp.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__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 6693304..6661e83 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 <cassert>
#include "test_macros.h"
+#include "count_new.hpp"
struct T
: public std::enable_shared_from_this<T>
@@ -62,7 +63,7 @@
// * 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<T> s(ptr);
{
@@ -87,6 +88,37 @@
}
}
#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<T> weak;
+ {
+ std::shared_ptr<T> 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<T> 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