Hi mclow.lists, danalbert,
This patch add support for "fancy pointers/allocators" as well as fixing
support for shared_pointer and "minimal" allocators.
Fancy pointers are class types that meet the NullablePointer requirements. In
our case they are created by fancy allocators. `support/min_allocator.h` is an
archetype for these types.
There are three types of changes made in this patch:
1. `_Alloc::template rebind<T>::other` -> `__allocator_traits_rebind<_Alloc,
T>::type`.
This change was made because allocators don't need a rebind template.
`__allocator_traits_rebind` is used instead of `allocator_traits::rebind`
because use of `allocator_traits::rebind` requires a workaround for when
template aliases are unavailable.
2. `a.deallocate(this, 1)` ->
`a.deallocate(pointer_traits<self>::pointer_to(*this), 1)`. This change change
is made because fancy pointers aren't always constructible from raw pointers.
3. `p.get()` -> `addressof(*p.get())`. Fancy pointers aren't actually a
pointer. When we need a "real" pointer we take the address of dereferencing the
fancy pointer. This should give us the actual raw pointer.
http://reviews.llvm.org/D4859
Files:
include/memory
test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp
test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp
test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -3677,9 +3677,13 @@
void
__shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
{
- typename _Alloc::template rebind<__shared_ptr_pointer>::other __a(__data_.second());
+ typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _A;
+ typedef allocator_traits<_A> _ATraits;
+ typedef pointer_traits<typename _A::pointer> _PTraits;
+
+ _A __a(__data_.second());
__data_.second().~_Alloc();
- __a.deallocate(this, 1);
+ __a.deallocate(_PTraits::pointer_to(*this), 1);
}
template <class _Tp, class _Alloc>
@@ -3742,9 +3746,11 @@
void
__shared_ptr_emplace<_Tp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
{
- typename _Alloc::template rebind<__shared_ptr_emplace>::other __a(__data_.first());
+ typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type _A;
+ typedef pointer_traits<typename _A::pointer> _PTraits;
+ _A __a(__data_.first());
__data_.first().~_Alloc();
- __a.deallocate(this, 1);
+ __a.deallocate(_PTraits::pointer_to(*this), 1);
}
template<class _Tp> class _LIBCPP_TYPE_VIS_ONLY enable_shared_from_this;
@@ -4090,12 +4096,13 @@
{
#endif // _LIBCPP_NO_EXCEPTIONS
typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
typedef __allocator_destructor<_A2> _D2;
_A2 __a2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
- ::new(__hold2.get()) _CntrlBlk(__p, __d, __a);
- __cntrl_ = __hold2.release();
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__p, __d, __a);
+ __cntrl_ = _VSTD::addressof(*__hold2.release());
__enable_weak_this(__p);
#ifndef _LIBCPP_NO_EXCEPTIONS
}
@@ -4117,12 +4124,13 @@
{
#endif // _LIBCPP_NO_EXCEPTIONS
typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
typedef __allocator_destructor<_A2> _D2;
_A2 __a2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
- ::new(__hold2.get()) _CntrlBlk(__p, __d, __a);
- __cntrl_ = __hold2.release();
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__p, __d, __a);
+ __cntrl_ = _VSTD::addressof(*__hold2.release());
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
@@ -4282,14 +4290,15 @@
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _Args&& ...__args)
{
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _A2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
typedef __allocator_destructor<_A2> _D2;
_A2 __a2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1));
- ::new(__hold2.get()) _CntrlBlk(__a, _VSTD::forward<_Args>(__args)...);
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__a, _VSTD::forward<_Args>(__args)...);
shared_ptr<_Tp> __r;
__r.__ptr_ = __hold2.get()->get();
- __r.__cntrl_ = __hold2.release();
+ __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
__r.__enable_weak_this(__r.__ptr_);
return __r;
}
@@ -4373,14 +4382,15 @@
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a)
{
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
typedef __allocator_destructor<_Alloc2> _D2;
_Alloc2 __alloc2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
- ::new(__hold2.get()) _CntrlBlk(__a);
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__a);
shared_ptr<_Tp> __r;
__r.__ptr_ = __hold2.get()->get();
- __r.__cntrl_ = __hold2.release();
+ __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
__r.__enable_weak_this(__r.__ptr_);
return __r;
}
@@ -4391,14 +4401,15 @@
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0)
{
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
typedef __allocator_destructor<_Alloc2> _D2;
_Alloc2 __alloc2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
- ::new(__hold2.get()) _CntrlBlk(__a, __a0);
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__a, __a0);
shared_ptr<_Tp> __r;
__r.__ptr_ = __hold2.get()->get();
- __r.__cntrl_ = __hold2.release();
+ __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
__r.__enable_weak_this(__r.__ptr_);
return __r;
}
@@ -4409,14 +4420,15 @@
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1)
{
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
typedef __allocator_destructor<_Alloc2> _D2;
_Alloc2 __alloc2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
- ::new(__hold2.get()) _CntrlBlk(__a, __a0, __a1);
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__a, __a0, __a1);
shared_ptr<_Tp> __r;
__r.__ptr_ = __hold2.get()->get();
- __r.__cntrl_ = __hold2.release();
+ __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
__r.__enable_weak_this(__r.__ptr_);
return __r;
}
@@ -4427,14 +4439,15 @@
shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1, _A2& __a2)
{
typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
- typedef typename _Alloc::template rebind<_CntrlBlk>::other _Alloc2;
+ typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
typedef __allocator_destructor<_Alloc2> _D2;
_Alloc2 __alloc2(__a);
unique_ptr<_CntrlBlk, _D2> __hold2(__alloc2.allocate(1), _D2(__alloc2, 1));
- ::new(__hold2.get()) _CntrlBlk(__a, __a0, __a1, __a2);
+ ::new(static_cast<void*>(_VSTD::addressof(*__hold2.get())))
+ _CntrlBlk(__a, __a0, __a1, __a2);
shared_ptr<_Tp> __r;
__r.__ptr_ = __hold2.get()->get();
- __r.__cntrl_ = __hold2.release();
+ __r.__cntrl_ = _VSTD::addressof(*__hold2.release());
__r.__enable_weak_this(__r.__ptr_);
return __r;
}
Index: test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp
===================================================================
--- test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp
+++ test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/nullptr_t_deleter_allocator.pass.cpp
@@ -15,6 +15,7 @@
#include <cassert>
#include "../test_deleter.h"
#include "test_allocator.h"
+#include "min_allocator.h"
struct A
{
@@ -47,4 +48,21 @@
assert(test_deleter<A>::dealloc_count == 1);
assert(test_allocator<A>::count == 0);
assert(test_allocator<A>::alloc_count == 0);
+ test_deleter<A>::dealloc_count = 0;
+#if __cplusplus >= 201103L
+ {
+ std::shared_ptr<A> p(nullptr, test_deleter<A>(1), min_allocator<void>());
+ assert(A::count == 0);
+ assert(p.use_count() == 1);
+ assert(p.get() == 0);
+ test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
+ assert(test_deleter<A>::count ==1);
+ assert(test_deleter<A>::dealloc_count == 0);
+ assert(d);
+ assert(d->state() == 1);
+ }
+ assert(A::count == 0);
+ assert(test_deleter<A>::count == 0);
+ assert(test_deleter<A>::dealloc_count == 1);
+#endif
}
Index: test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp
===================================================================
--- test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp
+++ test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/pointer_deleter_allocator.pass.cpp
@@ -15,6 +15,7 @@
#include <cassert>
#include "../test_deleter.h"
#include "test_allocator.h"
+#include "min_allocator.h"
struct A
{
@@ -27,6 +28,7 @@
int A::count = 0;
+
int main()
{
{
@@ -48,4 +50,22 @@
assert(test_deleter<A>::dealloc_count == 1);
assert(test_allocator<A>::count == 0);
assert(test_allocator<A>::alloc_count == 0);
+ test_deleter<A>::dealloc_count = 0;
+#if __cplusplus >= 201103L
+ {
+ A* ptr = new A;
+ std::shared_ptr<A> p(ptr, test_deleter<A>(3), min_allocator<void>());
+ assert(A::count == 1);
+ assert(p.use_count() == 1);
+ assert(p.get() == ptr);
+ test_deleter<A>* d = std::get_deleter<test_deleter<A> >(p);
+ assert(test_deleter<A>::count == 1);
+ assert(test_deleter<A>::dealloc_count == 0);
+ assert(d);
+ assert(d->state() == 3);
+ }
+ assert(A::count == 0);
+ assert(test_deleter<A>::count == 0);
+ assert(test_deleter<A>::dealloc_count == 1);
+#endif
}
Index: test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
===================================================================
--- test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
+++ test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
@@ -19,6 +19,7 @@
#include <cstdlib>
#include <cassert>
#include "test_allocator.h"
+#include "min_allocator.h"
int new_count = 0;
@@ -54,4 +55,15 @@
}
assert(A::count == 0);
assert(test_allocator<A>::alloc_count == 0);
+#if __cplusplus >= 201103L
+ {
+ int i = 67;
+ char c = 'e';
+ std::shared_ptr<A> p = std::allocate_shared<A>(min_allocator<void>(), i, c);
+ assert(A::count == 1);
+ assert(p->get_int() == 67);
+ assert(p->get_char() == 'e');
+ }
+ assert(A::count == 0);
+#endif
}
Index: test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
===================================================================
--- /dev/null
+++ test/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_no_variadics.pass.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class T, class A, class... Args>
+// shared_ptr<T> allocate_shared(const A& a, Args&&... args);
+
+#define _LIBCPP_HAS_NO_VARIADICS
+#include <memory>
+#include <new>
+#include <cstdlib>
+#include <cassert>
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+int new_count = 0;
+
+struct A
+{
+ static int count;
+
+ A(int i, char c) : int_(i), char_(c) {++count;}
+ A(const A& a)
+ : int_(a.int_), char_(a.char_)
+ {++count;}
+ ~A() {--count;}
+
+ int get_int() const {return int_;}
+ char get_char() const {return char_;}
+private:
+ int int_;
+ char char_;
+};
+
+int A::count = 0;
+
+struct B
+{
+ static int count;
+ B() {++count;}
+ B(B const &) {++count;}
+ ~B() {--count;}
+};
+
+int B::count = 0;
+
+struct C
+{
+ static int count;
+
+ C(int i, char c, char) : int_(i), char_(c) {++count;}
+ C(const C& a)
+ : int_(a.int_), char_(a.char_)
+ {++count;}
+ ~C() {--count;}
+
+ int get_int() const {return int_;}
+ char get_char() const {return char_;}
+private:
+ int int_;
+ char char_;
+};
+
+int C::count = 0;
+
+int main()
+{
+ {
+ int i = 67;
+ char c = 'e';
+ std::shared_ptr<A> p = std::allocate_shared<A>(test_allocator<A>(54), i, c);
+ assert(test_allocator<A>::alloc_count == 1);
+ assert(A::count == 1);
+ assert(p->get_int() == 67);
+ assert(p->get_char() == 'e');
+ }
+ assert(A::count == 0);
+ assert(test_allocator<A>::alloc_count == 0);
+#if __cplusplus >= 201103L
+ {
+ int i = 67;
+ char c = 'e';
+ std::shared_ptr<C> p = std::allocate_shared<C>(min_allocator<void>(), i, c, c);
+ assert(C::count == 1);
+ assert(p->get_int() == 67);
+ assert(p->get_char() == 'e');
+ }
+ assert(C::count == 0);
+ {
+ int i = 67;
+ char c = 'e';
+ std::shared_ptr<A> p = std::allocate_shared<A>(min_allocator<void>(), i, c);
+ assert(A::count == 1);
+ assert(p->get_int() == 67);
+ assert(p->get_char() == 'e');
+ }
+ assert(A::count == 0);
+ {
+ int i = 67;
+ std::shared_ptr<int> p = std::allocate_shared<int>(min_allocator<void>(), i);
+ assert(*p == i);
+ }
+ {
+ std::shared_ptr<B> p = std::allocate_shared<B>(min_allocator<void>());
+ assert(B::count == 1);
+ }
+ assert(B::count == 0);
+#endif
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits