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, 11:57 p.m.
Message ID <CAH6eHdSWYCyxmzwYDv5HHxGX7ZAujA_3Y8o2_nWY35hc5L2t7Q@mail.gmail.com>
Download mbox | patch
Permalink /patch/213101/
State New
Headers show

Comments

Jonathan Wakely - Jan. 16, 2013, 11:57 p.m.
Here's another attempt to fix this regression, I hope this time it
doesn't cause more problems than it solves.

Instead of specializing is_copy_constructible for the unordered
containers this causes their copy constructors to be deleted if the
value_type is not CopyInsertable into the container.  This makes
is_copy_constructible naturally give the right result, and so
__move_if_noexcept does the right thing and the testcase in the PR
passes. Yay.

As Daniel pointed out in the PR comments, the unfortunate side effect
of this approach is that we can no longer support instantiating
unordered containers with incomplete types. That's undefined
behaviour, but was allowed as QoI.  Conformance trumps QoI, I'm
afraid.  If someday we have noexcept move constructors for the
unordered containers we could allow incomplete types again.

        PR libstdc++/55043 (again)
        * include/bits/alloc_traits.h (allocator_traits::construct): Disable
        unless construction would be well-formed.
        (__allow_copy_cons, __check_copy_constructible): Define.
        * include/bits/unordered_map.h (__check_copy_constructible): Use as
        base class so copy constructor will be deleted if appropriate.
        (is_copy_constructible): Remove specialization.
        * include/bits/unordered_set.h: Likewise.
        * include/debug/unordered_map.h: Undo previous commit. Default copy
        and move constructors.
        * include/debug/unordered_set.h: Likewise.
        * include/profile/unordered_map.h: Undo previous commit.
        * include/profile/unordered_set.h: Likewise.
        * testsuite/23_containers/unordered_map/55043.cc: Fix test.
        * testsuite/23_containers/unordered_multimap/55043.cc: Likewise.
        * testsuite/23_containers/unordered_multiset/55043.cc: Likewise.
        * testsuite/23_containers/unordered_set/55043.cc: Likewise.
        * testsuite/23_containers/unordered_map/requirements/53339.cc: XFAIL,
        cannot support incomplete types.
        * testsuite/23_containers/unordered_multimap/requirements/53339.cc:
        Likewise.

Tested x86_86-linux, committed to trunk.
commit 20ee8df23bc999c8cf8876b88a188c4f51fb7665
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Wed Jan 16 09:50:47 2013 +0000

    	PR libstdc++/55043 (again)
    	* include/bits/alloc_traits.h (allocator_traits::construct): Disable
    	unless construction would be well-formed.
    	(__allow_copy_cons, __check_copy_constructible): Define.
    	* include/bits/unordered_map.h (__check_copy_constructible): Use as
    	base class so copy constructor will be deleted if appropriate.
    	(is_copy_constructible): Remove specialization.
    	* include/bits/unordered_set.h: Likewise.
    	* include/debug/unordered_map.h: Undo previous commit. Default copy
    	and move constructors.
    	* include/debug/unordered_set.h: Likewise.
    	* include/profile/unordered_map.h: Undo previous commit.
    	* include/profile/unordered_set.h: Likewise.
    	* testsuite/23_containers/unordered_map/55043.cc: Fix test.
    	* testsuite/23_containers/unordered_multimap/55043.cc: Likewise.
    	* testsuite/23_containers/unordered_multiset/55043.cc: Likewise.
    	* testsuite/23_containers/unordered_set/55043.cc: Likewise.
    	* testsuite/23_containers/unordered_map/requirements/53339.cc: XFAIL,
    	cannot support incomplete types.
    	* testsuite/23_containers/unordered_multimap/requirements/53339.cc:
    	Likewise.

Patch

diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index c6259a1..26c64f2 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -257,7 +257,8 @@  _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
 
       template<typename _Tp, typename... _Args>
 	static typename
-       	enable_if<!__construct_helper<_Tp, _Args...>::value, void>::type
+	enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>,
+			 is_constructible<_Tp, _Args...>>::value, void>::type
        	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
 	{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
 
@@ -389,7 +390,8 @@  _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
        *  arguments @a __args...
       */
       template<typename _Tp, typename... _Args>
-	static void construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+	static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
 	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
 
       /**
@@ -526,9 +528,10 @@  _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
 	_M_select(...);
 
     public:
-	typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
+      typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
     };
 
+  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
   template<typename _Alloc>
     struct __is_copy_insertable
     : __is_copy_insertable_impl<_Alloc>::type
@@ -540,9 +543,23 @@  _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
     : is_copy_constructible<_Tp>
     { };
 
-  template<typename _Container>
-    using __has_copy_insertable_val
-      = __is_copy_insertable<typename _Container::allocator_type>;
+  // Used to allow copy construction of unordered containers
+  template<bool> struct __allow_copy_cons { };
+
+  // Used to delete copy constructor of unordered containers
+  template<>
+    struct __allow_copy_cons<false>
+    {
+      __allow_copy_cons() = default;
+      __allow_copy_cons(const __allow_copy_cons&) = delete;
+      __allow_copy_cons(__allow_copy_cons&&) = default;
+      __allow_copy_cons& operator=(const __allow_copy_cons&) = default;
+      __allow_copy_cons& operator=(__allow_copy_cons&&) = default;
+    };
+
+  template<typename _Alloc>
+    using __check_copy_constructible
+      = __allow_copy_cons<__is_copy_insertable<_Alloc>::value>;
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h
index 0235a99..be213e0 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -94,7 +94,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	   class _Hash = hash<_Key>,
 	   class _Pred = std::equal_to<_Key>,
 	   class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
-    class unordered_map
+    class unordered_map : __check_copy_constructible<_Alloc>
     {
       typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
       _Hashtable _M_h;
@@ -775,7 +775,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	   class _Hash = hash<_Key>,
 	   class _Pred = std::equal_to<_Key>,
 	   class _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
-    class unordered_multimap
+    class unordered_multimap : __check_copy_constructible<_Alloc>
     {
       typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc>  _Hashtable;
       _Hashtable _M_h;
@@ -1408,26 +1408,6 @@  _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 2ada63d..50c233d 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -90,7 +90,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	   class _Hash = hash<_Value>,
 	   class _Pred = std::equal_to<_Value>,
 	   class _Alloc = std::allocator<_Value> >
-    class unordered_set
+    class unordered_set : __check_copy_constructible<_Alloc>
     {
       typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc>  _Hashtable;
       _Hashtable _M_h;
@@ -695,7 +695,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	   class _Hash = hash<_Value>,
 	   class _Pred = std::equal_to<_Value>,
 	   class _Alloc = std::allocator<_Value> >
-    class unordered_multiset
+    class unordered_multiset : __check_copy_constructible<_Alloc>
     {
       typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc>  _Hashtable;
       _Hashtable _M_h;
@@ -1291,23 +1291,6 @@  _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 115abb5..284450f 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -96,14 +96,12 @@  namespace __debug
 		__gnu_debug::__base(__last), __n,
 		__hf, __eql, __a) { }
 
-      unordered_map(const unordered_map& __x) 
-      : _Base(__x) { }
+      unordered_map(const unordered_map& __x) = default;
 
       unordered_map(const _Base& __x)
       : _Base(__x) { }
 
-      unordered_map(unordered_map&& __x)
-      : _Base(std::move(__x)) { }
+      unordered_map(unordered_map&& __x) = default;
 
       unordered_map(initializer_list<value_type> __l,
 		    size_type __n = 0,
@@ -547,14 +545,12 @@  namespace __debug
 		__gnu_debug::__base(__last), __n,
 		__hf, __eql, __a) { }
 
-      unordered_multimap(const unordered_multimap& __x) 
-      : _Base(__x) { }
+      unordered_multimap(const unordered_multimap& __x) = default;
 
       unordered_multimap(const _Base& __x) 
       : _Base(__x) { }
 
-      unordered_multimap(unordered_multimap&& __x)
-      : _Base(std::move(__x)) { }
+      unordered_multimap(unordered_multimap&& __x) = default;
 
       unordered_multimap(initializer_list<value_type> __l,
 			 size_type __n = 0,
@@ -938,30 +934,6 @@  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 895c943..2fe71e4 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -96,14 +96,12 @@  namespace __debug
 		__gnu_debug::__base(__last), __n,
 		__hf, __eql, __a) { }
 
-      unordered_set(const unordered_set& __x) 
-      : _Base(__x) { }
+      unordered_set(const unordered_set& __x) = default;
 
       unordered_set(const _Base& __x) 
       : _Base(__x) { }
 
-      unordered_set(unordered_set&& __x)
-      : _Base(std::move(__x)) { }
+      unordered_set(unordered_set&& __x) = default;
 
       unordered_set(initializer_list<value_type> __l,
 		    size_type __n = 0,
@@ -542,14 +540,12 @@  namespace __debug
 		__gnu_debug::__base(__last), __n,
 		__hf, __eql, __a) { }
 
-      unordered_multiset(const unordered_multiset& __x) 
-      : _Base(__x) { }
+      unordered_multiset(const unordered_multiset& __x) = default;
 
       unordered_multiset(const _Base& __x) 
       : _Base(__x) { }
 
-      unordered_multiset(unordered_multiset&& __x)
-      : _Base(std::move(__x)) { }
+      unordered_multiset(unordered_multiset&& __x) = default;
 
       unordered_multiset(initializer_list<value_type> __l,
 			 size_type __n = 0,
@@ -920,27 +916,6 @@  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 5ebcbf6..0fee176 100644
--- a/libstdc++-v3/include/profile/unordered_map
+++ b/libstdc++-v3/include/profile/unordered_map
@@ -339,25 +339,11 @@  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>,
@@ -623,18 +609,6 @@  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 ebe1c7d..737b6ec 100644
--- a/libstdc++-v3/include/profile/unordered_set
+++ b/libstdc++-v3/include/profile/unordered_set
@@ -305,23 +305,11 @@  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>,
@@ -580,17 +568,6 @@  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/testsuite/23_containers/unordered_map/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc
index 10d36a0..50e5437 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/55043.cc
@@ -63,7 +63,7 @@  struct Alloc : std::allocator<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");
+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_map/requirements/53339.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/53339.cc
index 4df4493..10404ce 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/53339.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/requirements/53339.cc
@@ -1,7 +1,9 @@ 
-// { dg-do compile }
+// XFAIL because of PR libstdc++/55043 fix
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
 // { dg-options "-std=gnu++11" }
 
-// Copyright (C) 2012 Free Software Foundation, Inc.
+// Copyright (C) 2012-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
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc
index 9ae912ef6..afeecaa 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/55043.cc
@@ -63,7 +63,7 @@  struct Alloc : std::allocator<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");
+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/requirements/53339.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/53339.cc
index 5745618..cccd2a8 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/53339.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/requirements/53339.cc
@@ -1,7 +1,9 @@ 
-// { dg-do compile }
+// XFAIL because of PR libstdc++/55043 fix
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
 // { dg-options "-std=gnu++11" }
 
-// Copyright (C) 2012 Free Software Foundation, Inc.
+// Copyright (C) 2012-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
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc
index ebb8cb8..445e4e4 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc
@@ -67,7 +67,7 @@  struct Alloc : std::allocator<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");
+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
index 3b0b973..e5ba065 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc
@@ -67,7 +67,7 @@  struct Alloc : std::allocator<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");
+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");