[Hashtable,3/6] Fix noexcept qualifications
diff mbox series

Message ID d297becd-86ab-650a-49c5-ecef118e0264@gmail.com
State New
Headers show
Series
  • Untitled series #143415
Related show

Commit Message

François Dumont Nov. 17, 2019, 8:59 p.m. UTC
This patch adds noexcept qualification on allocator aware constructors 
and fix the one on the default constructor.

     * include/bits/hashtable.h
     (_Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a, true_type)):
     Add noexcept qualification.
     (_Hashtable(_Hashtable&&)): Fix noexcept qualification.
     (_Hashtable(_Hashtable&&, const allocator_type&)): Add noexcept
     qualification.
     * include/bits/unordered_map.h
     (unordered_map(unordered_map&&, const allocator_type&)): Add noexcept
     qualification.
     (unordered_multimap(unordered_multimap&&, const allocator_type&)): Add
     noexcept qualification.
     * include/bits/unordered_set.h
     (unordered_set(unordered_set&&, const allocator_type&)): Add noexcept
     qualification.
     (unordered_multiset(unordered_multiset&&, const allocator_type&)): Add
     noexcept qualification.
     * testsuite/23_containers/unordered_map/allocator/default_init.cc:
     New.
     * testsuite/23_containers/unordered_map/cons/
     noexcept_default_construct.cc: New.
     * testsuite/23_containers/unordered_map/cons/
     noexcept_move_construct.cc: New.
     * testsuite/23_containers/unordered_map/modifiers/move_assign.cc:
     New.
     * testsuite/23_containers/unordered_multimap/cons/
     noexcept_default_construct.cc: New.
     * testsuite/23_containers/unordered_multimap/cons/
     noexcept_move_construct.cc: New.
     * testsuite/23_containers/unordered_multiset/cons/
     noexcept_default_construct.cc: New.
     * testsuite/23_containers/unordered_multiset/cons/
     noexcept_move_construct.cc: New.
     * testsuite/23_containers/unordered_set/allocator/default_init.cc: New.
     * testsuite/23_containers/unordered_set/cons/
     noexcept_default_construct.cc: New.
     * 
testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc:
     New.

Tested under Linux x86_64.

François

Patch
diff mbox series

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 5f785d4904d..ad07a36eb83 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -463,6 +463,35 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__hashtable_alloc(__node_alloc_type(__a))
       { }
 
+      _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a, true_type)
+	noexcept(std::is_nothrow_copy_constructible<_H1>::value &&
+		 std::is_nothrow_copy_constructible<_Equal>::value)
+      : __hashtable_base(__ht),
+	__map_base(__ht),
+	__rehash_base(__ht),
+	__hashtable_alloc(std::move(__a)),
+	_M_buckets(__ht._M_buckets),
+	_M_bucket_count(__ht._M_bucket_count),
+	_M_before_begin(__ht._M_before_begin._M_nxt),
+	_M_element_count(__ht._M_element_count),
+	_M_rehash_policy(__ht._M_rehash_policy)
+      {
+	// Update, if necessary, buckets if __ht is using its single bucket.
+	if (__ht._M_uses_single_bucket())
+	  {
+	    _M_buckets = &_M_single_bucket;
+	    _M_single_bucket = __ht._M_single_bucket;
+	  }
+
+	// Fix bucket containing the _M_before_begin pointer that can't be
+	// moved.
+	_M_update_bbegin();
+
+	__ht._M_reset();
+      }
+
+      _Hashtable(_Hashtable&&, __node_alloc_type&&, false_type);
+
       template<typename _InputIterator>
 	_Hashtable(_InputIterator __first, _InputIterator __last,
 		   size_type __bkt_count_hint,
@@ -489,11 +518,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _Hashtable(const _Hashtable&);
 
-      _Hashtable(_Hashtable&&) noexcept;
+      _Hashtable(_Hashtable&& __ht)
+	noexcept( noexcept(
+	  _Hashtable(std::declval<_Hashtable&&>(),
+	    std::declval<__node_alloc_type&&>(), std::declval<true_type>())) )
+      : _Hashtable(std::move(__ht), std::move(__ht._M_node_allocator()),
+		   true_type{})
+      { }
 
       _Hashtable(const _Hashtable&, const allocator_type&);
 
-      _Hashtable(_Hashtable&&, const allocator_type&);
+      _Hashtable(_Hashtable&& __ht, const allocator_type& __a)
+	noexcept( noexcept(
+	  _Hashtable(std::declval<_Hashtable&&>(),
+	    std::declval<__node_alloc_type&&>(),
+	    std::declval<typename __node_alloc_traits::is_always_equal>())) )
+      : _Hashtable(std::move(__ht), __node_alloc_type(__a),
+		   typename __node_alloc_traits::is_always_equal{})
+      { }
 
       // Use delegating constructors.
       template<typename _InputIterator>
@@ -1368,36 +1410,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_assign(__ht, __alloc_node_gen);
     }
 
-  template<typename _Key, typename _Value,
-	   typename _Alloc, typename _ExtractKey, typename _Equal,
-	   typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
-	   typename _Traits>
-    _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
-	       _H1, _H2, _Hash, _RehashPolicy, _Traits>::
-    _Hashtable(_Hashtable&& __ht) noexcept
-    : __hashtable_base(__ht),
-      __map_base(__ht),
-      __rehash_base(__ht),
-      __hashtable_alloc(std::move(__ht._M_base_alloc())),
-      _M_buckets(__ht._M_buckets),
-      _M_bucket_count(__ht._M_bucket_count),
-      _M_before_begin(__ht._M_before_begin._M_nxt),
-      _M_element_count(__ht._M_element_count),
-      _M_rehash_policy(__ht._M_rehash_policy)
-    {
-      // Update, if necessary, buckets if __ht is using its single bucket.
-      if (__ht._M_uses_single_bucket())
-	{
-	  _M_buckets = &_M_single_bucket;
-	  _M_single_bucket = __ht._M_single_bucket;
-	}
-
-      // Fix bucket containing the _M_before_begin pointer that can't be moved.
-      _M_update_bbegin();
-
-      __ht._M_reset();
-    }
-
   template<typename _Key, typename _Value,
 	   typename _Alloc, typename _ExtractKey, typename _Equal,
 	   typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
@@ -1424,11 +1436,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	   typename _Traits>
     _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
 	       _H1, _H2, _Hash, _RehashPolicy, _Traits>::
-    _Hashtable(_Hashtable&& __ht, const allocator_type& __a)
+    _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a, false_type)
     : __hashtable_base(__ht),
       __map_base(__ht),
       __rehash_base(__ht),
-      __hashtable_alloc(__node_alloc_type(__a)),
+      __hashtable_alloc(std::move(__a)),
       _M_buckets(nullptr),
       _M_bucket_count(__ht._M_bucket_count),
       _M_element_count(__ht._M_element_count),
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 49c175a90be..5131e02e8aa 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -209,6 +209,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       unordered_map(unordered_map&& __umap,
 		    const allocator_type& __a)
+	noexcept( noexcept(_Hashtable(declval<_Hashtable&&>(), __a)) )
       : _M_h(std::move(__umap._M_h), __a)
       { }
 
@@ -1356,6 +1357,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       unordered_multimap(unordered_multimap&& __ummap,
 			 const allocator_type& __a)
+	noexcept( noexcept(_Hashtable(declval<_Hashtable&&>(), __a)) )
       : _M_h(std::move(__ummap._M_h), __a)
       { }
 
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index 855579ee623..7154ec843db 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -203,6 +203,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       unordered_set(unordered_set&& __uset,
 		    const allocator_type& __a)
+	noexcept( noexcept(_Hashtable(declval<_Hashtable&&>(), __a)) )
       : _M_h(std::move(__uset._M_h), __a)
       { }
 
@@ -1044,6 +1045,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        */
       unordered_multiset(unordered_multiset&& __umset,
 			 const allocator_type& __a)
