Hi There was a little issue in this patch, here is the correct version.
François On 23/07/2017 19:41, François Dumont wrote:
Hi Is it time now to consider this patch ? * include/bits/stl_vector.h (_Vector_impl_data): New. (_Vector_impl): Inherit from latter. (_Vertor_impl(_Vector_impl&&, _Tp_alloc_type&&)): New. (_Vector_base(_Vector_base&&, const allocator_type&)): Use latter. (_Vector_base()): Default. (_Vector_base(size_t)): Delete. (_Vector_base(_Tp_alloc_type&&)): Delete. (_Vector_base(_Vector_base&&)): Default. (vector()): Default. (vector(vector&&, const allocator_type&, true_type)): New. (vector(vector&&, const allocator_type&, false_type)): New. (vector(vector&&, const allocator_type&)): Use latters. Tested under linux x86_64. François
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 69cb803..1cbfcd9 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -85,29 +85,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer; - struct _Vector_impl - : public _Tp_alloc_type + struct _Vector_impl_data { pointer _M_start; pointer _M_finish; pointer _M_end_of_storage; - _Vector_impl() - : _Tp_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage() - { } - - _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage() + _Vector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() { } #if __cplusplus >= 201103L - _Vector_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)), - _M_start(), _M_finish(), _M_end_of_storage() - { } + _Vector_impl_data(_Vector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish), + _M_end_of_storage(__x._M_end_of_storage) + { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); } #endif - void _M_swap_data(_Vector_impl& __x) _GLIBCXX_NOEXCEPT + void + _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT { std::swap(_M_start, __x._M_start); std::swap(_M_finish, __x._M_finish); @@ -230,54 +226,64 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR }; + struct _Vector_impl + : public _Tp_alloc_type, public _Vector_impl_data + { + _Vector_impl() _GLIBCXX_NOEXCEPT_IF( noexcept(_Tp_alloc_type()) ) + : _Tp_alloc_type() + { } + + _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Vector_impl(_Vector_impl&&) = default; + + _Vector_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Vector_impl(_Vector_impl&& __rv, _Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv)) + { } +#endif + }; + public: typedef _Alloc allocator_type; _Tp_alloc_type& _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT - { return *static_cast<_Tp_alloc_type*>(&this->_M_impl); } + { return this->_M_impl; } const _Tp_alloc_type& _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT - { return *static_cast<const _Tp_alloc_type*>(&this->_M_impl); } + { return this->_M_impl; } allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_get_Tp_allocator()); } - _Vector_base() - : _M_impl() { } +#if __cplusplus >= 201103L + _Vector_base() = default; +#else + _Vector_base() { } +#endif _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT : _M_impl(__a) { } - _Vector_base(size_t __n) - : _M_impl() - { _M_create_storage(__n); } - _Vector_base(size_t __n, const allocator_type& __a) : _M_impl(__a) { _M_create_storage(__n); } #if __cplusplus >= 201103L - _Vector_base(_Tp_alloc_type&& __a) noexcept - : _M_impl(std::move(__a)) { } - - _Vector_base(_Vector_base&& __x) noexcept - : _M_impl(std::move(__x._M_get_Tp_allocator())) - { this->_M_impl._M_swap_data(__x._M_impl); } + _Vector_base(_Vector_base&&) = default; _Vector_base(_Vector_base&& __x, const allocator_type& __a) - : _M_impl(__a) - { - if (__x.get_allocator() == __a) - this->_M_impl._M_swap_data(__x._M_impl); - else - { - size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start; - _M_create_storage(__n); - } - } + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { } #endif ~_Vector_base() _GLIBCXX_NOEXCEPT @@ -304,7 +310,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Tr::deallocate(_M_impl, __p, __n); } - private: + protected: void _M_create_storage(size_t __n) { @@ -379,11 +385,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Creates a %vector with no elements. */ - vector() #if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<_Alloc>::value) + vector() = default; +#else + vector() { } #endif - : _Base() { } /** * @brief Creates a %vector with no elements. @@ -459,13 +465,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L /** * @brief %Vector move constructor. - * @param __x A %vector of identical element and allocator types. * - * The newly-created %vector contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %vector. + * The newly-created %vector contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %vector. */ - vector(vector&& __x) noexcept - : _Base(std::move(__x)) { } + vector(vector&&) = default; /// Copy constructor with alternative allocator vector(const vector& __x, const allocator_type& __a) @@ -477,13 +483,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); } - /// Move constructor with alternative allocator - vector(vector&& __rv, const allocator_type& __m) - noexcept(_Alloc_traits::_S_always_equal()) + private: + vector(vector&& __rv, const allocator_type& __m, std::true_type) noexcept : _Base(std::move(__rv), __m) + { } + + vector(vector&& __rv, const allocator_type& __m, std::false_type) + : _Base(__m) { - if (__rv.get_allocator() != __m) + if (__rv.get_allocator() == __m) + this->_M_impl._M_swap_data(__rv._M_impl); + else if (!__rv.empty()) { + this->_M_create_storage(__rv.size()); this->_M_impl._M_finish = std::__uninitialized_move_a(__rv.begin(), __rv.end(), this->_M_impl._M_start, @@ -492,6 +504,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + public: + /// Move constructor with alternative allocator + vector(vector&& __rv, const allocator_type& __m) + noexcept(_Alloc_traits::_S_always_equal()) + : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{}) + { } + /** * @brief Builds a %vector from an initializer list. * @param __l An initializer_list. @@ -534,7 +553,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } #else template<typename _InputIterator> vector(_InputIterator __first, _InputIterator __last, @@ -1405,6 +1427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by the range constructor to implement [23.1.1]/9 +#if __cplusplus < 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template<typename _Integer> @@ -1423,10 +1446,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_range_initialize(__first, __last, _IterCategory()); + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); } +#endif // Called by the second initialize_dispatch above template<typename _InputIterator> diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc new file mode 100644 index 0000000..1f0719d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } +// { dg-options "-O0" } +// { dg-xfail-run-if "PR c++/65816" { *-*-* } } + +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +#include <ext/aligned_buffer.h> + +using T = int; + +using __gnu_test::default_init_allocator; + +void test01() +{ + typedef default_init_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type; + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +void test02() +{ + typedef default_init_allocator<T> alloc_type; + typedef std::vector<T, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type(); + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +int main() +{ + test01(); + test02(); + return 0; +}