summaryrefslogtreecommitdiffstats
path: root/libcxx/include/list
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2018-06-05 22:32:52 +0000
committerEric Fiselier <eric@efcs.ca>2018-06-05 22:32:52 +0000
commit8cef7fd75ac3cbeb8efb767e5ba2dcdb76bf4454 (patch)
tree1ba50be1285e73602ab0fd69f0c89eef23062683 /libcxx/include/list
parenta79b6b3ef0d814080680a84202570acf4425ee12 (diff)
downloadbcm5719-llvm-8cef7fd75ac3cbeb8efb767e5ba2dcdb76bf4454.tar.gz
bcm5719-llvm-8cef7fd75ac3cbeb8efb767e5ba2dcdb76bf4454.zip
Fix PR37694 - std::vector doesn't correctly move construct allocators.
C++2a[container.requirements.general]p8 states that when move constructing a container, the allocator is move constructed. Vector previously copy constructed these allocators. This patch fixes that bug. Additionally it cleans up some unnecessary allocator conversions when copy constructing containers. Libc++ uses __internal_allocator_traits::select_on_copy_construction to select the correct allocator during copy construction, but it unnecessarily converted the resulting allocator to the user specified allocator type and back. After this patch list and forward_list no longer do that. Technically we're supposed to be using allocator_traits<allocator_type>::select_on_copy_construction, but that should seemingly be addressed as a separate patch, if at all. llvm-svn: 334053
Diffstat (limited to 'libcxx/include/list')
-rw-r--r--libcxx/include/list35
1 files changed, 24 insertions, 11 deletions
diff --git a/libcxx/include/list b/libcxx/include/list
index 4b22017f713..d2e78cd66af 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -556,6 +556,9 @@ protected:
typedef typename __rebind_alloc_helper<__alloc_traits, __node_base>::type __node_base_allocator;
typedef typename allocator_traits<__node_base_allocator>::pointer __node_base_pointer;
+ static_assert((!is_same<allocator_type, __node_allocator>::value),
+ "internal allocator type must differ from user-specified "
+ "type; otherwise overload resolution breaks");
__node_base __end_;
__compressed_pair<size_type, __node_allocator> __size_alloc_;
@@ -590,6 +593,11 @@ protected:
_NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value);
_LIBCPP_INLINE_VISIBILITY
__list_imp(const allocator_type& __a);
+ _LIBCPP_INLINE_VISIBILITY
+ __list_imp(const __node_allocator& __a);
+#ifndef _LIBCPP_CXX03_LANG
+ __list_imp(__node_allocator&& __a) _NOEXCEPT;
+#endif
~__list_imp();
void clear() _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
@@ -713,9 +721,18 @@ __list_imp<_Tp, _Alloc>::__list_imp(const allocator_type& __a)
}
template <class _Tp, class _Alloc>
-__list_imp<_Tp, _Alloc>::~__list_imp()
-{
- clear();
+inline __list_imp<_Tp, _Alloc>::__list_imp(const __node_allocator& __a)
+ : __size_alloc_(0, __a) {}
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Tp, class _Alloc>
+inline __list_imp<_Tp, _Alloc>::__list_imp(__node_allocator&& __a) _NOEXCEPT
+ : __size_alloc_(0, std::move(__a)) {}
+#endif
+
+template <class _Tp, class _Alloc>
+__list_imp<_Tp, _Alloc>::~__list_imp() {
+ clear();
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__erase_c(this);
#endif
@@ -1248,10 +1265,8 @@ list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, const allocator_type& __a,
template <class _Tp, class _Alloc>
list<_Tp, _Alloc>::list(const list& __c)
- : base(allocator_type(
- __node_alloc_traits::select_on_container_copy_construction(
- __c.__node_alloc())))
-{
+ : base(__node_alloc_traits::select_on_container_copy_construction(
+ __c.__node_alloc())) {
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_c(this);
#endif
@@ -1296,11 +1311,9 @@ list<_Tp, _Alloc>::list(initializer_list<value_type> __il)
}
template <class _Tp, class _Alloc>
-inline
-list<_Tp, _Alloc>::list(list&& __c)
+inline list<_Tp, _Alloc>::list(list&& __c)
_NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value)
- : base(allocator_type(_VSTD::move(__c.__node_alloc())))
-{
+ : base(_VSTD::move(__c.__node_alloc())) {
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_c(this);
#endif
OpenPOWER on IntegriCloud