Author: ericwf
Date: Wed May 10 14:35:49 2017
New Revision: 302709

URL: http://llvm.org/viewvc/llvm-project?rev=302709&view=rev
Log:
[libc++] Fix PR32979 -  types with a private std::enable_shared_from_this base 
break shared_ptr

Summary:
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.

Reviewers: mclow.lists

Reviewed By: mclow.lists

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D33033

Modified:
    libcxx/trunk/include/memory
    
libcxx/trunk/test/std/utilities/memory/util.smartptr/util.smartptr.enab/enable_shared_from_this.pass.cpp

Modified: libcxx/trunk/include/memory
URL: 
http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=302709&r1=302708&r2=302709&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Wed May 10 14:35:49 2017
@@ -3924,7 +3924,10 @@ private:
 
     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 @@ private:
     template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
 };
 
+
 template<class _Tp>
 inline
 _LIBCPP_CONSTEXPR

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=302709&r1=302708&r2=302709&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 May 10 14:35:49 2017
@@ -49,6 +49,11 @@ struct Bar : public Foo {
 };
 
 
+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 @@ int main()
     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:


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to