Following feedback on std::list patch this one had the same problem of
unused code being deleted. So here is a new version.
Ok to commit ?
François
On 28/07/2017 18:45, François Dumont wrote:
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..2fd7e2f 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -85,34 +85,54 @@ _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);
std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
+ };
+
+ 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(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept
+ : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv))
+ { }
+#endif
#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
template<typename = _Tp_alloc_type>
@@ -235,38 +255,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_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) { }
+#if !_GLIBCXX_INLINE_VERSION
_Vector_base(size_t __n)
: _M_impl()
{ _M_create_storage(__n); }
+#endif
_Vector_base(size_t __n, const allocator_type& __a)
: _M_impl(__a)
{ _M_create_storage(__n); }
#if __cplusplus >= 201103L
+ _Vector_base(_Vector_base&&) = default;
+
+# if !_GLIBCXX_INLINE_VERSION
_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&& __x, const allocator_type& __a)
: _M_impl(__a)
{
@@ -278,6 +302,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_create_storage(__n);
}
}
+# endif
+
+ _Vector_base(const allocator_type& __a, _Vector_base&& __x)
+ : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl))
+ { }
#endif
~_Vector_base() _GLIBCXX_NOEXCEPT
@@ -304,7 +333,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Tr::deallocate(_M_impl, __p, __n);
}
- private:
+ protected:
void
_M_create_storage(size_t __n)
{
@@ -379,11 +408,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 +488,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 +506,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())
- : _Base(std::move(__rv), __m)
+ private:
+ vector(vector&& __rv, const allocator_type& __m, std::true_type) noexcept
+ : _Base(__m, std::move(__rv))
+ { }
+
+ 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 +527,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 +576,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 +1450,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 +1469,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;
+}