[libcxx] r273835 - Fix PR27115 - enable_shared_from_this does not work as a virtual base class.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 26 16:56:32 PDT 2016


Author: ericwf
Date: Sun Jun 26 18:56:32 2016
New Revision: 273835

URL: http://llvm.org/viewvc/llvm-project?rev=273835&view=rev
Log:
Fix PR27115 - enable_shared_from_this does not work as a virtual base class.

See https://llvm.org/bugs/show_bug.cgi?id=27115

The problem was that the conversion from
'const enable_shared_from_this<T>*' to 'const T*' didn't work if
T inherited enable_shared_from_this as a virtual base class. The fix
is to take the original pointer passed to shared_ptr's constructor in the
__enable_weak_this method and perform an upcast to 'const T*' instead of
performing a downcast from the enable_shared_from_this base.

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=273835&r1=273834&r2=273835&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Sun Jun 26 18:56:32 2016
@@ -4115,23 +4115,22 @@ public:
 
 private:
 
-    template <class _Yp>
+    template <class _Yp, class _OrigPtr>
         _LIBCPP_INLINE_VISIBILITY
         void
-        __enable_weak_this(const enable_shared_from_this<_Yp>* __e) _NOEXCEPT
+        __enable_weak_this(const enable_shared_from_this<_Yp>* __e,
+                           _OrigPtr* __ptr) _NOEXCEPT
         {
+            typedef typename remove_cv<_Yp>::type _RawYp;
             if (__e && __e->__weak_this_.expired())
             {
-                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);
+                __e->__weak_this_ = shared_ptr<_RawYp>(*this,
+                    const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr)));
             }
         }
 
     _LIBCPP_INLINE_VISIBILITY
-    void __enable_weak_this(const volatile void*) _NOEXCEPT {}
+    void __enable_weak_this(const volatile void*, const volatile void*) _NOEXCEPT {}
 
     template <class _Up> friend class _LIBCPP_TYPE_VIS_ONLY shared_ptr;
     template <class _Up> friend class _LIBCPP_TYPE_VIS_ONLY weak_ptr;
@@ -4165,7 +4164,7 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p,
     typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk;
     __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), allocator<_Yp>());
     __hold.release();
-    __enable_weak_this(__p);
+    __enable_weak_this(__p, __p);
 }
 
 template<class _Tp>
@@ -4180,7 +4179,7 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _D
 #endif  // _LIBCPP_NO_EXCEPTIONS
         typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk;
         __cntrl_ = new _CntrlBlk(__p, __d, allocator<_Yp>());
-        __enable_weak_this(__p);
+        __enable_weak_this(__p, __p);
 #ifndef _LIBCPP_NO_EXCEPTIONS
     }
     catch (...)
@@ -4230,7 +4229,7 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _D
         ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
             _CntrlBlk(__p, __d, __a);
         __cntrl_ = _VSTD::addressof(*__hold2.release());
-        __enable_weak_this(__p);
+        __enable_weak_this(__p, __p);
 #ifndef _LIBCPP_NO_EXCEPTIONS
     }
     catch (...)
@@ -4341,7 +4340,7 @@ shared_ptr<_Tp>::shared_ptr(auto_ptr<_Yp
 {
     typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk;
     __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<_Yp>());
-    __enable_weak_this(__r.get());
+    __enable_weak_this(__r.get(), __r.get());
     __r.release();
 }
 
@@ -4369,7 +4368,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_
     {
         typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk;
         __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>());
-        __enable_weak_this(__r.get());
+        __enable_weak_this(__r.get(), __r.get());
     }
     __r.release();
 }
@@ -4400,7 +4399,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_
                                      reference_wrapper<typename remove_reference<_Dp>::type>,
                                      allocator<_Yp> > _CntrlBlk;
         __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), allocator<_Yp>());
-        __enable_weak_this(__r.get());
+        __enable_weak_this(__r.get(), __r.get());
     }
     __r.release();
 }
@@ -4421,7 +4420,7 @@ shared_ptr<_Tp>::make_shared(_Args&& ...
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = __hold2.release();
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4440,7 +4439,7 @@ shared_ptr<_Tp>::allocate_shared(const _
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4459,7 +4458,7 @@ shared_ptr<_Tp>::make_shared()
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = __hold2.release();
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4477,7 +4476,7 @@ shared_ptr<_Tp>::make_shared(_A0& __a0)
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = __hold2.release();
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4495,7 +4494,7 @@ shared_ptr<_Tp>::make_shared(_A0& __a0,
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = __hold2.release();
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4513,7 +4512,7 @@ shared_ptr<_Tp>::make_shared(_A0& __a0,
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = __hold2.release();
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4532,7 +4531,7 @@ shared_ptr<_Tp>::allocate_shared(const _
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4551,7 +4550,7 @@ shared_ptr<_Tp>::allocate_shared(const _
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4570,7 +4569,7 @@ shared_ptr<_Tp>::allocate_shared(const _
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 
@@ -4589,7 +4588,7 @@ shared_ptr<_Tp>::allocate_shared(const _
     shared_ptr<_Tp> __r;
     __r.__ptr_ = __hold2.get()->get();
     __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
-    __r.__enable_weak_this(__r.__ptr_);
+    __r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
     return __r;
 }
 

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=273835&r1=273834&r2=273835&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 Sun Jun 26 18:56:32 2016
@@ -39,12 +39,28 @@ struct Z : Y {};
 
 void nullDeleter(void*) {}
 
+struct Foo : virtual public std::enable_shared_from_this<Foo>
+{
+	virtual ~Foo() {}
+};
+
+struct Bar : public Foo {
+    Bar(int) {}
+};
+
+
 int main()
 {
     {  // https://llvm.org/bugs/show_bug.cgi?id=18843
     std::shared_ptr<T const> t1(new T);
     std::shared_ptr<T const> t2(std::make_shared<T>());
     }
+    { // https://llvm.org/bugs/show_bug.cgi?id=27115
+    std::shared_ptr<Bar> t1(new Bar(42));
+    assert(t1->shared_from_this() == t1);
+    std::shared_ptr<Bar> t2(std::make_shared<Bar>(42));
+    assert(t2->shared_from_this() == t2);
+    }
     {
     std::shared_ptr<Y> p(new Z);
     std::shared_ptr<T> q = p->shared_from_this();




More information about the cfe-commits mailing list