aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2018-10-25 13:03:13 +0000
committerMarc Glisse <marc.glisse@inria.fr>2018-10-25 13:03:13 +0000
commite6eebf08fb7ccfef677f2732f7da4af779c3dc1c (patch)
tree9da28f80357d64a8e89cdd7f85a670e3161265a4
parent02d33ebc9ad7bcef10d0b071439db519116dc2d0 (diff)
Relocation (= move+destroy)
2018-10-25 Marc Glisse <marc.glisse@inria.fr> PR libstdc++/87106 * include/bits/alloc_traits.h (_S_construct, _S_destroy, construct, destroy): Add noexcept specification. * include/bits/allocator.h (construct, destroy): Likewise. * include/ext/alloc_traits.h (construct, destroy): Likewise. * include/ext/malloc_allocator.h (construct, destroy): Likewise. * include/ext/new_allocator.h (construct, destroy): Likewise. * include/bits/stl_uninitialized.h (__relocate_object_a, __relocate_a, __relocate_a_1): New functions. (__is_trivially_relocatable): New class. * include/bits/stl_vector.h (__use_relocate): New static member. * include/bits/vector.tcc (reserve, _M_realloc_insert, _M_default_append): Use __relocate_a. (reserve, _M_assign_aux, _M_realloc_insert, _M_fill_insert, _M_default_append, _M_range_insert): Move _GLIBCXX_ASAN_ANNOTATE_REINIT after _Destroy. * testsuite/23_containers/vector/modifiers/push_back/49836.cc: Replace CopyConsOnlyType with DelAnyAssign. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@265485 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog21
-rw-r--r--libstdc++-v3/include/bits/alloc_traits.h10
-rw-r--r--libstdc++-v3/include/bits/allocator.h6
-rw-r--r--libstdc++-v3/include/bits/stl_uninitialized.h62
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h9
-rw-r--r--libstdc++-v3/include/bits/vector.tcc124
-rw-r--r--libstdc++-v3/include/ext/alloc_traits.h3
-rw-r--r--libstdc++-v3/include/ext/malloc_allocator.h6
-rw-r--r--libstdc++-v3/include/ext/new_allocator.h6
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc6
10 files changed, 213 insertions, 40 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9285a6becf5..575e52a70b6 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,24 @@
+2018-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR libstdc++/87106
+ * include/bits/alloc_traits.h (_S_construct, _S_destroy, construct,
+ destroy): Add noexcept specification.
+ * include/bits/allocator.h (construct, destroy): Likewise.
+ * include/ext/alloc_traits.h (construct, destroy): Likewise.
+ * include/ext/malloc_allocator.h (construct, destroy): Likewise.
+ * include/ext/new_allocator.h (construct, destroy): Likewise.
+ * include/bits/stl_uninitialized.h (__relocate_object_a, __relocate_a,
+ __relocate_a_1): New functions.
+ (__is_trivially_relocatable): New class.
+ * include/bits/stl_vector.h (__use_relocate): New static member.
+ * include/bits/vector.tcc (reserve, _M_realloc_insert,
+ _M_default_append): Use __relocate_a.
+ (reserve, _M_assign_aux, _M_realloc_insert, _M_fill_insert,
+ _M_default_append, _M_range_insert): Move _GLIBCXX_ASAN_ANNOTATE_REINIT
+ after _Destroy.
+ * testsuite/23_containers/vector/modifiers/push_back/49836.cc:
+ Replace CopyConsOnlyType with DelAnyAssign.
+
2018-10-24 François Dumont <fdumont@gcc.gnu.org>
* include/debug/safe_unordered_container.h
diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 742fdd0447d..9321fdff352 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -240,6 +240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename... _Args>
static _Require<__has_construct<_Tp, _Args...>>
_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+ noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
{ __a.construct(__p, std::forward<_Args>(__args)...); }
template<typename _Tp, typename... _Args>
@@ -247,17 +248,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
is_constructible<_Tp, _Args...>>>
_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
+ noexcept(noexcept(::new((void*)__p)
+ _Tp(std::forward<_Args>(__args)...)))
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
template<typename _Alloc2, typename _Tp>
static auto
_S_destroy(_Alloc2& __a, _Tp* __p, int)
+ noexcept(noexcept(__a.destroy(__p)))
-> decltype(__a.destroy(__p))
{ __a.destroy(__p); }
template<typename _Alloc2, typename _Tp>
static void
_S_destroy(_Alloc2&, _Tp* __p, ...)
+ noexcept(noexcept(__p->~_Tp()))
{ __p->~_Tp(); }
template<typename _Alloc2>
@@ -340,6 +345,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Tp, typename... _Args>
static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+ noexcept(noexcept(_S_construct(__a, __p,
+ std::forward<_Args>(__args)...)))
-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
@@ -353,6 +360,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Tp>
static void destroy(_Alloc& __a, _Tp* __p)
+ noexcept(noexcept(_S_destroy(__a, __p, 0)))
{ _S_destroy(__a, __p, 0); }
/**
@@ -472,6 +480,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up, typename... _Args>
static void
construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+ noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
{ __a.construct(__p, std::forward<_Args>(__args)...); }
/**
@@ -484,6 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up>
static void
destroy(allocator_type& __a, _Up* __p)
+ noexcept(noexcept(__a.destroy(__p)))
{ __a.destroy(__p); }
/**
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index d9d1d26e13a..9f018ea239c 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -88,11 +88,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up, typename... _Args>
void
construct(_Up* __p, _Args&&... __args)
+ noexcept(noexcept(::new((void *)__p)
+ _Up(std::forward<_Args>(__args)...)))
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
template<typename _Up>
void
- destroy(_Up* __p) { __p->~_Up(); }
+ destroy(_Up* __p)
+ noexcept(noexcept(__p->~_Up()))
+ { __p->~_Up(); }
#endif
};
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index c740503052b..94c7e151e29 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -879,6 +879,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
+#if __cplusplus >= 201103L
+ template<typename _Tp, typename _Up, typename _Allocator>
+ inline void
+ __relocate_object_a(_Tp* __dest, _Up* __orig, _Allocator& __alloc)
+ noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc,
+ __dest, std::move(*__orig)))
+ && noexcept(std::allocator_traits<_Allocator>::destroy(
+ __alloc, std::__addressof(*__orig))))
+ {
+ typedef std::allocator_traits<_Allocator> __traits;
+ __traits::construct(__alloc, __dest, std::move(*__orig));
+ __traits::destroy(__alloc, std::__addressof(*__orig));
+ }
+
+ // This class may be specialized for specific types.
+ template<typename _Tp>
+ struct __is_trivially_relocatable
+ : is_trivial<_Tp> { };
+
+ template <typename _Tp, typename _Up>
+ inline __enable_if_t<std::__is_trivially_relocatable<_Tp>::value, _Tp*>
+ __relocate_a_1(_Tp* __first, _Tp* __last,
+ _Tp* __result, allocator<_Up>& __alloc)
+ {
+ ptrdiff_t __count = __last - __first;
+ __builtin_memmove(__result, __first, __count * sizeof(_Tp));
+ return __result + __count;
+ }
+
+ template <typename _InputIterator, typename _ForwardIterator,
+ typename _Allocator>
+ inline _ForwardIterator
+ __relocate_a_1(_InputIterator __first, _InputIterator __last,
+ _ForwardIterator __result, _Allocator& __alloc)
+ {
+ typedef typename iterator_traits<_InputIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_ForwardIterator>::value_type
+ _ValueType2;
+ static_assert(std::is_same<_ValueType, _ValueType2>::value);
+ static_assert(noexcept(std::__relocate_object_a(std::addressof(*__result),
+ std::addressof(*__first),
+ __alloc)));
+ _ForwardIterator __cur = __result;
+ for (; __first != __last; ++__first, (void)++__cur)
+ std::__relocate_object_a(std::__addressof(*__cur),
+ std::__addressof(*__first), __alloc);
+ return __cur;
+ }
+
+ template <typename _InputIterator, typename _ForwardIterator,
+ typename _Allocator>
+ inline _ForwardIterator
+ __relocate_a(_InputIterator __first, _InputIterator __last,
+ _ForwardIterator __result, _Allocator& __alloc)
+ {
+ return __relocate_a_1(std::__niter_base(__first),
+ std::__niter_base(__last),
+ std::__niter_base(__result), __alloc);
+ }
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 37607417d08..40debd62396 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -421,6 +421,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef ptrdiff_t difference_type;
typedef _Alloc allocator_type;
+ private:
+#if __cplusplus >= 201103L
+ static constexpr bool __use_relocate =
+ noexcept(std::__relocate_object_a(
+ std::addressof(*std::declval<pointer>()),
+ std::addressof(*std::declval<pointer>()),
+ std::declval<_Tp_alloc_type&>()));
+#endif
+
protected:
using _Base::_M_allocate;
using _Base::_M_deallocate;
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index a1d114a0a9a..8df0f4180d4 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -71,12 +71,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (this->capacity() < __n)
{
const size_type __old_size = size();
- pointer __tmp = _M_allocate_and_copy(__n,
- _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
- _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+ pointer __tmp;
+#if __cplusplus >= 201103L
+ if constexpr (__use_relocate)
+ {
+ __tmp = this->_M_allocate(__n);
+ std::__relocate_a(this->_M_impl._M_start,
+ this->_M_impl._M_finish,
+ __tmp, _M_get_Tp_allocator());
+ }
+ else
+#endif
+ {
+ __tmp = _M_allocate_and_copy(__n,
+ _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
+ _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
+ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ }
_GLIBCXX_ASAN_ANNOTATE_REINIT;
- std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
- _M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
@@ -295,9 +308,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
_S_check_init_len(__len, _M_get_Tp_allocator());
pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
- _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
@@ -443,17 +456,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
__new_finish = pointer();
- __new_finish
- = std::__uninitialized_move_if_noexcept_a
- (__old_start, __position.base(),
- __new_start, _M_get_Tp_allocator());
+#if __cplusplus >= 201103L
+ if constexpr (__use_relocate)
+ {
+ __new_finish
+ = std::__relocate_a
+ (__old_start, __position.base(),
+ __new_start, _M_get_Tp_allocator());
+
+ ++__new_finish;
+
+ __new_finish
+ = std::__relocate_a
+ (__position.base(), __old_finish,
+ __new_finish, _M_get_Tp_allocator());
+ }
+ else
+#endif
+ {
+ __new_finish
+ = std::__uninitialized_move_if_noexcept_a
+ (__old_start, __position.base(),
+ __new_start, _M_get_Tp_allocator());
- ++__new_finish;
+ ++__new_finish;
- __new_finish
- = std::__uninitialized_move_if_noexcept_a
- (__position.base(), __old_finish,
- __new_finish, _M_get_Tp_allocator());
+ __new_finish
+ = std::__uninitialized_move_if_noexcept_a
+ (__position.base(), __old_finish,
+ __new_finish, _M_get_Tp_allocator());
+ }
}
__catch(...)
{
@@ -465,8 +497,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
+#if __cplusplus >= 201103L
+ if constexpr (!__use_relocate)
+#endif
+ std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
_GLIBCXX_ASAN_ANNOTATE_REINIT;
- std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
_M_deallocate(__old_start,
this->_M_impl._M_end_of_storage - __old_start);
this->_M_impl._M_start = __new_start;
@@ -562,9 +597,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
- _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
@@ -603,27 +638,48 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const size_type __len =
_M_check_len(__n, "vector::_M_default_append");
pointer __new_start(this->_M_allocate(__len));
- pointer __destroy_from = pointer();
- __try
+#if __cplusplus >= 201103L
+ if constexpr (__use_relocate)
{
- std::__uninitialized_default_n_a(__new_start + __size,
- __n, _M_get_Tp_allocator());
- __destroy_from = __new_start + __size;
- std::__uninitialized_move_if_noexcept_a(
- this->_M_impl._M_start, this->_M_impl._M_finish,
- __new_start, _M_get_Tp_allocator());
+ __try
+ {
+ std::__uninitialized_default_n_a(__new_start + __size,
+ __n, _M_get_Tp_allocator());
+ }
+ __catch(...)
+ {
+ _M_deallocate(__new_start, __len);
+ __throw_exception_again;
+ }
+ std::__relocate_a(this->_M_impl._M_start,
+ this->_M_impl._M_finish,
+ __new_start, _M_get_Tp_allocator());
}
- __catch(...)
+ else
+#endif
{
- if (__destroy_from)
- std::_Destroy(__destroy_from, __destroy_from + __n,
- _M_get_Tp_allocator());
- _M_deallocate(__new_start, __len);
- __throw_exception_again;
+ pointer __destroy_from = pointer();
+ __try
+ {
+ std::__uninitialized_default_n_a(__new_start + __size,
+ __n, _M_get_Tp_allocator());
+ __destroy_from = __new_start + __size;
+ std::__uninitialized_move_if_noexcept_a(
+ this->_M_impl._M_start, this->_M_impl._M_finish,
+ __new_start, _M_get_Tp_allocator());
+ }
+ __catch(...)
+ {
+ if (__destroy_from)
+ std::_Destroy(__destroy_from, __destroy_from + __n,
+ _M_get_Tp_allocator());
+ _M_deallocate(__new_start, __len);
+ __throw_exception_again;
+ }
+ std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
}
_GLIBCXX_ASAN_ANNOTATE_REINIT;
- std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
- _M_get_Tp_allocator());
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
@@ -742,9 +798,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_deallocate(__new_start, __len);
__throw_exception_again;
}
- _GLIBCXX_ASAN_ANNOTATE_REINIT;
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
+ _GLIBCXX_ASAN_ANNOTATE_REINIT;
_M_deallocate(this->_M_impl._M_start,
this->_M_impl._M_end_of_storage
- this->_M_impl._M_start);
diff --git a/libstdc++-v3/include/ext/alloc_traits.h b/libstdc++-v3/include/ext/alloc_traits.h
index 2570c59d81f..f1685374366 100644
--- a/libstdc++-v3/include/ext/alloc_traits.h
+++ b/libstdc++-v3/include/ext/alloc_traits.h
@@ -80,6 +80,8 @@ template<typename _Alloc, typename = typename _Alloc::value_type>
template<typename _Ptr, typename... _Args>
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
construct(_Alloc& __a, _Ptr __p, _Args&&... __args)
+ noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p),
+ std::forward<_Args>(__args)...)))
{
_Base_type::construct(__a, std::__to_address(__p),
std::forward<_Args>(__args)...);
@@ -89,6 +91,7 @@ template<typename _Alloc, typename = typename _Alloc::value_type>
template<typename _Ptr>
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
destroy(_Alloc& __a, _Ptr __p)
+ noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p))))
{ _Base_type::destroy(__a, std::__to_address(__p)); }
static _Alloc _S_select_on_copy(const _Alloc& __a)
diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h
index 1ae53b11ddb..5f91fe08af4 100644
--- a/libstdc++-v3/include/ext/malloc_allocator.h
+++ b/libstdc++-v3/include/ext/malloc_allocator.h
@@ -151,11 +151,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up, typename... _Args>
void
construct(_Up* __p, _Args&&... __args)
+ noexcept(noexcept(::new((void *)__p)
+ _Up(std::forward<_Args>(__args)...)))
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
template<typename _Up>
void
- destroy(_Up* __p) { __p->~_Up(); }
+ destroy(_Up* __p)
+ noexcept(noexcept(__p->~_Up()))
+ { __p->~_Up(); }
#else
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 402. wrong new expression in [some_] allocator::construct
diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h
index 83c894ce0a7..18a45cd75f1 100644
--- a/libstdc++-v3/include/ext/new_allocator.h
+++ b/libstdc++-v3/include/ext/new_allocator.h
@@ -142,11 +142,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up, typename... _Args>
void
construct(_Up* __p, _Args&&... __args)
+ noexcept(noexcept(::new((void *)__p)
+ _Up(std::forward<_Args>(__args)...)))
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
template<typename _Up>
void
- destroy(_Up* __p) { __p->~_Up(); }
+ destroy(_Up* __p)
+ noexcept(noexcept( __p->~_Up()))
+ { __p->~_Up(); }
#else
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 402. wrong new expression in [some_] allocator::construct
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc
index eb39e41cfac..85925ab756e 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/49836.cc
@@ -24,11 +24,11 @@
// libstdc++/49836
void test01()
{
- using __gnu_test::CopyConsOnlyType;
+ using __gnu_test::assign::DelAnyAssign;
using __gnu_test::MoveConsOnlyType;
- std::vector<CopyConsOnlyType> v1;
- CopyConsOnlyType t1(1);
+ std::vector<DelAnyAssign> v1;
+ DelAnyAssign t1;
v1.push_back(t1);
v1.push_back(t1);
v1.push_back(t1);