erik.pilkington updated this revision to Diff 93488. erik.pilkington marked 2 inline comments as done. erik.pilkington added a comment.
In this new patch, use an explicit specialization of std::allocator that specifically only performs a rebind. This needs to be a specialization of std::allocator so we can use allocator's `allocator(const allocator<U> &)` ctor from `shared_ptr_pointer::__on_zero_shared_weak()`. Thanks, Erik https://reviews.llvm.org/D30837 Files: include/memory test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp =================================================================== --- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp +++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp @@ -45,6 +45,13 @@ virtual ~Foo() = default; }; +struct Result {}; +static Result theFunction() { return Result(); } +static int resultDeletorCount; +static void resultDeletor(Result (*pf)()) { + assert(pf == theFunction); + ++resultDeletorCount; +} int main() { @@ -65,7 +72,11 @@ std::shared_ptr<const Foo> p2 = std::make_shared<const Foo>(); assert(p2.get()); } - + { // https://bugs.llvm.org/show_bug.cgi?id=27566 + std::shared_ptr<Result()> x(&theFunction, &resultDeletor); + std::shared_ptr<Result()> y(theFunction, resultDeletor); + } + assert(resultDeletorCount == 2); #if TEST_STD_VER >= 11 nc = globalMemCounter.outstanding_new; { Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -3601,6 +3601,17 @@ __a.deallocate(_PTraits::pointer_to(*this), 1); } +struct __shared_ptr_dummy_rebind_allocator_type; +template <> +class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type> +{ + template <class _Other> + struct rebind + { + typedef allocator<_Other> other; + }; +}; + template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; template<class _Tp> @@ -3869,6 +3880,17 @@ #endif // _LIBCPP_HAS_NO_VARIADICS private: + template <class _Yp, bool = is_function<_Yp>::value> + struct __shared_ptr_default_allocator + { + typedef allocator<_Yp> type; + }; + + template <class _Yp> + struct __shared_ptr_default_allocator<_Yp, true> + { + typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type; + }; template <class _Yp, class _OrigPtr> _LIBCPP_INLINE_VISIBILITY @@ -3884,8 +3906,7 @@ } } - _LIBCPP_INLINE_VISIBILITY - void __enable_weak_this(const volatile void*, const volatile void*) _NOEXCEPT {} + _LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {} template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; @@ -3916,8 +3937,9 @@ : __ptr_(__p) { unique_ptr<_Yp> __hold(__p); - typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), allocator<_Yp>()); + typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; + typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT()); __hold.release(); __enable_weak_this(__p, __p); } @@ -3932,8 +3954,9 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__p, __d, allocator<_Yp>()); + typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; + typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); __enable_weak_this(__p, __p); #ifndef _LIBCPP_NO_EXCEPTIONS } @@ -3954,8 +3977,9 @@ try { #endif // _LIBCPP_NO_EXCEPTIONS - typedef __shared_ptr_pointer<nullptr_t, _Dp, allocator<_Tp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__p, __d, allocator<_Tp>()); + typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; + typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) @@ -4123,8 +4147,9 @@ else #endif { - typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>()); + typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; + typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } __r.release(); @@ -4152,10 +4177,11 @@ else #endif { + typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, reference_wrapper<typename remove_reference<_Dp>::type>, - allocator<_Yp> > _CntrlBlk; - __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), allocator<_Yp>()); + _AllocT > _CntrlBlk; + __cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), _AllocT()); __enable_weak_this(__r.get(), __r.get()); } __r.release();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits