Author: ericwf Date: Wed Jun 1 19:15:35 2016 New Revision: 271449 URL: http://llvm.org/viewvc/llvm-project?rev=271449&view=rev Log: Implement P0033R1 - Re-enabling shared_from_this
Summary: See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0033r1.html Reviewers: mclow.lists Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D19254 Modified: libcxx/trunk/include/memory libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp libcxx/trunk/www/cxx1z_status.html Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=271449&r1=271448&r2=271449&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Wed Jun 1 19:15:35 2016 @@ -4120,7 +4120,7 @@ private: void __enable_weak_this(const enable_shared_from_this<_Yp>* __e) _NOEXCEPT { - if (__e) + if (__e && __e->__weak_this_.expired()) { __e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__e)); __e->__weak_this_.__cntrl_ = __cntrl_; @@ -5432,6 +5432,16 @@ public: shared_ptr<_Tp const> shared_from_this() const {return shared_ptr<const _Tp>(__weak_this_);} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + weak_ptr<_Tp> weak_from_this() _NOEXCEPT + { return __weak_this_; } + + _LIBCPP_INLINE_VISIBILITY + weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT + { return __weak_this_; } +#endif // _LIBCPP_STD_VER > 14 + template <class _Up> friend class shared_ptr; }; Modified: libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp?rev=271449&r1=271448&r2=271449&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp Wed Jun 1 19:15:35 2016 @@ -18,11 +18,15 @@ // public: // shared_ptr<T> shared_from_this(); // shared_ptr<T const> shared_from_this() const; +// weak_ptr<T> weak_from_this() noexcept; // C++17 +// weak_ptr<T const> weak_from_this() const noexecpt; // C++17 // }; #include <memory> #include <cassert> +#include "test_macros.h" + struct T : public std::enable_shared_from_this<T> { @@ -32,6 +36,8 @@ struct Y : T {}; struct Z : Y {}; +void nullDeleter(void*) {} + int main() { { // https://llvm.org/bugs/show_bug.cgi?id=18843 @@ -50,4 +56,84 @@ int main() assert(p == q); assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership } + // Test LWG issue 2529. Only reset '__weak_ptr_' when it's already expired. + // http://cplusplus.github.io/LWG/lwg-active.html#2529. + // Test two different ways: + // * Using 'weak_from_this().expired()' in C++17. + // * Using 'shared_from_this()' in all dialects. + { + + T* ptr = new T; + std::shared_ptr<T> s(ptr); + { + // Don't re-initialize the "enabled_shared_from_this" base + // because it already references a non-expired shared_ptr. + std::shared_ptr<T> s2(ptr, &nullDeleter); + } +#if TEST_STD_VER > 14 + // The enabled_shared_from_this base should still be referencing + // the original shared_ptr. + assert(!ptr->weak_from_this().expired()); +#endif +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + std::shared_ptr<T> new_s = ptr->shared_from_this(); + assert(new_s == s); + } catch (std::bad_weak_ptr const&) { + assert(false); + } catch (...) { + assert(false); + } + } +#endif + } + // Test LWG issue 2529 again. This time check that an expired pointer + // is replaced. + { + 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; + } + // Test weak_from_this_methods +#if TEST_STD_VER > 14 + { + T* ptr = new T; + const T* cptr = ptr; + + static_assert(noexcept(ptr->weak_from_this()), "Operation must be noexcept"); + static_assert(noexcept(cptr->weak_from_this()), "Operation must be noexcept"); + + std::weak_ptr<T> my_weak = ptr->weak_from_this(); + assert(my_weak.expired()); + + std::weak_ptr<T const> my_const_weak = cptr->weak_from_this(); + assert(my_const_weak.expired()); + + // Enable shared_from_this with ptr. + std::shared_ptr<T> sptr(ptr); + my_weak = ptr->weak_from_this(); + assert(!my_weak.expired()); + assert(my_weak.lock().get() == ptr); + } +#endif } Modified: libcxx/trunk/www/cxx1z_status.html URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=271449&r1=271448&r2=271449&view=diff ============================================================================== --- libcxx/trunk/www/cxx1z_status.html (original) +++ libcxx/trunk/www/cxx1z_status.html Wed Jun 1 19:15:35 2016 @@ -82,7 +82,7 @@ <tr><td><a href="http://wg21.link/P0226R1">P0226R1</a></td><td>LWG</td><td>Mathematical Special Functions for C++17</td><td>Jacksonville</td><td></td><td></td></tr> <tr><td><a href="http://wg21.link/P0220R1">P0220R1</a></td><td>LWG</td><td>Adopt Library Fundamentals V1 TS Components for C++17</td><td>Jacksonville</td><td></td><td></td></tr> <tr><td><a href="http://wg21.link/P0218R1">P0218R1</a></td><td>LWG</td><td>Adopt the File System TS for C++17</td><td>Jacksonville</td><td></td><td></td></tr> - <tr><td><a href="http://wg21.link/P0033R1">P0033R1</a></td><td>LWG</td><td>Re-enabling shared_from_this</td><td>Jacksonville</td><td></td><td></td></tr> + <tr><td><a href="http://wg21.link/P0033R1">P0033R1</a></td><td>LWG</td><td>Re-enabling shared_from_this</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr> <tr><td><a href="http://wg21.link/P0005R4">P0005R4</a></td><td>LWG</td><td>Adopt not_fn from Library Fundamentals 2 for C++17</td><td>Jacksonville</td><td></td><td></td></tr> <tr><td><a href="http://wg21.link/P0152R1">P0152R1</a></td><td>LWG</td><td>constexpr atomic::is_always_lock_free</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr> <tr><td><a href="http://wg21.link/P0185R1">P0185R1</a></td><td>LWG</td><td>Adding [nothrow-]swappable traits</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits