diff options
| author | Eric Fiselier <eric@efcs.ca> | 2018-06-05 22:32:52 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2018-06-05 22:32:52 +0000 |
| commit | 8cef7fd75ac3cbeb8efb767e5ba2dcdb76bf4454 (patch) | |
| tree | 1ba50be1285e73602ab0fd69f0c89eef23062683 /libcxx/include/list | |
| parent | a79b6b3ef0d814080680a84202570acf4425ee12 (diff) | |
| download | bcm5719-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/list | 35 |
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 |

