Patchwork Fix libstdc++/55043 - issue with nesting unordered_map containing unique_ptr into vector

login
register
mail settings
Submitter Jonathan Wakely
Date Jan. 16, 2013, 9:25 a.m.
Message ID <CAH6eHdT2avC6qkM6Y7u4mAvj49TMc2-GiJ+eZxGHzJv8EttEJw@mail.gmail.com>
Download mbox | patch
Permalink /patch/212461/
State New
Headers show

Comments

Jonathan Wakely - Jan. 16, 2013, 9:25 a.m.
This fixes a regression caused by supporting the C++11 allocator
requirements in std::vector, and the fact that the unordered
containers don't have noexcept move constructors.  Fixed by
specializing is_copy_constructible for the unordered containers so
vector doesn't try to copy them when their element type is not
CopyInsertable into the container, and instead resorts to a move that
might throw.

        PR libstdc++/55043
        * include/std/unordered_map: Include alloc_traits.h
        * include/std/unordered_set: Likewise.
        * include/bits/alloc_traits.h: Define __is_copy_insertable.
        * include/bits/unordered_map.h: Use it.
        * include/bits/unordered_set.h: Likewise.
        * include/debug/unordered_map.h: Likewise.
        * include/debug/unordered_set.h: Likewise.
        * include/profile/unordered_map.h: Likewise.
        * include/profile/unordered_set.h: Likewise.
        * include/bits/hashtable.h: Fix comment typos.
        * testsuite/23_containers/unordered_map/55043.cc: New.
        * testsuite/23_containers/unordered_multimap/55043.cc: New.
        * testsuite/23_containers/unordered_multiset/55043.cc: New.
        * testsuite/23_containers/unordered_set/55043.cc: New.

Tested x86_64-linux, in normal, debug and profile modes.
Committed to trunk, to be committed to the 4.7 branch shortly.
commit e9c94b31c67f26e52c9927a4eedb39095efcd8be
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Wed Jan 16 09:19:11 2013 +0000

    	PR libstdc++/55043
    	* include/std/unordered_map: Include alloc_traits.h
    	* include/std/unordered_set: Likewise.
    	* include/bits/alloc_traits.h: Define __is_copy_insertable.
    	* include/bits/unordered_map.h: Use it.
    	* include/bits/unordered_set.h: Likewise.
    	* include/debug/unordered_map.h: Likewise.
    	* include/debug/unordered_set.h: Likewise.
    	* include/profile/unordered_map.h: Likewise.
    	* include/profile/unordered_set.h: Likewise.
    	* include/bits/hashtable.h: Fix comment typos.
    	* testsuite/23_containers/unordered_map/55043.cc: New.
    	* testsuite/23_containers/unordered_multimap/55043.cc: New.
    	* testsuite/23_containers/unordered_multiset/55043.cc: New.
    	* testsuite/23_containers/unordered_set/55043.cc: New.
Jonathan Wakely - Jan. 16, 2013, 9:44 a.m.
On 16 January 2013 09:25, Jonathan Wakely wrote:
> This fixes a regression caused by supporting the C++11 allocator
> requirements in std::vector, and the fact that the unordered
> containers don't have noexcept move constructors.  Fixed by
> specializing is_copy_constructible for the unordered containers so
> vector doesn't try to copy them when their element type is not
> CopyInsertable into the container, and instead resorts to a move that
> might throw.
>
>         PR libstdc++/55043
>         * include/std/unordered_map: Include alloc_traits.h
>         * include/std/unordered_set: Likewise.
>         * include/bits/alloc_traits.h: Define __is_copy_insertable.
>         * include/bits/unordered_map.h: Use it.
>         * include/bits/unordered_set.h: Likewise.
>         * include/debug/unordered_map.h: Likewise.
>         * include/debug/unordered_set.h: Likewise.
>         * include/profile/unordered_map.h: Likewise.
>         * include/profile/unordered_set.h: Likewise.
>         * include/bits/hashtable.h: Fix comment typos.
>         * testsuite/23_containers/unordered_map/55043.cc: New.
>         * testsuite/23_containers/unordered_multimap/55043.cc: New.
>         * testsuite/23_containers/unordered_multiset/55043.cc: New.
>         * testsuite/23_containers/unordered_set/55043.cc: New.
>
> Tested x86_64-linux, in normal, debug and profile modes.
> Committed to trunk, to be committed to the 4.7 branch shortly.

