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.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@273835 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/memory b/include/memory
index 587d305..47963e0 100644
--- a/include/memory
+++ b/include/memory
@@ -4115,23 +4115,22 @@
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 @@
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 @@
#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 @@
::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 @@
{
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 @@
{
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 @@
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> __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> __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> __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> __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> __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> __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> __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> __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> __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> __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;
}