https://gcc.gnu.org/g:c832cf1c1d114aed70c2f84566cf4d63de0a56d0 commit c832cf1c1d114aed70c2f84566cf4d63de0a56d0 Author: François Dumont Date: Fri Jul 3 08:13:19 2020 +0200 libstdc++: Fix [multi]map/[multi]set move constructors noexcept qualification Container move constructors shall not consider their allocator move constructor qualification. libstdc++-v3/ChangeLog: * include/bits/stl_tree.h (_Rb_tree_impl(_Rb_tree_impl&&)): Add noexcept qualification based only on _Compare one. * testsuite/23_containers/map/cons/noexcept_move_construct.cc: Add static asserts. * testsuite/23_containers/multimap/cons/noexcept_move_construct.cc: Likewise. * testsuite/23_containers/multiset/cons/noexcept_move_construct.cc: Likewise. * testsuite/23_containers/set/cons/noexcept_move_construct.cc: Likewise. Diff: --- libstdc++-v3/include/bits/stl_tree.h | 4 ++- .../map/cons/noexcept_move_construct.cc | 32 +++++++++++++++++++++- .../multimap/cons/noexcept_move_construct.cc | 32 +++++++++++++++++++++- .../multiset/cons/noexcept_move_construct.cc | 32 +++++++++++++++++++++- .../set/cons/noexcept_move_construct.cc | 32 +++++++++++++++++++++- 5 files changed, 127 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 5be15afa257..21b72cebf2e 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -698,7 +698,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Node_allocator(__a), _Base_key_compare(__comp) { } #else - _Rb_tree_impl(_Rb_tree_impl&&) = default; + _Rb_tree_impl(_Rb_tree_impl&&) + noexcept( is_nothrow_move_constructible<_Base_key_compare>::value ) + = default; explicit _Rb_tree_impl(_Node_allocator&& __a) 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 119b199ddff..25d1c9b5aca 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 @@ -29,6 +29,33 @@ static_assert( std::is_nothrow_constructible::value, "noexcept move constructor with allocator" ); +template + class not_noexcept_move_constructor_alloc : public std::allocator + { + public: + not_noexcept_move_constructor_alloc() noexcept { } + + not_noexcept_move_constructor_alloc( + const not_noexcept_move_constructor_alloc& x) noexcept + : std::allocator(x) + { } + + not_noexcept_move_constructor_alloc( + not_noexcept_move_constructor_alloc&& x) noexcept(false) + : std::allocator(std::move(x)) + { } + + template + struct rebind + { typedef not_noexcept_move_constructor_alloc<_Tp1> other; }; + }; + +typedef std::map, + not_noexcept_move_constructor_alloc>> amtype; + +static_assert( std::is_nothrow_move_constructible::value, + "noexcept move constructor with not noexcept alloc" ); + struct not_noexcept_less { not_noexcept_less() = default; @@ -42,6 +69,9 @@ struct not_noexcept_less typedef std::map emtype; +static_assert( !std::is_nothrow_move_constructible::value, + "not noexcept move constructor with not noexcept less" ); + static_assert( !std::is_nothrow_constructible::value, - "except move constructor with allocator" ); + "not noexcept move constructor with allocator" ); 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 44c3015a282..af545ae297c 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 @@ -29,6 +29,33 @@ static_assert( std::is_nothrow_constructible::value, "noexcept move constructor with allocator" ); +template + class not_noexcept_move_constructor_alloc : public std::allocator + { + public: + not_noexcept_move_constructor_alloc() noexcept { } + + not_noexcept_move_constructor_alloc( + const not_noexcept_move_constructor_alloc& x) noexcept + : std::allocator(x) + { } + + not_noexcept_move_constructor_alloc( + not_noexcept_move_constructor_alloc&& x) noexcept(false) + : std::allocator(std::move(x)) + { } + + template + struct rebind + { typedef not_noexcept_move_constructor_alloc<_Tp1> other; }; + }; + +typedef std::multimap, + not_noexcept_move_constructor_alloc>> ammtype; + +static_assert( std::is_nothrow_move_constructible::value, + "noexcept move constructor with not noexcept alloc" ); + struct not_noexcept_less { not_noexcept_less() = default; @@ -42,6 +69,9 @@ struct not_noexcept_less typedef std::multimap emmtype; +static_assert( !std::is_nothrow_move_constructible::value, + "not noexcept move constructor with not noexcept less" ); + static_assert( !std::is_nothrow_constructible::value, - "except move constructor with allocator" ); + "not noexcept move constructor with allocator" ); 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 225b2206ad4..ed4d9128606 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 @@ -29,6 +29,33 @@ static_assert( std::is_nothrow_constructible::value, "noexcept move constructor with allocator" ); +template + class not_noexcept_move_constructor_alloc : public std::allocator + { + public: + not_noexcept_move_constructor_alloc() noexcept { } + + not_noexcept_move_constructor_alloc( + const not_noexcept_move_constructor_alloc& x) noexcept + : std::allocator(x) + { } + + not_noexcept_move_constructor_alloc( + not_noexcept_move_constructor_alloc&& x) noexcept(false) + : std::allocator(std::move(x)) + { } + + template + struct rebind + { typedef not_noexcept_move_constructor_alloc<_Tp1> other; }; + }; + +typedef std::multiset, + not_noexcept_move_constructor_alloc> amstype; + +static_assert( std::is_nothrow_move_constructible::value, + "noexcept move constructor with not noexcept alloc" ); + struct not_noexcept_less { not_noexcept_less() = default; @@ -42,6 +69,9 @@ struct not_noexcept_less typedef std::multiset emstype; +static_assert( !std::is_nothrow_move_constructible::value, + "not noexcept move constructor with not noexcept less" ); + static_assert( !std::is_nothrow_constructible::value, - "except move constructor with allocator" ); + "not noexcept move constructor with allocator" ); 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 acd84a8fcd0..dc96236a668 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 @@ -29,6 +29,33 @@ static_assert( std::is_nothrow_constructible::value, "noexcept move constructor with allocator" ); +template + class not_noexcept_move_constructor_alloc : public std::allocator + { + public: + not_noexcept_move_constructor_alloc() noexcept { } + + not_noexcept_move_constructor_alloc( + const not_noexcept_move_constructor_alloc& x) noexcept + : std::allocator(x) + { } + + not_noexcept_move_constructor_alloc( + not_noexcept_move_constructor_alloc&& x) noexcept(false) + : std::allocator(std::move(x)) + { } + + template + struct rebind + { typedef not_noexcept_move_constructor_alloc<_Tp1> other; }; + }; + +typedef std::set, + not_noexcept_move_constructor_alloc> astype; + +static_assert( std::is_nothrow_move_constructible::value, + "noexcept move constructor with not noexcept alloc" ); + struct not_noexcept_less { not_noexcept_less() = default; @@ -42,6 +69,9 @@ struct not_noexcept_less typedef std::set estype; +static_assert( !std::is_nothrow_move_constructible::value, + "not noexcept move constructor with not noexcept less" ); + static_assert( !std::is_nothrow_constructible::value, - "except move constructor with allocator" ); + "not noexcept move constructor with allocator" );