Daniel K has pointed out a problem with this fix, so I'll try to fix
it again, properly, this evening.

Patch

diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 9abadbb..c6259a1 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -1,6 +1,6 @@ 
 // Allocator traits -*- C++ -*-
 
-// Copyright (C) 2011-2012 Free Software Foundation, Inc.
+// Copyright (C) 2011-2013 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
@@ -39,6 +39,9 @@  namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+  template<typename _Tp>
+    class allocator;
+
   template<typename _Alloc, typename _Tp>
     class __alloctr_rebind_helper
     {
@@ -506,6 +509,41 @@  _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
       __do_alloc_on_swap(__one, __two, __pocs());
     }
 
+  template<typename _Alloc>
+    class __is_copy_insertable_impl
+    {
+      typedef allocator_traits<_Alloc> _Traits;
+
+      template<typename _Up, typename
+	       = decltype(_Traits::construct(std::declval<_Alloc&>(),
+					     std::declval<_Up*>(),
+					     std::declval<const _Up&>()))>
+	static true_type
+	_M_select(int);
+
+      template<typename _Up>
+	static false_type
+	_M_select(...);
+
+    public:
+	typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
+    };
+
+  template<typename _Alloc>
+    struct __is_copy_insertable
+    : __is_copy_insertable_impl<_Alloc>::type
+    { };
+
+  // std::allocator<_Tp> just requires CopyConstructible
+  template<typename _Tp>
+    struct __is_copy_insertable<allocator<_Tp>>
+    : is_copy_constructible<_Tp>
+    { };
+
+  template<typename _Container>
+    using __has_copy_insertable_val
+      = __is_copy_insertable<typename _Container::allocator_type>;
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index fab6c7c..49cb4db 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -370,7 +370,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _Hashtable(_Hashtable&&);
 
-      // Use delegating construtors.
+      // Use delegating constructors.
       explicit
       _Hashtable(size_type __n = 10,
 		 const _H1& __hf = _H1(),
@@ -914,7 +914,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_element_count(__ht._M_element_count),
       _M_rehash_policy(__ht._M_rehash_policy)
     {
-      // Update, if necessary, bucket pointing to before begin that hasn't move.
+      // Update, if necessary, bucket pointing to before begin that hasn't moved.
       if (_M_begin())
 	_M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
       __ht._M_rehash_policy = _RehashPolicy();
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 9fa0553..0235a99 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -1408,6 +1408,26 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     { return !(__x == __y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<_GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
+							_Pred, _Alloc>>
+    : __has_copy_insertable_val<_GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
+							      _Pred, _Alloc>>
+    { };
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<_GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
+							     _Pred, _Alloc>>
+    : __has_copy_insertable_val<_GLIBCXX_STD_C::unordered_multimap<_Key, _Tp,
+								   _Hash, _Pred,
+								   _Alloc>>
+    { };
+
 } // namespace std
 
 #endif /* _UNORDERED_MAP_H */
diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h
index c3eaa48..2ada63d 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -1,6 +1,6 @@ 
 // unordered_set implementation -*- C++ -*-
 
-// Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2010-2013 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
@@ -1291,6 +1291,23 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     { return !(__x == __y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
+
+  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
+    struct is_copy_constructible<_GLIBCXX_STD_C::unordered_set<_Key, _Hash,
+							       _Pred, _Alloc>>
+    : __has_copy_insertable_val<_GLIBCXX_STD_C::unordered_set<_Key, _Hash,
+							      _Pred, _Alloc>>
+    { };
+
+  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
+    struct
+    is_copy_constructible<_GLIBCXX_STD_C::unordered_multiset<_Key, _Hash,
+							     _Pred, _Alloc>>
+    : __has_copy_insertable_val<_GLIBCXX_STD_C::unordered_multiset<_Key, _Hash,
+								   _Pred,
+								   _Alloc>>
+    { };
+
 } // namespace std
 
 #endif /* _UNORDERED_SET_H */
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index 1c99ac8..115abb5 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -1,7 +1,6 @@ 
 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
 
-// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-// Free Software Foundation, Inc.
+// Copyright (C) 2003-2013 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
@@ -939,6 +938,30 @@  namespace __debug
     { return !(__x == __y); }
 
 } // namespace __debug
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<__debug::unordered_map<_Key, _Tp, _Hash, _Pred,
+						 _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_C::unordered_map<_Key, _Tp,
+							   _Hash, _Pred,
+							   _Alloc> >
+    { };
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<__debug::unordered_multimap<_Key, _Tp, _Hash, _Pred,
+						      _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp,
+								_Hash, _Pred,
+								_Alloc> >
+    { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
 #endif // C++11
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index d270ecc..895c943 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -1,7 +1,6 @@ 
 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
 
-// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-// Free Software Foundation, Inc.
+// Copyright (C) 2003-2013 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
@@ -921,6 +920,27 @@  namespace __debug
     { return !(__x == __y); }
 
 } // namespace __debug
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
+    struct
+    is_copy_constructible<__debug::unordered_set<_Key, _Hash, _Pred, _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_C::unordered_set<_Key,
+							   _Hash, _Pred,
+							   _Alloc> >
+    { };
+
+  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
+    struct
+    is_copy_constructible<__debug::unordered_multiset<_Key, _Hash, _Pred,
+						      _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_C::unordered_multiset<_Key,
+								_Hash, _Pred,
+								_Alloc> >
+    { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
 #endif // C++11
diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map
index e7b4c37..5ebcbf6 100644
--- a/libstdc++-v3/include/profile/unordered_map
+++ b/libstdc++-v3/include/profile/unordered_map
@@ -1,6 +1,6 @@ 
 // Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
 
-// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2009-2013 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
@@ -339,11 +339,25 @@  namespace __profile
 	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
     { return !(__x == __y); }
 
+} // namespace __profile
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<__profile::unordered_map<_Key, _Tp, _Hash,
+						   _Pred, _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_BASE >
+    { };
+_GLIBCXX_END_NAMESPACE_VERSION
+
 #undef _GLIBCXX_BASE
 #undef _GLIBCXX_STD_BASE
 #define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
 
+namespace __profile
+{
   /// Class std::unordered_multimap wrapper with performance instrumentation.
   template<typename _Key, typename _Tp,
 	   typename _Hash  = std::hash<_Key>,
@@ -609,6 +623,18 @@  namespace __profile
     { return !(__x == __y); }
 
 } // namespace __profile
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
+	   typename _Alloc>
+    struct
+    is_copy_constructible<__profile::unordered_multimap<_Key, _Tp, _Hash,
+							_Pred, _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_BASE >
+    { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
 #undef _GLIBCXX_BASE
diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set
index 357c073..ebe1c7d 100644
--- a/libstdc++-v3/include/profile/unordered_set
+++ b/libstdc++-v3/include/profile/unordered_set
@@ -1,6 +1,6 @@ 
 // Profiling unordered_set/unordered_multiset implementation -*- C++ -*-
 
-// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2009-2013 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
@@ -305,11 +305,23 @@  namespace __profile
 	       const unordered_set<_Key, _Hash, _Pred, _Alloc>& __y)
     { return !(__x == __y); }
 
+} // namespace __profile
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  template<typename _Key, typename _Hash, typename _Pred, typename _Alloc>
+    struct
+    is_copy_constructible<__profile::unordered_set<_Key, _Hash, _Pred, _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_BASE >
+    { };
+_GLIBCXX_END_NAMESPACE_VERSION
+
 #undef _GLIBCXX_BASE
 #undef _GLIBCXX_STD_BASE
 #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE
 #define _GLIBCXX_BASE unordered_multiset<_Value, _Hash, _Pred, _Alloc>
 
+namespace __profile
+{
   /** @brief Unordered_multiset wrapper with performance instrumentation.  */
   template<typename _Value,
        typename _Hash  = std::hash<_Value>,
@@ -568,6 +580,17 @@  namespace __profile
     { return !(__x == __y); }
 
 } // namespace __profile
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
+    struct
+    is_copy_constructible<__profile::unordered_multiset<_Value, _Hash,
+							_Pred, _Alloc>>
+    : is_copy_constructible< _GLIBCXX_STD_BASE >
+    { };
+
+_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
 #undef _GLIBCXX_BASE
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index 3514203..7c10173 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -1,6 +1,6 @@ 
 // <unordered_map> -*- C++ -*-
 
-// Copyright (C) 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2007-2013 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
@@ -41,6 +41,7 @@ 
 #include <tuple>
 #include <bits/stl_algobase.h>
 #include <bits/allocator.h>
+#include <bits/alloc_traits.h>
 #include <bits/stl_function.h> // equal_to, _Identity, _Select1st
 #include <bits/functional_hash.h>
 #include <bits/hashtable.h>
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index af6f624..cfe91ad 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -1,6 +1,6 @@ 
 // <unordered_set> -*- C++ -*-
 
-// Copyright (C) 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2007-2013 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
@@ -41,6 +41,7 @@ 
 #include <tuple>
 #include <bits/stl_algobase.h>
 #include <bits/allocator.h>
+#include <bits/alloc_traits.h>
 #include <bits/stl_function.h> // equal_to, _Identity, _Select1st
 #include <bits/functional_hash.h>
 #include <bits/hashtable.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc
new file mode 100644
index 0000000..10d36a0
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc
@@ -0,0 +1,69 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// libstdc++/55043
+
+#include <unordered_map>
+#include <vector>
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) = default;
+};
+
+using hash = std::hash<int>;
+using equal = std::equal_to<int>;
+
+template<typename Alloc>
+  using test_type = std::unordered_map<int, MoveOnly, hash, equal, Alloc>;
+
+void test01()
+{
+  typedef test_type<std::allocator<MoveOnly>> uim;
+  std::vector<uim> v;
+  v.emplace_back(uim());
+}
+
+// Unordered containers don't use allocator_traits yet so need full
+// Allocator interface, derive from std::allocator to get it.
+template<typename T, bool R>
+struct Alloc : std::allocator<T>
+{
+  template<typename U>
+    struct rebind { typedef Alloc<U, R> other; };
+
+  Alloc() = default;
+
+  template<typename U>
+    Alloc(const Alloc<U, R>&) { }
+
+  typedef typename std::conditional<R, T&&, const T&>::type arg_type;
+
+  void construct(T* p, arg_type) const
+  { new((void*)p) T(); }
+};
+
+// verify is_copy_constructible depends on allocator
+typedef test_type<Alloc<MoveOnly, true>> uim_rval;
+static_assert(std::is_copy_constructible<uim_rval>::value, "is not copyable");
+
+typedef test_type<Alloc<MoveOnly, false>> uim_lval;
+static_assert(std::is_copy_constructible<uim_lval>::value, "is copyable");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc
new file mode 100644
index 0000000..9ae912ef6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc
@@ -0,0 +1,69 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// libstdc++/55043
+
+#include <unordered_map>
+#include <vector>
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) = default;
+};
+
+using hash = std::hash<int>;
+using equal = std::equal_to<int>;
+
+template<typename Alloc>
+  using test_type = std::unordered_multimap<int, MoveOnly, hash, equal, Alloc>;
+
+void test01()
+{
+  typedef test_type<std::allocator<MoveOnly>> uim;
+  std::vector<uim> v;
+  v.emplace_back(uim());
+}
+
+// Unordered containers don't use allocator_traits yet so need full
+// Allocator interface, derive from std::allocator to get it.
+template<typename T, bool R>
+struct Alloc : std::allocator<T>
+{
+  template<typename U>
+    struct rebind { typedef Alloc<U, R> other; };
+
+  Alloc() = default;
+
+  template<typename U>
+    Alloc(const Alloc<U, R>&) { }
+
+  typedef typename std::conditional<R, T&&, const T&>::type arg_type;
+
+  void construct(T* p, arg_type) const
+  { new((void*)p) T(); }
+};
+
+// verify is_copy_constructible depends on allocator
+typedef test_type<Alloc<MoveOnly, true>> uim_rval;
+static_assert(std::is_copy_constructible<uim_rval>::value, "is not copyable");
+
+typedef test_type<Alloc<MoveOnly, false>> uim_lval;
+static_assert(std::is_copy_constructible<uim_lval>::value, "is copyable");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc
new file mode 100644
index 0000000..ebb8cb8
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc
@@ -0,0 +1,73 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// libstdc++/55043
+
+#include <unordered_set>
+#include <vector>
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) = default;
+};
+
+struct equal {
+  bool operator()(const MoveOnly&, const MoveOnly) const { return true; }
+};
+struct hash {
+  size_t operator()(const MoveOnly&) const { return 0; }
+};
+
+template<typename Alloc>
+  using test_type = std::unordered_multiset<MoveOnly, hash, equal, Alloc>;
+
+void test01()
+{
+  typedef test_type<std::allocator<MoveOnly>> uim;
+  std::vector<uim> v;
+  v.emplace_back(uim());
+}
+
+// Unordered containers don't use allocator_traits yet so need full
+// Allocator interface, derive from std::allocator to get it.
+template<typename T, bool R>
+struct Alloc : std::allocator<T>
+{
+  template<typename U>
+    struct rebind { typedef Alloc<U, R> other; };
+
+  Alloc() = default;
+
+  template<typename U>
+    Alloc(const Alloc<U, R>&) { }
+
+  typedef typename std::conditional<R, T&&, const T&>::type arg_type;
+
+  void construct(T* p, arg_type) const
+  { new((void*)p) T(); }
+};
+
+// verify is_copy_constructible depends on allocator
+typedef test_type<Alloc<MoveOnly, true>> uim_rval;
+static_assert(std::is_copy_constructible<uim_rval>::value, "is not copyable");
+
+typedef test_type<Alloc<MoveOnly, false>> uim_lval;
+static_assert(std::is_copy_constructible<uim_lval>::value, "is copyable");
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc
new file mode 100644
index 0000000..3b0b973
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc
@@ -0,0 +1,73 @@ 
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// libstdc++/55043
+
+#include <unordered_set>
+#include <vector>
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) = default;
+};
+
+struct equal {
+  bool operator()(const MoveOnly&, const MoveOnly) const { return true; }
+};
+struct hash {
+  size_t operator()(const MoveOnly&) const { return 0; }
+};
+
+template<typename Alloc>
+  using test_type = std::unordered_set<MoveOnly, hash, equal, Alloc>;
+
+void test01()
+{
+  typedef test_type<std::allocator<MoveOnly>> uim;
+  std::vector<uim> v;
+  v.emplace_back(uim());
+}
+
+// Unordered containers don't use allocator_traits yet so need full
+// Allocator interface, derive from std::allocator to get it.
+template<typename T, bool R>
+struct Alloc : std::allocator<T>
+{
+  template<typename U>
+    struct rebind { typedef Alloc<U, R> other; };
+
+  Alloc() = default;
+
+  template<typename U>
+    Alloc(const Alloc<U, R>&) { }
+
+  typedef typename std::conditional<R, T&&, const T&>::type arg_type;
+
+  void construct(T* p, arg_type) const
+  { new((void*)p) T(); }
+};
+
+// verify is_copy_constructible depends on allocator
+typedef test_type<Alloc<MoveOnly, true>> uim_rval;
+static_assert(std::is_copy_constructible<uim_rval>::value, "is not copyable");
+
+typedef test_type<Alloc<MoveOnly, false>> uim_lval;
+static_assert(std::is_copy_constructible<uim_lval>::value, "is copyable");