[libcxx] r242056 - Implement the first part of N4258: 'Cleaning up noexcept in the Library'. This patch deals with swapping containers, and implements a more strict noexcept specification (a conforming extension) than the standard mandates.

Marshall Clow mclow.lists at gmail.com
Mon Jul 13 13:04:57 PDT 2015


Author: marshall
Date: Mon Jul 13 15:04:56 2015
New Revision: 242056

URL: http://llvm.org/viewvc/llvm-project?rev=242056&view=rev
Log:
Implement the first part of N4258: 'Cleaning up noexcept in the Library'. This patch deals with swapping containers, and implements a more strict noexcept specification (a conforming extension) than the standard mandates.

Modified:
    libcxx/trunk/include/__hash_table
    libcxx/trunk/include/__split_buffer
    libcxx/trunk/include/__tree
    libcxx/trunk/include/deque
    libcxx/trunk/include/forward_list
    libcxx/trunk/include/list
    libcxx/trunk/include/map
    libcxx/trunk/include/memory
    libcxx/trunk/include/string
    libcxx/trunk/include/unordered_map
    libcxx/trunk/include/unordered_set
    libcxx/trunk/include/vector
    libcxx/trunk/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp
    libcxx/trunk/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp

Modified: libcxx/trunk/include/__hash_table
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__hash_table?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/__hash_table (original)
+++ libcxx/trunk/include/__hash_table Mon Jul 13 15:04:56 2015
@@ -985,12 +985,14 @@ public:
 
     void swap(__hash_table& __u)
         _NOEXCEPT_(
-            (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<__pointer_allocator>::value) &&
-            (!__node_traits::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<__node_allocator>::value) &&
-            __is_nothrow_swappable<hasher>::value &&
-            __is_nothrow_swappable<key_equal>::value);
+            __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
+#if _LIBCPP_STD_VER <= 11
+            && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
+                  || __is_nothrow_swappable<__pointer_allocator>::value)
+            && (!__node_traits::propagate_on_container_swap::value
+                  || __is_nothrow_swappable<__node_allocator>::value)
+#endif
+            );
 
     _LIBCPP_INLINE_VISIBILITY
     size_type max_bucket_count() const _NOEXCEPT
@@ -1118,38 +1120,6 @@ private:
     _LIBCPP_INLINE_VISIBILITY
         void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
 
-    template <class _Ap>
-    _LIBCPP_INLINE_VISIBILITY
-    static
-    void
-    __swap_alloc(_Ap& __x, _Ap& __y)
-        _NOEXCEPT_(
-            !allocator_traits<_Ap>::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<_Ap>::value)
-    {
-        __swap_alloc(__x, __y,
-                     integral_constant<bool,
-                        allocator_traits<_Ap>::propagate_on_container_swap::value
-                                      >());
-    }
-
-    template <class _Ap>
-    _LIBCPP_INLINE_VISIBILITY
-    static
-    void
-    __swap_alloc(_Ap& __x, _Ap& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
-    {
-        using _VSTD::swap;
-        swap(__x, __y);
-    }
-
-    template <class _Ap>
-    _LIBCPP_INLINE_VISIBILITY
-    static
-    void
-    __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
-
     void __deallocate(__node_pointer __np) _NOEXCEPT;
     __node_pointer __detach() _NOEXCEPT;
 
@@ -2382,12 +2352,14 @@ template <class _Tp, class _Hash, class
 void
 __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
     _NOEXCEPT_(
-        (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
-         __is_nothrow_swappable<__pointer_allocator>::value) &&
-        (!__node_traits::propagate_on_container_swap::value ||
-         __is_nothrow_swappable<__node_allocator>::value) &&
-        __is_nothrow_swappable<hasher>::value &&
-        __is_nothrow_swappable<key_equal>::value)
+        __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
+#if _LIBCPP_STD_VER <= 11
+        && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
+              || __is_nothrow_swappable<__pointer_allocator>::value)
+        && (!__node_traits::propagate_on_container_swap::value
+              || __is_nothrow_swappable<__node_allocator>::value)
+#endif
+            )
 {
     {
     __node_pointer_pointer __npp = __bucket_list_.release();
@@ -2395,9 +2367,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>
     __u.__bucket_list_.reset(__npp);
     }
     _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
-    __swap_alloc(__bucket_list_.get_deleter().__alloc(),
+    __swap_allocator(__bucket_list_.get_deleter().__alloc(),
              __u.__bucket_list_.get_deleter().__alloc());
-    __swap_alloc(__node_alloc(), __u.__node_alloc());
+    __swap_allocator(__node_alloc(), __u.__node_alloc());
     _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
     __p2_.swap(__u.__p2_);
     __p3_.swap(__u.__p3_);

Modified: libcxx/trunk/include/__split_buffer
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__split_buffer?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/__split_buffer (original)
+++ libcxx/trunk/include/__split_buffer Mon Jul 13 15:04:56 2015
@@ -156,25 +156,6 @@ private:
     _LIBCPP_INLINE_VISIBILITY
     void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT
         {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__alloc_rr& __x, __alloc_rr& __y)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value||
-                   __is_nothrow_swappable<__alloc_rr>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __alloc_traits::propagate_on_container_swap::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__alloc_rr& __x, __alloc_rr& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<__alloc_rr>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__alloc_rr&, __alloc_rr&, false_type) _NOEXCEPT
-        {}
 };
 
 template <class _Tp, class _Allocator>
@@ -431,7 +412,7 @@ __split_buffer<_Tp, _Allocator>::swap(__
     _VSTD::swap(__begin_, __x.__begin_);
     _VSTD::swap(__end_, __x.__end_);
     _VSTD::swap(__end_cap(), __x.__end_cap());
-    __swap_alloc(__alloc(), __x.__alloc());
+    __swap_allocator(__alloc(), __x.__alloc());
 }
 
 template <class _Tp, class _Allocator>

Modified: libcxx/trunk/include/__tree
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tree?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/__tree (original)
+++ libcxx/trunk/include/__tree Mon Jul 13 15:04:56 2015
@@ -926,9 +926,12 @@ public:
 
     void swap(__tree& __t)
         _NOEXCEPT_(
-            __is_nothrow_swappable<value_compare>::value &&
-            (!__node_traits::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<__node_allocator>::value));
+            __is_nothrow_swappable<value_compare>::value
+#if _LIBCPP_STD_VER <= 11
+            && (!__node_traits::propagate_on_container_swap::value ||
+                 __is_nothrow_swappable<__node_allocator>::value)
+#endif
+            );
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #ifndef _LIBCPP_HAS_NO_VARIADICS
@@ -1096,25 +1099,6 @@ private:
     _LIBCPP_INLINE_VISIBILITY
     void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {}
 
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y)
-        _NOEXCEPT_(
-            !__node_traits::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<__node_allocator>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __node_traits::propagate_on_container_swap::value>());}
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type)
-        _NOEXCEPT
-        {}
-
     __node_pointer __detach();
     static __node_pointer __detach(__node_pointer);
 
@@ -1452,15 +1436,18 @@ __tree<_Tp, _Compare, _Allocator>::destr
 template <class _Tp, class _Compare, class _Allocator>
 void
 __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
-    _NOEXCEPT_(
-        __is_nothrow_swappable<value_compare>::value &&
-        (!__node_traits::propagate_on_container_swap::value ||
-         __is_nothrow_swappable<__node_allocator>::value))
+        _NOEXCEPT_(
+            __is_nothrow_swappable<value_compare>::value
+#if _LIBCPP_STD_VER <= 11
+            && (!__node_traits::propagate_on_container_swap::value ||
+                 __is_nothrow_swappable<__node_allocator>::value)
+#endif
+            )
 {
     using _VSTD::swap;
     swap(__begin_node_, __t.__begin_node_);
     swap(__pair1_.first(), __t.__pair1_.first());
-    __swap_alloc(__node_alloc(), __t.__node_alloc());
+    __swap_allocator(__node_alloc(), __t.__node_alloc());
     __pair3_.swap(__t.__pair3_);
     if (size() == 0)
         __begin_node() = __end_node();

Modified: libcxx/trunk/include/deque
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/deque?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/deque (original)
+++ libcxx/trunk/include/deque Mon Jul 13 15:04:56 2015
@@ -124,8 +124,7 @@ public:
     iterator erase(const_iterator p);
     iterator erase(const_iterator f, const_iterator l);
     void swap(deque& c)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value);
+        noexcept(allocator_traits<allocator_type>::is_always_equal::value);  // C++17
     void clear() noexcept;
 };
 
@@ -954,8 +953,12 @@ public:
 
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     void swap(__deque_base& __c)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 protected:
     void clear() _NOEXCEPT;
 
@@ -991,26 +994,6 @@ private:
     _LIBCPP_INLINE_VISIBILITY
     void __move_assign_alloc(__deque_base&, false_type) _NOEXCEPT
         {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __alloc_traits::propagate_on_container_swap::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type&, allocator_type&, false_type)
-        _NOEXCEPT
-        {}
 };
 
 template <class _Tp, class _Allocator>
@@ -1134,13 +1117,17 @@ __deque_base<_Tp, _Allocator>::__deque_b
 template <class _Tp, class _Allocator>
 void
 __deque_base<_Tp, _Allocator>::swap(__deque_base& __c)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     __map_.swap(__c.__map_);
     _VSTD::swap(__start_, __c.__start_);
     _VSTD::swap(size(), __c.size());
-    __swap_alloc(__alloc(), __c.__alloc());
+    __swap_allocator(__alloc(), __c.__alloc());
 }
 
 template <class _Tp, class _Allocator>
@@ -1342,8 +1329,12 @@ public:
     iterator erase(const_iterator __f, const_iterator __l);
 
     void swap(deque& __c)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
         _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
                    __is_nothrow_swappable<allocator_type>::value);
+#endif
     void clear() _NOEXCEPT;
 
     _LIBCPP_INLINE_VISIBILITY
@@ -2277,13 +2268,13 @@ deque<_Tp, _Allocator>::__add_front_capa
             __buf(max<size_type>(2 * __base::__map_.capacity(), 1),
                   0, __base::__map_.__alloc());
 
-		typedef __allocator_destructor<_Allocator> _Dp;
-		unique_ptr<pointer, _Dp> __hold(
-			__alloc_traits::allocate(__a, __base::__block_size),
-				_Dp(__a, __base::__block_size));
-		__buf.push_back(__hold.get());
-		__hold.release();
-	
+        typedef __allocator_destructor<_Allocator> _Dp;
+        unique_ptr<pointer, _Dp> __hold(
+            __alloc_traits::allocate(__a, __base::__block_size),
+                _Dp(__a, __base::__block_size));
+        __buf.push_back(__hold.get());
+        __hold.release();
+    
         for (typename __base::__map_pointer __i = __base::__map_.begin();
                 __i != __base::__map_.end(); ++__i)
             __buf.push_back(*__i);
@@ -2420,12 +2411,12 @@ deque<_Tp, _Allocator>::__add_back_capac
                   __base::__map_.size(),
                   __base::__map_.__alloc());
 
-		typedef __allocator_destructor<_Allocator> _Dp;
-		unique_ptr<pointer, _Dp> __hold(
-			__alloc_traits::allocate(__a, __base::__block_size),
-				_Dp(__a, __base::__block_size));
-		__buf.push_back(__hold.get());
-		__hold.release();
+        typedef __allocator_destructor<_Allocator> _Dp;
+        unique_ptr<pointer, _Dp> __hold(
+            __alloc_traits::allocate(__a, __base::__block_size),
+                _Dp(__a, __base::__block_size));
+        __buf.push_back(__hold.get());
+        __hold.release();
 
         for (typename __base::__map_pointer __i = __base::__map_.end();
                 __i != __base::__map_.begin();)
@@ -2793,8 +2784,12 @@ template <class _Tp, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
 void
 deque<_Tp, _Allocator>::swap(deque& __c)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     __base::swap(__c);
 }

Modified: libcxx/trunk/include/forward_list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/forward_list?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/forward_list (original)
+++ libcxx/trunk/include/forward_list Mon Jul 13 15:04:56 2015
@@ -107,8 +107,7 @@ public:
     iterator erase_after(const_iterator first, const_iterator last);
 
     void swap(forward_list& x)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value);
+        noexcept(allocator_traits<allocator_type>::is_always_equal::value);  // C++17
 
     void resize(size_type n);
     void resize(size_type n, const value_type& v);
@@ -431,8 +430,12 @@ protected:
 
 public:
     void swap(__forward_list_base& __x)
-        _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || 
+                    __is_nothrow_swappable<__node_allocator>::value);
+#endif
 protected:
     void clear() _NOEXCEPT;
 
@@ -454,26 +457,6 @@ private:
     void __move_assign_alloc(__forward_list_base& __x, true_type)
         _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value)
         {__alloc() = _VSTD::move(__x.__alloc());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y)
-        _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                         __node_traits::propagate_on_container_swap::value>());}
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y,
-                                                                     false_type)
-        _NOEXCEPT
-        {}
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y,
-                                                                      true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
 };
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
@@ -512,10 +495,15 @@ template <class _Tp, class _Alloc>
 inline _LIBCPP_INLINE_VISIBILITY
 void
 __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x)
-        _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
+        _NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value || 
+                    __is_nothrow_swappable<__node_allocator>::value)
+#endif
 {
-    __swap_alloc(__alloc(), __x.__alloc());
+    __swap_allocator(__alloc(), __x.__alloc(), 
+            integral_constant<bool, __node_traits::propagate_on_container_swap::value>());
     using _VSTD::swap;
     swap(__before_begin()->__next_, __x.__before_begin()->__next_);
 }
@@ -703,8 +691,12 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY
     void swap(forward_list& __x)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
         _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value ||
                    __is_nothrow_swappable<__node_allocator>::value)
+#endif
         {base::swap(__x);}
 
     void resize(size_type __n);

Modified: libcxx/trunk/include/list
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/list?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/list (original)
+++ libcxx/trunk/include/list Mon Jul 13 15:04:56 2015
@@ -118,8 +118,7 @@ public:
     void resize(size_type sz, const value_type& c);
 
     void swap(list&)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value);
+        noexcept(allocator_traits<allocator_type>::is_always_equal::value);  // C++17
     void clear() noexcept;
 
     void splice(const_iterator position, list& x);
@@ -593,8 +592,12 @@ protected:
     }
 
     void swap(__list_imp& __c)
-        _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     void __copy_assign_alloc(const __list_imp& __c)
@@ -611,24 +614,6 @@ protected:
 
 private:
     _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y)
-        _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __node_alloc_traits::propagate_on_container_swap::value>());}
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<__node_allocator>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__node_allocator& __x, __node_allocator& __y, false_type)
-        _NOEXCEPT
-        {}
-
-    _LIBCPP_INLINE_VISIBILITY
     void __copy_assign_alloc(const __list_imp& __c, true_type)
         {
             if (__node_alloc() != __c.__node_alloc())
@@ -728,15 +713,19 @@ __list_imp<_Tp, _Alloc>::clear() _NOEXCE
 template <class _Tp, class _Alloc>
 void
 __list_imp<_Tp, _Alloc>::swap(__list_imp& __c)
-        _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<__node_allocator>::value)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value ||
                    this->__node_alloc() == __c.__node_alloc(),
                    "list::swap: Either propagate_on_container_swap must be true"
                    " or the allocators must compare equal");
     using _VSTD::swap;
-    __swap_alloc(__node_alloc(), __c.__node_alloc());
+    __swap_allocator(__node_alloc(), __c.__node_alloc());
     swap(__sz(), __c.__sz());
     swap(__end_, __c.__end_);
     if (__sz() == 0)
@@ -972,8 +961,12 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY
     void swap(list& __c)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
         _NOEXCEPT_(!__node_alloc_traits::propagate_on_container_swap::value ||
                    __is_nothrow_swappable<__node_allocator>::value)
+#endif
         {base::swap(__c);}
     _LIBCPP_INLINE_VISIBILITY
     void clear() _NOEXCEPT {base::clear();}

Modified: libcxx/trunk/include/map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/map?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/map (original)
+++ libcxx/trunk/include/map Mon Jul 13 15:04:56 2015
@@ -159,10 +159,8 @@ public:
     void clear() noexcept;
 
     void swap(map& m)
-        noexcept(
-            __is_nothrow_swappable<key_compare>::value &&
-            (!allocator_type::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<allocator_type>::value));
+        noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
+            __is_nothrow_swappable<key_compare>::value); // C++17
 
     // observers:
     allocator_type get_allocator() const noexcept;
@@ -354,10 +352,8 @@ public:
     void clear() noexcept;
 
     void swap(multimap& m)
-        noexcept(
-            __is_nothrow_swappable<key_compare>::value &&
-            (!allocator_type::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<allocator_type>::value));
+        noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
+            __is_nothrow_swappable<key_compare>::value); // C++17
 
     // observers:
     allocator_type get_allocator() const noexcept;
@@ -479,6 +475,12 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     bool operator()(const _Key& __x, const _CP& __y) const
         {return static_cast<const _Compare&>(*this)(__x, __y.__cc.first);}
+    void swap(__map_value_compare&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value)
+    {
+        using _VSTD::swap;
+        swap(static_cast<const _Compare&>(*this), static_cast<const _Compare&>(__y));
+    }
 
 #if _LIBCPP_STD_VER > 11
     template <typename _K2>
@@ -521,7 +523,13 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     bool operator()(const _Key& __x, const _CP& __y) const
         {return comp(__x, __y.__cc.first);}
-
+    void swap(__map_value_compare&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value)
+    {
+        using _VSTD::swap;
+        swap(comp, __y.comp);
+    }
+    
 #if _LIBCPP_STD_VER > 11
     template <typename _K2>
     _LIBCPP_INLINE_VISIBILITY
@@ -537,6 +545,16 @@ public:
 #endif
 };
 
+template <class _Key, class _CP, class _Compare, bool __b>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x,
+     __map_value_compare<_Key, _CP, _Compare, __b>& __y)
+    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
+{
+    __x.swap(__y);
+}
+
 template <class _Allocator>
 class __map_node_destructor
 {

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Mon Jul 13 15:04:56 2015
@@ -5543,6 +5543,38 @@ undeclare_reachable(_Tp* __p)
 
 _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space);
 
+// --- Helper for container swap --
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc & __a1, _Alloc & __a2)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+#endif
+{
+    __swap_allocator(__a1, __a2, 
+      integral_constant<bool, _VSTD::allocator_traits<_Alloc>::propagate_on_container_swap::value>());
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
+#endif
+{
+    using _VSTD::swap;
+    swap(__a1, __a2);
+}
+
+template <typename _Alloc>
+_LIBCPP_INLINE_VISIBILITY
+void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
+
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_MEMORY

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Mon Jul 13 15:04:56 2015
@@ -220,8 +220,8 @@ public:
     basic_string substr(size_type pos = 0, size_type n = npos) const;
 
     void swap(basic_string& str)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value)
+        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17
 
     const value_type* c_str() const noexcept;
     const value_type* data() const noexcept;
@@ -1604,8 +1604,12 @@ public:
 
     _LIBCPP_INLINE_VISIBILITY
     void swap(basic_string& __str)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     const value_type* c_str() const _NOEXCEPT {return data();}
@@ -1868,24 +1872,6 @@ private:
         _NOEXCEPT
         {}
 
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __alloc_traits::propagate_on_container_swap::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type&, allocator_type&, false_type) _NOEXCEPT
-        {}
-
     _LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
     _LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(size_type);
 
@@ -3366,8 +3352,12 @@ template <class _CharT, class _Traits, c
 inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
 #if _LIBCPP_DEBUG_LEVEL >= 2
     if (!__is_long())
@@ -3377,7 +3367,7 @@ basic_string<_CharT, _Traits, _Allocator
     __get_db()->swap(this, &__str);
 #endif
     _VSTD::swap(__r_.first(), __str.__r_.first());
-    __swap_alloc(__alloc(), __str.__alloc());
+    __swap_allocator(__alloc(), __str.__alloc());
 }
 
 // find

Modified: libcxx/trunk/include/unordered_map
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_map?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/unordered_map (original)
+++ libcxx/trunk/include/unordered_map Mon Jul 13 15:04:56 2015
@@ -401,6 +401,12 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     size_t operator()(const _Key& __x) const
         {return static_cast<const _Hash&>(*this)(__x);}
+    void swap(__unordered_map_hasher&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value)
+    {
+        using _VSTD::swap;
+        swap(static_cast<const _Hash&>(*this), static_cast<const _Hash&>(__y));
+    }
 };
 
 template <class _Key, class _Cp, class _Hash>
@@ -425,8 +431,24 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     size_t operator()(const _Key& __x) const
         {return __hash_(__x);}
+    void swap(__unordered_map_hasher&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Hash>::value)
+    {
+        using _VSTD::swap;
+        swap(__hash_, __y.__hash_);
+    }
 };
 
+template <class _Key, class _Cp, class _Hash, bool __b>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__unordered_map_hasher<_Key, _Cp, _Hash, __b>& __x,
+     __unordered_map_hasher<_Key, _Cp, _Hash, __b>& __y)
+    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
+{
+    __x.swap(__y);
+}
+
 template <class _Key, class _Cp, class _Pred,
           bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value
          >
@@ -453,6 +475,12 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     bool operator()(const _Key& __x, const _Cp& __y) const
         {return static_cast<const _Pred&>(*this)(__x, __y.__cc.first);}
+    void swap(__unordered_map_equal&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
+    {
+        using _VSTD::swap;
+        swap(static_cast<const _Pred&>(*this), static_cast<const _Pred&>(__y));
+    }
 };
 
 template <class _Key, class _Cp, class _Pred>
@@ -480,8 +508,24 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     bool operator()(const _Key& __x, const _Cp& __y) const
         {return __pred_(__x, __y.__cc.first);}
+    void swap(__unordered_map_equal&__y)
+        _NOEXCEPT_(__is_nothrow_swappable<_Pred>::value)
+    {
+        using _VSTD::swap;
+        swap(__pred_, __y.__pred_);
+    }
 };
 
+template <class _Key, class _Cp, class _Pred, bool __b>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__unordered_map_equal<_Key, _Cp, _Pred, __b>& __x,
+     __unordered_map_equal<_Key, _Cp, _Pred, __b>& __y)
+    _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
+{
+    __x.swap(__y);
+}
+
 template <class _Alloc>
 class __hash_map_node_destructor
 {

Modified: libcxx/trunk/include/unordered_set
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/unordered_set?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/unordered_set (original)
+++ libcxx/trunk/include/unordered_set Mon Jul 13 15:04:56 2015
@@ -120,11 +120,9 @@ public:
     void clear() noexcept;
 
     void swap(unordered_set&)
-        noexcept(
-            (!allocator_type::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<allocator_type>::value) &&
-            __is_nothrow_swappable<hasher>::value &&
-            __is_nothrow_swappable<key_equal>::value);
+       noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+                 noexcept(swap(declval<hasher&>(), declval<hasher&>())) &&
+                 noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); // C++17
 
     hasher hash_function() const;
     key_equal key_eq() const;
@@ -270,11 +268,9 @@ public:
     void clear() noexcept;
 
     void swap(unordered_multiset&)
-        noexcept(
-            (!allocator_type::propagate_on_container_swap::value ||
-             __is_nothrow_swappable<allocator_type>::value) &&
-            __is_nothrow_swappable<hasher>::value &&
-            __is_nothrow_swappable<key_equal>::value);
+       noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+                 noexcept(swap(declval<hasher&>(), declval<hasher&>())) &&
+                 noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); // C++17
 
     hasher hash_function() const;
     key_equal key_eq() const;

Modified: libcxx/trunk/include/vector
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/vector?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/include/vector (original)
+++ libcxx/trunk/include/vector Mon Jul 13 15:04:56 2015
@@ -119,8 +119,8 @@ public:
     void resize(size_type sz, const value_type& c);
 
     void swap(vector&)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value);
+        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17
 
     bool __invariants() const;
 };
@@ -237,8 +237,8 @@ public:
     void resize(size_type sz, value_type x);
 
     void swap(vector&)
-        noexcept(!allocator_type::propagate_on_container_swap::value ||
-                 __is_nothrow_swappable<allocator_type>::value);
+        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
+                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17
     void flip() noexcept;
 
     bool __invariants() const;
@@ -385,14 +385,6 @@ protected:
             is_nothrow_move_assignable<allocator_type>::value)
         {__move_assign_alloc(__c, integral_constant<bool,
                       __alloc_traits::propagate_on_container_move_assignment::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y)
-        _NOEXCEPT_(
-            !__alloc_traits::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __alloc_traits::propagate_on_container_swap::value>());}
 private:
     _LIBCPP_INLINE_VISIBILITY
     void __copy_assign_alloc(const __vector_base& __c, true_type)
@@ -421,18 +413,6 @@ private:
     void __move_assign_alloc(__vector_base&, false_type)
         _NOEXCEPT
         {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type& __x, allocator_type& __y, true_type)
-        _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(allocator_type&, allocator_type&, false_type)
-        _NOEXCEPT
-        {}
 };
 
 template <class _Tp, class _Allocator>
@@ -760,8 +740,12 @@ public:
     void resize(size_type __sz, const_reference __x);
 
     void swap(vector&)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     bool __invariants() const;
 
@@ -2016,8 +2000,12 @@ vector<_Tp, _Allocator>::resize(size_typ
 template <class _Tp, class _Allocator>
 void
 vector<_Tp, _Allocator>::swap(vector& __x)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value ||
                    this->__alloc() == __x.__alloc(),
@@ -2026,7 +2014,8 @@ vector<_Tp, _Allocator>::swap(vector& __
     _VSTD::swap(this->__begin_, __x.__begin_);
     _VSTD::swap(this->__end_, __x.__end_);
     _VSTD::swap(this->__end_cap(), __x.__end_cap());
-    __base::__swap_alloc(this->__alloc(), __x.__alloc());
+    __swap_allocator(this->__alloc(), __x.__alloc(), 
+        integral_constant<bool,__alloc_traits::propagate_on_container_swap::value>());
 #if _LIBCPP_DEBUG_LEVEL >= 2
     __get_db()->swap(this, &__x);
 #endif  // _LIBCPP_DEBUG_LEVEL >= 2
@@ -2354,8 +2343,12 @@ public:
     void clear() _NOEXCEPT {__size_ = 0;}
 
     void swap(vector&)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value);
+#if _LIBCPP_STD_VER >= 14
+        _NOEXCEPT;
+#else
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                    __is_nothrow_swappable<allocator_type>::value);
+#endif
 
     void resize(size_type __sz, value_type __x = false);
     void flip() _NOEXCEPT;
@@ -2433,26 +2426,6 @@ private:
         _NOEXCEPT
         {}
 
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator& __x, __storage_allocator& __y)
-        _NOEXCEPT_(
-            !__storage_traits::propagate_on_container_swap::value ||
-            __is_nothrow_swappable<allocator_type>::value)
-        {__swap_alloc(__x, __y, integral_constant<bool,
-                      __storage_traits::propagate_on_container_swap::value>());}
-
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator& __x, __storage_allocator& __y, true_type)
-        _NOEXCEPT_(__is_nothrow_swappable<allocator_type>::value)
-        {
-            using _VSTD::swap;
-            swap(__x, __y);
-        }
-    _LIBCPP_INLINE_VISIBILITY
-    static void __swap_alloc(__storage_allocator&, __storage_allocator&, false_type)
-        _NOEXCEPT
-        {}
-
     size_t __hash_code() const _NOEXCEPT;
 
     friend class __bit_reference<vector>;
@@ -3155,13 +3128,18 @@ vector<bool, _Allocator>::erase(const_it
 template <class _Allocator>
 void
 vector<bool, _Allocator>::swap(vector& __x)
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
-                   __is_nothrow_swappable<allocator_type>::value)
+#if _LIBCPP_STD_VER >= 14
+    _NOEXCEPT
+#else
+    _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+                __is_nothrow_swappable<allocator_type>::value)
+#endif
 {
     _VSTD::swap(this->__begin_, __x.__begin_);
     _VSTD::swap(this->__size_, __x.__size_);
     _VSTD::swap(this->__cap(), __x.__cap());
-    __swap_alloc(this->__alloc(), __x.__alloc());
+    __swap_allocator(this->__alloc(), __x.__alloc(), 
+        integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
 }
 
 template <class _Allocator>

Modified: libcxx/trunk/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(map& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//              noexcept(swap(declval<Compare&>(), declval<Compare&>())));                 
 
 // This tests a conforming extension
 
@@ -33,6 +37,60 @@ struct some_comp
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -56,5 +114,35 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/associative/multimap/multimap.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(multimap& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//              noexcept(swap(declval<Compare&>(), declval<Compare&>())));                 
 
 // This tests a conforming extension
 
@@ -33,6 +37,60 @@ struct some_comp
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -56,5 +114,35 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for comp
+    typedef std::multimap<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for comp
+    typedef std::multimap<MoveOnly, MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for comp
+    typedef std::multimap<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for comp
+    typedef std::multimap<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for comp
+    typedef std::map<MoveOnly, MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/associative/multiset/multiset.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(multiset& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//              noexcept(swap(declval<Compare&>(), declval<Compare&>())));                 
 
 // This tests a conforming extension
 
@@ -33,6 +37,60 @@ struct some_comp
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -56,5 +114,35 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for comp
+    typedef std::multiset<MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for comp
+    typedef std::multiset<MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for comp
+    typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for comp
+    typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for comp
+    typedef std::multiset<MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/associative/set/set.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(set& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//              noexcept(swap(declval<Compare&>(), declval<Compare&>())));                 
 
 // This tests a conforming extension
 
@@ -33,6 +37,60 @@ struct some_comp
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -56,5 +114,35 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for comp
+    typedef std::set<MoveOnly, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for comp
+    typedef std::set<MoveOnly, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for comp
+    typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for comp
+    typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for comp
+    typedef std::set<MoveOnly, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/deque/deque.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,9 @@
 // void swap(deque& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value);
 
 // This tests a conforming extension
 
@@ -33,6 +36,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -54,7 +70,21 @@ int main()
     {
         typedef std::deque<MoveOnly, some_alloc<MoveOnly>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::deque<MoveOnly, some_alloc2<MoveOnly>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,9 @@
 // void swap(forward_list& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(is_always_equal<allocator_type>::value);
 
 // This tests a conforming extension
 
@@ -33,6 +36,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -54,7 +70,21 @@ int main()
     {
         typedef std::forward_list<MoveOnly, some_alloc<MoveOnly>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::forward_list<MoveOnly, some_alloc2<MoveOnly>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/list/list.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,9 @@
 // void swap(list& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value);
 
 // This tests a conforming extension
 
@@ -33,6 +36,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -54,7 +70,21 @@ int main()
     {
         typedef std::list<MoveOnly, some_alloc<MoveOnly>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::list<MoveOnly, some_alloc2<MoveOnly>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/vector.bool/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(vector& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
+//              allocator_traits<Allocator>::is_always_equal::value);
 
 // This tests a conforming extension
 
@@ -32,6 +36,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -53,7 +70,21 @@ int main()
     {
         typedef std::vector<bool, some_alloc<bool>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::vector<bool, some_alloc2<bool>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/sequences/vector/vector.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(vector& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
+//              allocator_traits<Allocator>::is_always_equal::value);
 
 // This tests a conforming extension
 
@@ -33,6 +37,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -54,7 +71,21 @@ int main()
     {
         typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/unord/unord.map/unord.map.swap/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -10,8 +10,16 @@
 // <unordered_map>
 
 // void swap(unordered_map& c)
-//     noexcept(!allocator_type::propagate_on_container_swap::value ||
-//              __is_nothrow_swappable<allocator_type>::value);
+//      noexcept(
+//          (!allocator_type::propagate_on_container_swap::value ||
+//           __is_nothrow_swappable<allocator_type>::value) &&
+//           __is_nothrow_swappable<hasher>::value &&
+//           __is_nothrow_swappable<key_equal>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//               noexcept(swap(declval<Hash&>(), declval<Hash&>())) &&
+//               noexcept(swap(declval<Pred&>(), declval<Pred&>())));
 
 // This tests a conforming extension
 
@@ -31,6 +39,22 @@ struct some_comp
 };
 
 template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
 struct some_hash
 {
     typedef T value_type;
@@ -38,9 +62,62 @@ struct some_hash
     some_hash(const some_hash&);
 };
 
+template <class T>
+struct some_hash2
+{
+    typedef T value_type;
+    some_hash2() {}
+    some_hash2(const some_hash2&);
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_hash2<T>&, some_hash2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
+	typedef std::pair<const MoveOnly, MoveOnly> MapType;
     {
         typedef std::unordered_map<MoveOnly, MoveOnly> C;
         C c1, c2;
@@ -48,13 +125,13 @@ int main()
     }
     {
         typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>,
-                           std::equal_to<MoveOnly>, test_allocator<std::pair<const MoveOnly, MoveOnly>>> C;
+                           std::equal_to<MoveOnly>, test_allocator<MapType>> C;
         C c1, c2;
         static_assert(noexcept(swap(c1, c2)), "");
     }
     {
         typedef std::unordered_map<MoveOnly, MoveOnly, std::hash<MoveOnly>,
-                          std::equal_to<MoveOnly>, other_allocator<std::pair<const MoveOnly, MoveOnly>>> C;
+                          std::equal_to<MoveOnly>, other_allocator<MapType>> C;
         C c1, c2;
         static_assert(noexcept(swap(c1, c2)), "");
     }
@@ -69,5 +146,54 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_map<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
 #endif
 }

Modified: libcxx/trunk/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/unord/unord.multimap/unord.multimap.swap/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -10,8 +10,16 @@
 // <unordered_map>
 
 // void swap(unordered_multimap& c)
-//     noexcept(!allocator_type::propagate_on_container_swap::value ||
-//              __is_nothrow_swappable<allocator_type>::value);
+//      noexcept(
+//          (!allocator_type::propagate_on_container_swap::value ||
+//                __is_nothrow_swappable<allocator_type>::value) &&
+//           __is_nothrow_swappable<hasher>::value &&
+//           __is_nothrow_swappable<key_equal>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
+//               __is_nothrow_swappable<hasher>::value &&
+//               __is_nothrow_swappable<key_equal>::value);
 
 // This tests a conforming extension
 
@@ -31,6 +39,22 @@ struct some_comp
 };
 
 template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
 struct some_hash
 {
     typedef T value_type;
@@ -38,9 +62,61 @@ struct some_hash
     some_hash(const some_hash&);
 };
 
+template <class T>
+struct some_hash2
+{
+    typedef T value_type;
+    some_hash2() {}
+    some_hash2(const some_hash2&);
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_hash2<T>&, some_hash2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
+	typedef std::pair<const MoveOnly, MoveOnly> MapType;
     {
         typedef std::unordered_multimap<MoveOnly, MoveOnly> C;
         C c1, c2;
@@ -48,13 +124,13 @@ int main()
     }
     {
         typedef std::unordered_multimap<MoveOnly, MoveOnly, std::hash<MoveOnly>,
-                           std::equal_to<MoveOnly>, test_allocator<std::pair<const MoveOnly, MoveOnly>>> C;
+                           std::equal_to<MoveOnly>, test_allocator<MapType>> C;
         C c1, c2;
         static_assert(noexcept(swap(c1, c2)), "");
     }
     {
         typedef std::unordered_multimap<MoveOnly, MoveOnly, std::hash<MoveOnly>,
-                          std::equal_to<MoveOnly>, other_allocator<std::pair<const MoveOnly, MoveOnly>>> C;
+                          std::equal_to<MoveOnly>, other_allocator<MapType>> C;
         C c1, c2;
         static_assert(noexcept(swap(c1, c2)), "");
     }
@@ -69,5 +145,54 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multimap<MoveOnly, MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MapType>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/unord/unord.multiset/unord.multiset.swap/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -10,8 +10,16 @@
 // <unordered_set>
 
 // void swap(unordered_multiset& c)
-//     noexcept(!allocator_type::propagate_on_container_swap::value ||
-//              __is_nothrow_swappable<allocator_type>::value);
+//      noexcept(
+//          (!allocator_type::propagate_on_container_swap::value ||
+//           __is_nothrow_swappable<allocator_type>::value) &&
+//           __is_nothrow_swappable<hasher>::value &&
+//           __is_nothrow_swappable<key_equal>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//               noexcept(swap(declval<Hash&>(), declval<Hash&>())) &&
+//               noexcept(swap(declval<Pred&>(), declval<Pred&>())));
 
 // This tests a conforming extension
 
@@ -31,6 +39,22 @@ struct some_comp
 };
 
 template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
 struct some_hash
 {
     typedef T value_type;
@@ -38,6 +62,57 @@ struct some_hash
     some_hash(const some_hash&);
 };
 
+template <class T>
+struct some_hash2
+{
+    typedef T value_type;
+    some_hash2() {}
+    some_hash2(const some_hash2&);
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_hash2<T>&, some_hash2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -69,5 +144,55 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_multiset<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/containers/unord/unord.set/unord.set.swap/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -10,8 +10,16 @@
 // <unordered_set>
 
 // void swap(unordered_set& c)
-//     noexcept(!allocator_type::propagate_on_container_swap::value ||
-//              __is_nothrow_swappable<allocator_type>::value);
+//      noexcept(
+//          (!allocator_type::propagate_on_container_swap::value ||
+//           __is_nothrow_swappable<allocator_type>::value) &&
+//           __is_nothrow_swappable<hasher>::value &&
+//           __is_nothrow_swappable<key_equal>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::is_always_equal::value &&
+//               noexcept(swap(declval<Hash&>(), declval<Hash&>())) &&
+//               noexcept(swap(declval<Pred&>(), declval<Pred&>())));
 
 // This tests a conforming extension
 
@@ -31,6 +39,22 @@ struct some_comp
 };
 
 template <class T>
+struct some_comp2
+{
+    typedef T value_type;
+    
+    some_comp2() {}
+    some_comp2(const some_comp2&) {}
+    void deallocate(void*, unsigned) {}
+    typedef std::true_type propagate_on_container_swap;
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_comp2<T>&, some_comp2<T>&) noexcept {}
+#endif
+
+template <class T>
 struct some_hash
 {
     typedef T value_type;
@@ -38,6 +62,57 @@ struct some_hash
     some_hash(const some_hash&);
 };
 
+template <class T>
+struct some_hash2
+{
+    typedef T value_type;
+    some_hash2() {}
+    some_hash2(const some_hash2&);
+};
+
+#if TEST_STD_VER >= 14
+template <typename T>
+void swap(some_hash2<T>&, some_hash2<T>&) noexcept {}
+#endif
+
+template <class T>
+struct some_alloc
+{
+    typedef T value_type;
+    
+    some_alloc() {}
+    some_alloc(const some_alloc&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
+template <class T>
+struct some_alloc3
+{
+    typedef T value_type;
+    
+    some_alloc3() {}
+    some_alloc3(const some_alloc3&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::false_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -69,5 +144,55 @@ int main()
         C c1, c2;
         static_assert(!noexcept(swap(c1, c2)), "");
     }
+
+#if TEST_STD_VER >= 14
+    { // POCS allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, throwable swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, throwable swap for hash, nothrow swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, throwable swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp <MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert(!noexcept(swap(c1, c2)), "");
+    }
+    { // POCS allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc <MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+    { // always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc2<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+
+    { // NOT always equal allocator, nothrow swap for hash, nothrow swap for comp
+    typedef std::unordered_set<MoveOnly, some_hash2<MoveOnly>, some_comp2<MoveOnly>, some_alloc3<MoveOnly>> C;
+    C c1, c2;
+    static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }

Modified: libcxx/trunk/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp?rev=242056&r1=242055&r2=242056&view=diff
==============================================================================
--- libcxx/trunk/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp (original)
+++ libcxx/trunk/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp Mon Jul 13 15:04:56 2015
@@ -12,6 +12,10 @@
 // void swap(basic_string& c)
 //     noexcept(!allocator_type::propagate_on_container_swap::value ||
 //              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
+//              allocator_traits<Allocator>::is_always_equal::value);
 
 // This tests a conforming extension
 
@@ -32,6 +36,19 @@ struct some_alloc
     typedef std::true_type propagate_on_container_swap;
 };
 
+template <class T>
+struct some_alloc2
+{
+    typedef T value_type;
+    
+    some_alloc2() {}
+    some_alloc2(const some_alloc2&);
+    void deallocate(void*, unsigned) {}
+
+    typedef std::false_type propagate_on_container_swap;
+    typedef std::true_type is_always_equal;
+};
+
 int main()
 {
 #if __has_feature(cxx_noexcept)
@@ -48,7 +65,21 @@ int main()
     {
         typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
         C c1, c2;
+#if TEST_STD_VER >= 14
+    //  In c++14, if POCS is set, swapping the allocator is required not to throw
+        static_assert( noexcept(swap(c1, c2)), "");
+#else
         static_assert(!noexcept(swap(c1, c2)), "");
+#endif
     }
+#if TEST_STD_VER >= 14
+    {
+        typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C;
+        C c1, c2;
+    //  if the allocators are always equal, then the swap can be noexcept
+        static_assert( noexcept(swap(c1, c2)), "");
+    }
+#endif
+
 #endif
 }





More information about the cfe-commits mailing list