diff options
14 files changed, 224 insertions, 25 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c4e10f1..092fa75 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,35 @@ +2018-05-18 François Dumont <fdumont@gcc.gnu.org> + + * include/bits/stl_tree.h + (_Rb_tree_impl(_Rb_tree_impl&&, _Node_allocator&&)): New. + (_Rb_tree(_Rb_tree&&, _Node_allocator&&, true_type)): New, use latter. + (_Rb_tree(_Rb_tree&&, _Node_allocator&&, false_type)): New. + (_Rb_tree(_Rb_tree&&, _Node_allocator&&)): Adapt, use latters. + * include/debug/map.h + (map(map&&, const_allocator_type&)): Add noexcept qualitication. + * include/debug/multimap.h + (multimap(multimap&&, const_allocator_type&)): Likewise. + * include/debug/set.h + (set(set&&, const_allocator_type&)): Likewise. + * include/debug/multiset.h + (multiset(multiset&&, const_allocator_type&)): Likewise. + * testsuite/23_containers/map/cons/noexcept_default_construct.cc: + Add checks. + * testsuite/23_containers/map/cons/noexcept_move_construct.cc: + Add checks. + * testsuite/23_containers/multimap/cons/noexcept_default_construct.cc: + Add checks. + * testsuite/23_containers/multimap/cons/noexcept_move_construct.cc: + Add checks. + * testsuite/23_containers/multiset/cons/noexcept_default_construct.cc: + Add checks. + * testsuite/23_containers/multiset/cons/noexcept_move_construct.cc: + Add checks. + * testsuite/23_containers/set/cons/noexcept_default_construct.cc: + Add checks. + * testsuite/23_containers/set/cons/noexcept_move_construct.cc: + Add checks. + 2018-05-18 Jason Merrill <jason@redhat.com> * include/bits/stl_deque.h (_Deque_iterator): Constrain constructor diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index d0a8448..85f190a 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -471,7 +471,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _Reuse_or_alloc_node { _Reuse_or_alloc_node(_Rb_tree& __t) - : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t) + : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t) { if (_M_root) { @@ -555,7 +555,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _Alloc_node { _Alloc_node(_Rb_tree& __t) - : _M_t(__t) { } + : _M_t(__t) { } template<typename _Arg> _Link_type @@ -715,6 +715,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else _Rb_tree_impl(_Rb_tree_impl&&) = default; + _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a) + : _Node_allocator(std::move(__a)), + _Base_key_compare(std::move(__x)), + _Rb_tree_header(std::move(__x)) + { } + _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) { } @@ -958,7 +964,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Rb_tree(std::move(__x), _Node_allocator(__a)) { } - _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a); + private: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type) + noexcept(is_nothrow_default_constructible<_Compare>::value) + : _M_impl(std::move(__x._M_impl), std::move(__a)) + { } + + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type) + : _M_impl(__x._M_impl._M_key_compare, std::move(__a)) + { + if (__x._M_root() != nullptr) + _M_move_data(__x, false_type{}); + } + + public: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) + noexcept( noexcept( + _Rb_tree(std::declval<_Rb_tree>(), std::declval<_Node_allocator>(), + std::declval<typename _Alloc_traits::is_always_equal>())) ) + : _Rb_tree(std::move(__x), std::move(__a), + typename _Alloc_traits::is_always_equal{}) + { } #endif ~_Rb_tree() _GLIBCXX_NOEXCEPT @@ -1358,22 +1384,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: // Move elements from container with equal allocator. void - _M_move_data(_Rb_tree& __x, std::true_type) + _M_move_data(_Rb_tree& __x, true_type) { _M_impl._M_move_data(__x._M_impl); } // Move elements from container with possibly non-equal allocator, // which might result in a copy not a move. void - _M_move_data(_Rb_tree&, std::false_type); + _M_move_data(_Rb_tree&, false_type); // Move assignment from container with equal allocator. void - _M_move_assign(_Rb_tree&, std::true_type); + _M_move_assign(_Rb_tree&, true_type); // Move assignment from container with possibly non-equal allocator, // which might result in a copy not a move. void - _M_move_assign(_Rb_tree&, std::false_type); + _M_move_assign(_Rb_tree&, false_type); #endif #if __cplusplus > 201402L @@ -1601,23 +1627,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Key, typename _Val, typename _KeyOfValue, typename _Compare, typename _Alloc> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) - : _M_impl(__x._M_impl._M_key_compare, std::move(__a)) - { - using __eq = typename _Alloc_traits::is_always_equal; - if (__x._M_root() != nullptr) - _M_move_data(__x, __eq()); - } - - template<typename _Key, typename _Val, typename _KeyOfValue, - typename _Compare, typename _Alloc> void _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_move_data(_Rb_tree& __x, std::false_type) + _M_move_data(_Rb_tree& __x, false_type) { if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) - _M_move_data(__x, std::true_type()); + _M_move_data(__x, true_type()); else { _Alloc_node __an(*this); @@ -1639,7 +1654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { clear(); if (__x._M_root() != nullptr) - _M_move_data(__x, std::true_type()); + _M_move_data(__x, true_type()); std::__alloc_on_move(_M_get_Node_allocator(), __x._M_get_Node_allocator()); } diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index 3f0649a..23966ba 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -105,6 +105,7 @@ namespace __debug : _Base(__m, __a) { } map(map&& __m, const allocator_type& __a) + noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index e709eb7..8054984 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -105,6 +105,7 @@ namespace __debug : _Base(__m, __a) { } multimap(multimap&& __m, const allocator_type& __a) + noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index 461f4f6..6e4c1b0 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -104,6 +104,7 @@ namespace __debug : _Base(__m, __a) { } multiset(multiset&& __m, const allocator_type& __a) + noexcept( noexcept(_Base(std::move(__m._M_base()), __a)) ) : _Safe(std::move(__m._M_safe()), __a), _Base(std::move(__m._M_base()), __a) { } diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index 2ac8f1c..571cc47 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -104,6 +104,7 @@ namespace __debug : _Base(__x, __a) { } set(set&& __x, const allocator_type& __a) + noexcept( noexcept(_Base(std::move(__x._M_base()), __a)) ) : _Safe(std::move(__x._M_safe()), __a), _Base(std::move(__x._M_base()), __a) { } diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_default_construct.cc index 4b9e119..e5c924d 100644 --- a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_default_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_default_construct.cc @@ -30,3 +30,19 @@ struct cmp using mtype2 = std::map<int, int, cmp>; static_assert( !std::is_nothrow_default_constructible<mtype2>::value, "Error"); + +template<typename _Tp> + struct not_noexcept_cons_alloc : std::allocator<_Tp> + { + not_noexcept_cons_alloc() /* noexcept */ + { } + + template<typename _Tp1> + struct rebind + { typedef not_noexcept_cons_alloc<_Tp1> other; }; + }; + +using mtype3 = std::map<int, int, std::less<int>, + not_noexcept_cons_alloc<std::pair<const int, int>>>; + +static_assert(!std::is_nothrow_default_constructible<mtype3>::value, "Error"); diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc index 0041408..723a63f 100644 --- a/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/map/cons/noexcept_move_construct.cc @@ -23,4 +23,25 @@ typedef std::map<int, int> mtype; -static_assert(std::is_nothrow_move_constructible<mtype>::value, "Error"); +static_assert( std::is_nothrow_move_constructible<mtype>::value, + "noexcept move constructor" ); +static_assert( std::is_nothrow_constructible<mtype, + mtype&&, const typename mtype::allocator_type&>::value, + "noexcept move constructor with allocator" ); + +struct not_noexcept_less +{ + not_noexcept_less() = default; + not_noexcept_less(const not_noexcept_less&) /* noexcept */ + { } + + bool + operator()(int l, int r) const + { return l < r; } +}; + +typedef std::map<int, int, not_noexcept_less> emtype; + +static_assert( !std::is_nothrow_constructible<emtype, emtype&&, + const typename emtype::allocator_type&>::value, + "except move constructor with allocator" ); diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_default_construct.cc index 9873770..62f5d60 100644 --- a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_default_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_default_construct.cc @@ -30,3 +30,19 @@ struct cmp using mtype2 = std::multimap<int, int, cmp>; static_assert( !std::is_nothrow_default_constructible<mtype2>::value, "Error"); + +template<typename _Tp> + struct not_noexcept_cons_alloc : std::allocator<_Tp> + { + not_noexcept_cons_alloc() /* noexcept */ + { } + + template<typename _Tp1> + struct rebind + { typedef not_noexcept_cons_alloc<_Tp1> other; }; + }; + +using mtype3 = std::multimap<int, int, std::less<int>, + not_noexcept_cons_alloc<std::pair<const int, int>>>; + +static_assert(!std::is_nothrow_default_constructible<mtype3>::value, "Error"); diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc index 0319a61..1612b0d 100644 --- a/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/noexcept_move_construct.cc @@ -23,4 +23,25 @@ typedef std::multimap<int, int> mmtype; -static_assert(std::is_nothrow_move_constructible<mmtype>::value, "Error"); +static_assert( std::is_nothrow_move_constructible<mmtype>::value, + "noexcept move constructor" ); +static_assert( std::is_nothrow_constructible<mmtype, + mmtype&&, const typename mmtype::allocator_type&>::value, + "noexcept move constructor with allocator" ); + +struct not_noexcept_less +{ + not_noexcept_less() = default; + not_noexcept_less(const not_noexcept_less&) /* noexcept */ + { } + + bool + operator()(int l, int r) const + { return l < r; } +}; + +typedef std::multimap<int, int, not_noexcept_less> emmtype; + +static_assert( !std::is_nothrow_constructible<emmtype, emmtype&&, + const typename emmtype::allocator_type&>::value, + "except move constructor with allocator" ); diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_default_construct.cc index 963e3d1..8e49168 100644 --- a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_default_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_default_construct.cc @@ -30,3 +30,19 @@ struct cmp using stype2 = std::multiset<int, cmp>; static_assert( !std::is_nothrow_default_constructible<stype2>::value, "Error"); + +template<typename _Tp> + struct not_noexcept_cons_alloc : std::allocator<_Tp> + { + not_noexcept_cons_alloc() /* noexcept */ + { } + + template<typename _Tp1> + struct rebind + { typedef not_noexcept_cons_alloc<_Tp1> other; }; + }; + +using stype3 = std::multiset<int, std::less<int>, + not_noexcept_cons_alloc<int>>; + +static_assert(!std::is_nothrow_default_constructible<stype3>::value, "Error"); diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc index b1c6dd5..4ef5127 100644 --- a/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/noexcept_move_construct.cc @@ -23,4 +23,25 @@ typedef std::multiset<int> mstype; -static_assert(std::is_nothrow_move_constructible<mstype>::value, "Error"); +static_assert( std::is_nothrow_move_constructible<mstype>::value, + "noexcept move constructor" ); +static_assert( std::is_nothrow_constructible<mstype, + mstype&&, const typename mstype::allocator_type&>::value, + "noexcept move constructor with allocator" ); + +struct not_noexcept_less +{ + not_noexcept_less() = default; + not_noexcept_less(const not_noexcept_less&) /* noexcept */ + { } + + bool + operator()(int l, int r) const + { return l < r; } +}; + +typedef std::multiset<int, not_noexcept_less> emstype; + +static_assert( !std::is_nothrow_constructible<emstype, emstype&&, + const typename emstype::allocator_type&>::value, + "except move constructor with allocator" ); diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_default_construct.cc index 882a12c..d3dc98d 100644 --- a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_default_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_default_construct.cc @@ -30,3 +30,19 @@ struct cmp using stype2 = std::set<int, cmp>; static_assert( !std::is_nothrow_default_constructible<stype2>::value, "Error"); + +template<typename _Tp> + struct not_noexcept_cons_alloc : std::allocator<_Tp> + { + not_noexcept_cons_alloc() /* noexcept */ + { } + + template<typename _Tp1> + struct rebind + { typedef not_noexcept_cons_alloc<_Tp1> other; }; + }; + +using stype3 = std::set<int, std::less<int>, + not_noexcept_cons_alloc<int>>; + +static_assert(!std::is_nothrow_default_constructible<stype3>::value, "Error"); diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc index a7de0ef..942400e 100644 --- a/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc +++ b/libstdc++-v3/testsuite/23_containers/set/cons/noexcept_move_construct.cc @@ -23,4 +23,25 @@ typedef std::set<int> stype; -static_assert(std::is_nothrow_move_constructible<stype>::value, "Error"); +static_assert( std::is_nothrow_move_constructible<stype>::value, + "noexcept move constructor" ); +static_assert( std::is_nothrow_constructible<stype, + stype&&, const typename stype::allocator_type&>::value, + "noexcept move constructor with allocator" ); + +struct not_noexcept_less +{ + not_noexcept_less() = default; + not_noexcept_less(const not_noexcept_less&) /* noexcept */ + { } + + bool + operator()(int l, int r) const + { return l < r; } +}; + +typedef std::set<int, not_noexcept_less> estype; + +static_assert( !std::is_nothrow_constructible<estype, estype&&, + const typename estype::allocator_type&>::value, + "except move constructor with allocator" ); |