+	noexcept( noexcept(_Hashtable(declval<_Hashtable&&>(), __a)) )
       : _M_h(std::move(__umset._M_h), __a)
       { }
 
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/allocator/default_init.cc
new file mode 100644
index 00000000000..8c3103c2614
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/allocator/default_init.cc
@@ -0,0 +1,69 @@ 
+// Copyright (C) 2019 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 <unordered_map>
+#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<std::pair<const T, T>> alloc_type;
+  typedef std::unordered_map<T, T, std::hash<T>, std::equal_to<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<std::pair<const T, T>> alloc_type;
+  typedef std::unordered_map<T, T, std::hash<T>, std::equal_to<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;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_default_construct.cc
new file mode 100644
index 00000000000..549d0a8d96a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_default_construct.cc
@@ -0,0 +1,68 @@ 
+// Copyright (C) 2019 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 compile { target c++11 } }
+
+#include <unordered_map>
+
+using type1 = std::unordered_map<int, int>;
+
+static_assert(std::is_nothrow_default_constructible<type1>::value,
+	      "noexcept default constructible");
+
+struct not_noexcept_dflt_cons_hash
+{
+  not_noexcept_dflt_cons_hash() /* noexcept */;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_map<int, int, not_noexcept_dflt_cons_hash>;
+
+static_assert( !std::is_nothrow_default_constructible<type2>::value,
+	       "not noexcept default constructible");
+
+struct not_noexcept_dflt_cons_equal_to
+{
+  not_noexcept_dflt_cons_equal_to() /* noexcept */;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_map<int, int, std::hash<int>,
+				  not_noexcept_dflt_cons_equal_to>;
+
+static_assert( !std::is_nothrow_default_constructible<type3>::value,
+	       "not noexcept default constructible");
+
+template<typename _Tp>
+  struct not_noexcept_dflt_cons_alloc : std::allocator<_Tp>
+  {
+    not_noexcept_dflt_cons_alloc() /* noexcept */;
+
+    template<typename _Tp1>
+      struct rebind
+      { typedef not_noexcept_dflt_cons_alloc<_Tp1> other; };
+  };
+
+using type4 = std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,
+			not_noexcept_dflt_cons_alloc<std::pair<const int, int>>>;
+
+static_assert(!std::is_nothrow_default_constructible<type4>::value,
+	      "not noexcept default constructible");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc
new file mode 100644
index 00000000000..1929b6ac66d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/noexcept_move_construct.cc
@@ -0,0 +1,65 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2019 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/>.
+
+#include <unordered_map>
+
+using type1 = std::unordered_map<int, int>;
+
+static_assert( std::is_nothrow_move_constructible<type1>::value,
+	       "noexcept move constructor" );
+static_assert( std::is_nothrow_constructible<type1,
+	       type1&&, const typename type1::allocator_type&>::value,
+	       "noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_hash
+{
+  not_noexcept_copy_cons_hash() noexcept;
+  not_noexcept_copy_cons_hash(const not_noexcept_copy_cons_hash&) /* noexcept */;
+  not_noexcept_copy_cons_hash(not_noexcept_copy_cons_hash&&) noexcept;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_map<int, int, not_noexcept_copy_cons_hash>;
+
+static_assert( !std::is_nothrow_move_constructible<type2>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type2, type2&&,
+	       const typename type2::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_equal_to
+{
+  not_noexcept_copy_cons_equal_to() noexcept;
+  not_noexcept_copy_cons_equal_to(const not_noexcept_copy_cons_equal_to&) /* noexcept */;
+  not_noexcept_copy_cons_equal_to(not_noexcept_copy_cons_equal_to&&) noexcept;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_map<int, int, std::hash<int>,
+				  not_noexcept_copy_cons_equal_to>;
+
+static_assert( !std::is_nothrow_move_constructible<type3>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type3, type3&&,
+	       const typename type3::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/move_assign.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/move_assign.cc
new file mode 100644
index 00000000000..15d8e8011e6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/move_assign.cc
@@ -0,0 +1,81 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2019 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/>.
+
+#include <utility>
+#include <unordered_map>
+#include <vector>
+
+#include <testsuite_hooks.h>
+#include <testsuite_counter_type.h>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+  using namespace std;
+  using __gnu_test::counter_type;
+
+  std::vector<pair<int, counter_type>> insts { { 0, 0 }, { 1, 1 }, { 2, 2 } };
+  typedef unordered_map<int, counter_type> Map;
+  Map m;
+
+  counter_type::reset();
+
+  m.insert(make_move_iterator(insts.begin()), make_move_iterator(insts.end()));
+
+  VERIFY( m.size() == 3 );
+  VERIFY( counter_type::default_count == 0 );
+  VERIFY( counter_type::copy_count == 0 );
+  VERIFY( counter_type::move_count == 3 );
+}
+
+void test02()
+{
+  using namespace std;
+  using __gnu_test::counter_type;
+  using __gnu_test::propagating_allocator;
+
+  typedef propagating_allocator<pair<const int, counter_type>, false> Alloc;
+  typedef unordered_map<int, counter_type,
+			hash<int>, equal_to<int>,
+			Alloc> Map;
+
+  Alloc a1(1);
+  Map m1(3, a1);
+  m1 = { { 0, 0 }, { 1, 1 }, { 2, 2 } };
+  Alloc a2(2);
+  Map m2(3, a2);
+  m2 = { { 3, 0 }, { 4, 1 }, { 5, 2 } };
+
+  counter_type::reset();
+
+  m2 = move(m1);
+
+  VERIFY( m1.empty() );
+  VERIFY( m2.size() == 3 );
+  VERIFY( counter_type::default_count == 0 );
+  VERIFY( counter_type::copy_count == 0 );
+  VERIFY( counter_type::move_count == 3 );
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_default_construct.cc
new file mode 100644
index 00000000000..bda8c54dc4c
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_default_construct.cc
@@ -0,0 +1,68 @@ 
+// Copyright (C) 2019 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 compile { target c++11 } }
+
+#include <unordered_map>
+
+using type1 = std::unordered_multimap<int, int>;
+
+static_assert(std::is_nothrow_default_constructible<type1>::value,
+	      "noexcept default constructible");
+
+struct not_noexcept_dflt_cons_hash
+{
+  not_noexcept_dflt_cons_hash() /* noexcept */;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_multimap<int, int, not_noexcept_dflt_cons_hash>;
+
+static_assert( !std::is_nothrow_default_constructible<type2>::value,
+	       "not noexcept default constructible");
+
+struct not_noexcept_dflt_cons_equal_to
+{
+  not_noexcept_dflt_cons_equal_to() /* noexcept */;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_multimap<int, int, std::hash<int>,
+				       not_noexcept_dflt_cons_equal_to>;
+
+static_assert( !std::is_nothrow_default_constructible<type3>::value,
+	       "not noexcept default constructible");
+
+template<typename _Tp>
+  struct not_noexcept_dflt_cons_alloc : std::allocator<_Tp>
+  {
+    not_noexcept_dflt_cons_alloc() /* noexcept */;
+
+    template<typename _Tp1>
+      struct rebind
+      { typedef not_noexcept_dflt_cons_alloc<_Tp1> other; };
+  };
+
+using type4 = std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>,
+				       not_noexcept_dflt_cons_alloc<std::pair<const int, int>>>;
+
+static_assert(!std::is_nothrow_default_constructible<type4>::value,
+	      "not noexcept default constructible");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc
new file mode 100644
index 00000000000..f3b1b908f2f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/noexcept_move_construct.cc
@@ -0,0 +1,65 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2019 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/>.
+
+#include <unordered_map>
+
+using type1 = std::unordered_multimap<int, int>;
+
+static_assert( std::is_nothrow_move_constructible<type1>::value,
+	       "noexcept move constructor" );
+static_assert( std::is_nothrow_constructible<type1,
+	       type1&&, const typename type1::allocator_type&>::value,
+	       "noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_hash
+{
+  not_noexcept_copy_cons_hash() noexcept;
+  not_noexcept_copy_cons_hash(const not_noexcept_copy_cons_hash&) /* noexcept */;
+  not_noexcept_copy_cons_hash(not_noexcept_copy_cons_hash&&) noexcept;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_multimap<int, int, not_noexcept_copy_cons_hash>;
+
+static_assert( !std::is_nothrow_move_constructible<type2>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type2, type2&&,
+	       const typename type2::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_equal_to
+{
+  not_noexcept_copy_cons_equal_to() noexcept;
+  not_noexcept_copy_cons_equal_to(const not_noexcept_copy_cons_equal_to&) /* noexcept */;
+  not_noexcept_copy_cons_equal_to(not_noexcept_copy_cons_equal_to&&) noexcept;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_multimap<int, int, std::hash<int>,
+				       not_noexcept_copy_cons_equal_to>;
+
+static_assert( !std::is_nothrow_move_constructible<type3>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type3, type3&&,
+	       const typename type3::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_default_construct.cc
new file mode 100644
index 00000000000..5b7ff7ce655
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_default_construct.cc
@@ -0,0 +1,68 @@ 
+// Copyright (C) 2019 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 compile { target c++11 } }
+
+#include <unordered_set>
+
+using type1 = std::unordered_multiset<int>;
+
+static_assert(std::is_nothrow_default_constructible<type1>::value,
+	      "noexcept default constructible");
+
+struct not_noexcept_dflt_cons_hash
+{
+  not_noexcept_dflt_cons_hash() /* noexcept */;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_multiset<int, not_noexcept_dflt_cons_hash>;
+
+static_assert( !std::is_nothrow_default_constructible<type2>::value,
+	       "not noexcept default constructible");
+
+struct not_noexcept_dflt_cons_equal_to
+{
+  not_noexcept_dflt_cons_equal_to() /* noexcept */;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_multiset<int, std::hash<int>,
+				      not_noexcept_dflt_cons_equal_to>;
+
+static_assert( !std::is_nothrow_default_constructible<type3>::value,
+	       "not noexcept default constructible");
+
+template<typename _Tp>
+  struct not_noexcept_dflt_cons_alloc : std::allocator<_Tp>
+  {
+    not_noexcept_dflt_cons_alloc() /* noexcept */;
+
+    template<typename _Tp1>
+      struct rebind
+      { typedef not_noexcept_dflt_cons_alloc<_Tp1> other; };
+  };
+
+using type4 = std::unordered_multiset<int, std::hash<int>, std::equal_to<int>,
+				      not_noexcept_dflt_cons_alloc<std::pair<const int, int>>>;
+
+static_assert(!std::is_nothrow_default_constructible<type4>::value,
+	      "not noexcept default constructible");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc
new file mode 100644
index 00000000000..a03f7f8d959
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/noexcept_move_construct.cc
@@ -0,0 +1,65 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2019 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/>.
+
+#include <unordered_set>
+
+using type1 = std::unordered_multiset<int>;
+
+static_assert( std::is_nothrow_move_constructible<type1>::value,
+	       "noexcept move constructor" );
+static_assert( std::is_nothrow_constructible<type1,
+	       type1&&, const typename type1::allocator_type&>::value,
+	       "noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_hash
+{
+  not_noexcept_copy_cons_hash() noexcept;
+  not_noexcept_copy_cons_hash(const not_noexcept_copy_cons_hash&) /* noexcept */;
+  not_noexcept_copy_cons_hash(not_noexcept_copy_cons_hash&&) noexcept;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_multiset<int, not_noexcept_copy_cons_hash>;
+
+static_assert( !std::is_nothrow_move_constructible<type2>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type2, type2&&,
+	       const typename type2::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_equal_to
+{
+  not_noexcept_copy_cons_equal_to() noexcept;
+  not_noexcept_copy_cons_equal_to(const not_noexcept_copy_cons_equal_to&) /* noexcept */;
+  not_noexcept_copy_cons_equal_to(not_noexcept_copy_cons_equal_to&&) noexcept;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_multiset<int, std::hash<int>,
+				      not_noexcept_copy_cons_equal_to>;
+
+static_assert( !std::is_nothrow_move_constructible<type3>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type3, type3&&,
+	       const typename type3::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/default_init.cc
new file mode 100644
index 00000000000..51fa5e7094b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/default_init.cc
@@ -0,0 +1,69 @@ 
+// Copyright (C) 2019 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 <unordered_set>
+#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::unordered_set<T, std::hash<T>, std::equal_to<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::unordered_set<T, std::hash<T>, std::equal_to<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;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_default_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_default_construct.cc
new file mode 100644
index 00000000000..2966703461f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_default_construct.cc
@@ -0,0 +1,68 @@ 
+// Copyright (C) 2019 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 compile { target c++11 } }
+
+#include <unordered_set>
+
+using type1 = std::unordered_set<int>;
+
+static_assert(std::is_nothrow_default_constructible<type1>::value,
+	      "noexcept default constructible");
+
+struct not_noexcept_dflt_cons_hash
+{
+  not_noexcept_dflt_cons_hash() /* noexcept */;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_set<int, not_noexcept_dflt_cons_hash>;
+
+static_assert( !std::is_nothrow_default_constructible<type2>::value,
+	       "not noexcept default constructible");
+
+struct not_noexcept_dflt_cons_equal_to
+{
+  not_noexcept_dflt_cons_equal_to() /* noexcept */;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_set<int, std::hash<int>,
+				  not_noexcept_dflt_cons_equal_to>;
+
+static_assert( !std::is_nothrow_default_constructible<type3>::value,
+	       "not noexcept default constructible");
+
+template<typename _Tp>
+  struct not_noexcept_dflt_cons_alloc : std::allocator<_Tp>
+  {
+    not_noexcept_dflt_cons_alloc() /* noexcept */;
+
+    template<typename _Tp1>
+      struct rebind
+      { typedef not_noexcept_dflt_cons_alloc<_Tp1> other; };
+  };
+
+using type4 = std::unordered_set<int, std::hash<int>, std::equal_to<int>,
+				  not_noexcept_dflt_cons_alloc<std::pair<const int, int>>>;
+
+static_assert(!std::is_nothrow_default_constructible<type4>::value,
+	      "not noexcept default constructible");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc
new file mode 100644
index 00000000000..2470079bc90
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/noexcept_move_construct.cc
@@ -0,0 +1,65 @@ 
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2019 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/>.
+
+#include <unordered_set>
+
+using type1 = std::unordered_set<int>;
+
+static_assert( std::is_nothrow_move_constructible<type1>::value,
+	       "noexcept move constructor" );
+static_assert( std::is_nothrow_constructible<type1,
+	       type1&&, const typename type1::allocator_type&>::value,
+	       "noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_hash
+{
+  not_noexcept_copy_cons_hash() noexcept;
+  not_noexcept_copy_cons_hash(const not_noexcept_copy_cons_hash&) /* noexcept */;
+  not_noexcept_copy_cons_hash(not_noexcept_copy_cons_hash&&) noexcept;
+
+  std::size_t
+  operator()(int) const noexcept;
+};
+
+using type2 = std::unordered_set<int, not_noexcept_copy_cons_hash>;
+
+static_assert( !std::is_nothrow_move_constructible<type2>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type2, type2&&,
+	       const typename type2::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );
+
+struct not_noexcept_copy_cons_equal_to
+{
+  not_noexcept_copy_cons_equal_to() noexcept;
+  not_noexcept_copy_cons_equal_to(const not_noexcept_copy_cons_equal_to&) /* noexcept */;
+  not_noexcept_copy_cons_equal_to(not_noexcept_copy_cons_equal_to&&) noexcept;
+
+  bool
+  operator()(int, int) const noexcept;
+};
+
+using type3 = std::unordered_set<int, std::hash<int>,
+				  not_noexcept_copy_cons_equal_to>;
+
+static_assert( !std::is_nothrow_move_constructible<type3>::value,
+	       "noexcept move constructor" );
+static_assert( !std::is_nothrow_constructible<type3, type3&&,
+	       const typename type3::allocator_type&>::value,
+	       "not noexcept move constructor with allocator" );