EricWF created this revision. This patch fixes bugs.llvm.org/PR32979.
[util.smartptr.shared.const] says: > In the constructor definitions below, enables shared_from_this with p, for a > pointer p of type Y*, means > that if Y has an unambiguous and accessible base class that is a > specialization of enable_shared_from_- > this. This means that libc++ needs to respect the access specifier of the base class, and not attempt to construct and enabled_shared_from_this base if it is private. However access specifiers don't affect overload resolution so our current implementation will attempt to construct the private base. This patch uses SFINAE to correctly detect if the shared_ptr input has an accessible enable_shared_from_this base class. https://reviews.llvm.org/D33033 Files: include/memory test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp Index: test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp @@ -49,6 +49,11 @@ }; +struct PrivateBase : private std::enable_shared_from_this<PrivateBase> { + std::weak_ptr<PrivateBase> get_weak() { return weak_from_this(); } +}; + + int main() { { // https://bugs.llvm.org/show_bug.cgi?id=18843 @@ -74,6 +79,12 @@ assert(p == q); assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership } + { + typedef std::shared_ptr<PrivateBase> APtr; + typedef std::weak_ptr<PrivateBase> WeakAPtr; + APtr a1 = std::make_shared<PrivateBase>(); + assert(a1.use_count() == 1); + } // 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: Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3924,7 +3924,10 @@ template <class _Yp, class _OrigPtr> _LIBCPP_INLINE_VISIBILITY - void + typename enable_if<is_convertible<_OrigPtr*, + const enable_shared_from_this<_Yp>* + >::value, + void>::type __enable_weak_this(const enable_shared_from_this<_Yp>* __e, _OrigPtr* __ptr) _NOEXCEPT { @@ -3943,6 +3946,7 @@ template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; }; + template<class _Tp> inline _LIBCPP_CONSTEXPR
Index: test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp @@ -49,6 +49,11 @@ }; +struct PrivateBase : private std::enable_shared_from_this<PrivateBase> { + std::weak_ptr<PrivateBase> get_weak() { return weak_from_this(); } +}; + + int main() { { // https://bugs.llvm.org/show_bug.cgi?id=18843 @@ -74,6 +79,12 @@ assert(p == q); assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership } + { + typedef std::shared_ptr<PrivateBase> APtr; + typedef std::weak_ptr<PrivateBase> WeakAPtr; + APtr a1 = std::make_shared<PrivateBase>(); + assert(a1.use_count() == 1); + } // 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: Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3924,7 +3924,10 @@ template <class _Yp, class _OrigPtr> _LIBCPP_INLINE_VISIBILITY - void + typename enable_if<is_convertible<_OrigPtr*, + const enable_shared_from_this<_Yp>* + >::value, + void>::type __enable_weak_this(const enable_shared_from_this<_Yp>* __e, _OrigPtr* __ptr) _NOEXCEPT { @@ -3943,6 +3946,7 @@ template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; }; + template<class _Tp> inline _LIBCPP_CONSTEXPR
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits