From b965fed10bc47c74ed491717af082ecf5c8b815b Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Fri, 3 Jun 2011 16:20:53 +0000 Subject: [PATCH] noexcept for . git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@132553 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/deque | 2 +- include/forward_list | 84 ++++++++++++++----- .../deque/deque.cons/dtor_noexcept.pass.cpp | 4 + .../default_noexcept.pass.cpp | 50 +++++++++++ .../forwardlist.cons/dtor_noexcept.pass.cpp | 52 ++++++++++++ .../move_assign_noexcept.pass.cpp | 52 ++++++++++++ .../forwardlist.cons/move_noexcept.pass.cpp | 50 +++++++++++ .../forwardlist.spec/swap_noexcept.pass.cpp | 60 +++++++++++++ 8 files changed, 334 insertions(+), 20 deletions(-) create mode 100644 test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp create mode 100644 test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp create mode 100644 test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp create mode 100644 test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp create mode 100644 test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp diff --git a/include/deque b/include/deque index 71fa7f845..6ada42a66 100644 --- a/include/deque +++ b/include/deque @@ -948,7 +948,7 @@ public: #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES void swap(__deque_base& __c) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value); protected: void clear() _NOEXCEPT; diff --git a/include/forward_list b/include/forward_list index 1babc8f2b..2387bcebe 100644 --- a/include/forward_list +++ b/include/forward_list @@ -34,7 +34,8 @@ public: typedef
iterator; typedef
const_iterator; - forward_list(); + forward_list() + noexcept(is_nothrow_default_constructible::value); explicit forward_list(const allocator_type& a); explicit forward_list(size_type n); forward_list(size_type n, const value_type& v); @@ -45,7 +46,8 @@ public: forward_list(InputIterator first, InputIterator last, const allocator_type& a); forward_list(const forward_list& x); forward_list(const forward_list& x, const allocator_type& a); - forward_list(forward_list&& x); + forward_list(forward_list&& x) + noexcept(is_nothrow_move_constructible::value); forward_list(forward_list&& x, const allocator_type& a); forward_list(initializer_list il); forward_list(initializer_list il, const allocator_type& a); @@ -53,7 +55,10 @@ public: ~forward_list(); forward_list& operator=(const forward_list& x); - forward_list& operator=(forward_list&& x); + forward_list& operator=(forward_list&& x) + noexcept( + allocator_type::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value); forward_list& operator=(initializer_list il); template @@ -100,7 +105,9 @@ public: iterator erase_after(const_iterator p); iterator erase_after(const_iterator first, const_iterator last); - void swap(forward_list& x); + void swap(forward_list& x) + noexcept(!allocator_type::propagate_on_container_swap::value || + __is_nothrow_swappable::value); void resize(size_type n); void resize(size_type n, const value_type& v); @@ -152,7 +159,8 @@ template const forward_list& y); template - void swap(forward_list& x, forward_list& y); + void swap(forward_list& x, forward_list& y) + noexcept(x.swap(y)); } // std @@ -370,7 +378,8 @@ protected: static_cast(__before_begin_.first()));} _LIBCPP_INLINE_VISIBILITY - __node_allocator& __alloc() {return __before_begin_.second();} + __node_allocator& __alloc() _NOEXCEPT + {return __before_begin_.second();} _LIBCPP_INLINE_VISIBILITY const __node_allocator& __alloc() const _NOEXCEPT {return __before_begin_.second();} @@ -380,23 +389,27 @@ protected: _LIBCPP_INLINE_VISIBILITY __forward_list_base() + _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) : __before_begin_(__begin_node()) {} _LIBCPP_INLINE_VISIBILITY __forward_list_base(const allocator_type& __a) : __before_begin_(__begin_node(), __node_allocator(__a)) {} #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - __forward_list_base(__forward_list_base&& __x); +public: + __forward_list_base(__forward_list_base&& __x) + _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value); __forward_list_base(__forward_list_base&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES private: __forward_list_base(const __forward_list_base&); __forward_list_base& operator=(const __forward_list_base&); -protected: +public: ~__forward_list_base(); +protected: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __forward_list_base& __x) {__copy_assign_alloc(__x, integral_constant::value) {__move_assign_alloc(__x, integral_constant());} - void swap(__forward_list_base& __x); +public: + void swap(__forward_list_base& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value); +protected: void clear() _NOEXCEPT; private: @@ -422,22 +441,28 @@ private: } _LIBCPP_INLINE_VISIBILITY - void __move_assign_alloc(__forward_list_base& __x, false_type) {} + void __move_assign_alloc(__forward_list_base& __x, false_type) _NOEXCEPT + {} _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__forward_list_base& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {__alloc() = _STD::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());} _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 _STD::swap; swap(__x, __y); @@ -449,6 +474,7 @@ private: template inline _LIBCPP_INLINE_VISIBILITY __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x) + _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value) : __before_begin_(_STD::move(__x.__before_begin_)) { __x.__before_begin()->__next_ = nullptr; @@ -479,6 +505,8 @@ template 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) { __swap_alloc(__alloc(), __x.__alloc()); using _STD::swap; @@ -505,6 +533,11 @@ class _LIBCPP_VISIBLE forward_list : private __forward_list_base<_Tp, _Alloc> { typedef __forward_list_base<_Tp, _Alloc> base; + typedef typename base::__node_allocator __node_allocator; + typedef typename base::__node __node; + typedef typename base::__node_traits __node_traits; + typedef typename base::__node_pointer __node_pointer; + public: typedef _Tp value_type; typedef _Alloc allocator_type; @@ -519,7 +552,10 @@ public: typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; - _LIBCPP_INLINE_VISIBILITY forward_list() {} // = default; + _LIBCPP_INLINE_VISIBILITY + forward_list() + _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) + {} // = default; explicit forward_list(const allocator_type& __a); explicit forward_list(size_type __n); forward_list(size_type __n, const value_type& __v); @@ -539,7 +575,9 @@ public: forward_list(const forward_list& __x, const allocator_type& __a); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES _LIBCPP_INLINE_VISIBILITY - forward_list(forward_list&& __x) : base(_STD::move(__x)) {} + forward_list(forward_list&& __x) + _NOEXCEPT_(is_nothrow_move_constructible::value) + : base(_STD::move(__x)) {} forward_list(forward_list&& __x, const allocator_type& __a); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES forward_list(initializer_list __il); @@ -549,7 +587,10 @@ public: forward_list& operator=(const forward_list& __x); #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - forward_list& operator=(forward_list&& __x); + forward_list& operator=(forward_list&& __x) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value); #endif forward_list& operator=(initializer_list __il); @@ -643,7 +684,10 @@ public: iterator erase_after(const_iterator __f, const_iterator __l); _LIBCPP_INLINE_VISIBILITY - void swap(forward_list& __x) {base::swap(__x);} + void swap(forward_list& __x) + _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) + {base::swap(__x);} void resize(size_type __n); void resize(size_type __n, const value_type& __v); @@ -685,13 +729,10 @@ public: void reverse() _NOEXCEPT; private: - typedef typename base::__node_allocator __node_allocator; - typedef typename base::__node __node; - typedef typename base::__node_traits __node_traits; - typedef typename base::__node_pointer __node_pointer; #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES - void __move_assign(forward_list& __x, true_type); + void __move_assign(forward_list& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable::value); void __move_assign(forward_list& __x, false_type); #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -833,6 +874,7 @@ forward_list<_Tp, _Alloc>::operator=(const forward_list& __x) template void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, true_type) + _NOEXCEPT_(is_nothrow_move_assignable::value) { clear(); base::__move_assign_alloc(__x); @@ -857,6 +899,9 @@ template inline _LIBCPP_INLINE_VISIBILITY forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(forward_list&& __x) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value) { __move_assign(__x, integral_constant()); @@ -1557,6 +1602,7 @@ template inline _LIBCPP_INLINE_VISIBILITY void swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) { __x.swap(__y); } diff --git a/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp b/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp index 491e906b0..15e082e45 100644 --- a/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp +++ b/test/containers/sequences/deque/deque.cons/dtor_noexcept.pass.cpp @@ -17,6 +17,8 @@ #include "../../../MoveOnly.h" #include "../../../test_allocator.h" +#if __has_feature(cxx_noexcept) + template struct some_alloc { @@ -25,6 +27,8 @@ struct some_alloc ~some_alloc() noexcept(false); }; +#endif + int main() { #if __has_feature(cxx_noexcept) diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp new file mode 100644 index 000000000..2236048d0 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/default_noexcept.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// forward_list() +// noexcept(is_nothrow_default_constructible::value); + +// This tests a conforming extension + +#include +#include + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list C; + static_assert(std::is_nothrow_default_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_default_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_default_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_default_constructible::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp new file mode 100644 index 000000000..9f12ced1e --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/dtor_noexcept.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// ~forward_list() // implied noexcept; + +#include +#include + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +#if __has_feature(cxx_noexcept) + +template +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); + ~some_alloc() noexcept(false); +}; + +#endif + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list C; + static_assert(std::is_nothrow_destructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_destructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_destructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_destructible::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp new file mode 100644 index 000000000..b19e6dcfe --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/move_assign_noexcept.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// forward_list& operator=(forward_list&& c) +// noexcept( +// allocator_type::propagate_on_container_move_assignment::value && +// is_nothrow_move_assignable::value); + +// This tests a conforming extension + +#include +#include + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list C; + static_assert(std::is_nothrow_move_assignable::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_move_assignable::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_move_assignable::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_move_assignable::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp new file mode 100644 index 000000000..d3a3d5237 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.cons/move_noexcept.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// forward_list(forward_list&&) +// noexcept(is_nothrow_move_constructible::value); + +// This tests a conforming extension + +#include +#include + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template +struct some_alloc +{ + typedef T value_type; + some_alloc(const some_alloc&); +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list C; + static_assert(std::is_nothrow_move_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_move_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(std::is_nothrow_move_constructible::value, ""); + } + { + typedef std::forward_list> C; + static_assert(!std::is_nothrow_move_constructible::value, ""); + } +#endif +} diff --git a/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp b/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp new file mode 100644 index 000000000..777a66688 --- /dev/null +++ b/test/containers/sequences/forwardlist/forwardlist.spec/swap_noexcept.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// void swap(forward_list& c) +// noexcept(!allocator_type::propagate_on_container_swap::value || +// __is_nothrow_swappable::value); + +// This tests a conforming extension + +#include +#include + +#include "../../../MoveOnly.h" +#include "../../../test_allocator.h" + +template +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; +}; + +int main() +{ +#if __has_feature(cxx_noexcept) + { + typedef std::forward_list C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list> C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list> C; + C c1, c2; + static_assert(noexcept(swap(c1, c2)), ""); + } + { + typedef std::forward_list> C; + C c1, c2; + static_assert(!noexcept(swap(c1, c2)), ""); + } +#endif +}