Author: ericwf Date: Tue Oct 11 16:13:44 2016 New Revision: 283941 URL: http://llvm.org/viewvc/llvm-project?rev=283941&view=rev Log: Fix incorrect exception handling behavior in the uninitialized algorithms
Modified: libcxx/trunk/include/memory libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Tue Oct 11 16:13:44 2016 @@ -3709,21 +3709,63 @@ uninitialized_fill_n(_ForwardIterator __ #if _LIBCPP_STD_VER > 14 +template <class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +void destroy_at(_Tp* __loc) { + _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at"); + __loc->~_Tp(); +} + +template <class _ForwardIterator> +inline _LIBCPP_INLINE_VISIBILITY +void destroy(_ForwardIterator __first, _ForwardIterator __last) { + for (; __first != __last; ++__first) + _VSTD::destroy_at(_VSTD::addressof(*__first)); +} + +template <class _ForwardIterator, class _Size> +inline _LIBCPP_INLINE_VISIBILITY +_ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { + for (; __n > 0; (void)++__first, --__n) + _VSTD::destroy_at(_VSTD::addressof(*__first)); + return __first; +} + template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) { using _Vt = typename iterator_traits<_ForwardIterator>::value_type; - for (; __first != __last; ++__first) - ::new((void*)_VSTD::addressof(*__first)) _Vt; + auto __idx = __first; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __idx != __last; ++__idx) + ::new((void*)_VSTD::addressof(*__idx)) _Vt; +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first, __idx); + throw; + } +#endif } template <class _ForwardIterator, class _Size> inline _LIBCPP_INLINE_VISIBILITY _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { using _Vt = typename iterator_traits<_ForwardIterator>::value_type; - for (; __n > 0; (void)++__first, --__n) - ::new((void*)_VSTD::addressof(*__first)) _Vt; - return __first; + auto __idx = __first; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __n > 0; (void)++__idx, --__n) + ::new((void*)_VSTD::addressof(*__idx)) _Vt; + return __idx; +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first, __idx); + throw; + } +#endif } @@ -3731,60 +3773,79 @@ template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) { using _Vt = typename iterator_traits<_ForwardIterator>::value_type; - for (; __first != __last; ++__first) - ::new((void*)_VSTD::addressof(*__first)) _Vt(); + auto __idx = __first; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __idx != __last; ++__idx) + ::new((void*)_VSTD::addressof(*__idx)) _Vt(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first, __idx); + throw; + } +#endif } template <class _ForwardIterator, class _Size> inline _LIBCPP_INLINE_VISIBILITY _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { using _Vt = typename iterator_traits<_ForwardIterator>::value_type; - for (; __n > 0; (void)++__first, --__n) - ::new((void*)_VSTD::addressof(*__first)) _Vt(); - return __first; + auto __idx = __first; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __n > 0; (void)++__idx, --__n) + ::new((void*)_VSTD::addressof(*__idx)) _Vt(); + return __idx; +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first, __idx); + throw; + } +#endif } template <class _InputIt, class _ForwardIt> inline _LIBCPP_INLINE_VISIBILITY -_ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __res) { +_ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __first_res) { using _Vt = typename iterator_traits<_ForwardIt>::value_type; - for (; __first != __last; (void)++__res, ++__first) - ::new((void*)_VSTD::addressof(*__res)) _Vt(std::move(*__first)); - return __res; + auto __idx = __first_res; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __first != __last; (void)++__idx, ++__first) + ::new((void*)_VSTD::addressof(*__idx)) _Vt(std::move(*__first)); + return __idx; +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first_res, __idx); + throw; + } +#endif } template <class _InputIt, class _Size, class _ForwardIt> inline _LIBCPP_INLINE_VISIBILITY pair<_InputIt, _ForwardIt> -uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __res) { +uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __first_res) { using _Vt = typename iterator_traits<_ForwardIt>::value_type; - for (; __n > 0; ++__res, (void)++__first, --__n) - ::new((void*)_VSTD::addressof(*__res)) _Vt(std::move(*__first)); - return {__first, __res}; -} - -template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY -void destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at"); - __loc->~_Tp(); -} - -template <class _ForwardIterator> -inline _LIBCPP_INLINE_VISIBILITY -void destroy(_ForwardIterator __first, _ForwardIterator __last) { - for (; __first != __last; ++__first) - _VSTD::destroy_at(_VSTD::addressof(*__first)); + auto __idx = __first_res; +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif + for (; __n > 0; ++__idx, (void)++__first, --__n) + ::new((void*)_VSTD::addressof(*__idx)) _Vt(std::move(*__first)); + return {__first, __idx}; +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + _VSTD::destroy(__first_res, __idx); + throw; + } +#endif } -template <class _ForwardIterator, class _Size> -inline _LIBCPP_INLINE_VISIBILITY -_ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { - for (; __n > 0; (void)++__first, --__n) - _VSTD::destroy_at(_VSTD::addressof(*__first)); - return __first; -} #endif // _LIBCPP_STD_VER > 14 Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp Tue Oct 11 16:13:44 2016 @@ -47,7 +47,7 @@ struct ThrowsCounted { ++count; } ThrowsCounted(ThrowsCounted const&) { assert(false); } - ~ThrowsCounted() { --count; } + ~ThrowsCounted() { assert(count > 0); --count; } friend void operator&(ThrowsCounted) = delete; }; int ThrowsCounted::count = 0; @@ -67,10 +67,8 @@ void test_ctor_throws() std::uninitialized_default_construct(It(p), It(p+N)); assert(false); } catch (...) {} - assert(ThrowsCounted::count == 3); - assert(ThrowsCounted::constructed == 4); // forth construction throws - std::destroy(p, p+3); assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws #endif } Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp Tue Oct 11 16:13:44 2016 @@ -27,7 +27,7 @@ struct Counted { static void reset() { count = constructed = 0; } explicit Counted() { ++count; ++constructed; } Counted(Counted const&) { assert(false); } - ~Counted() { --count; } + ~Counted() { assert(count > 0); --count; } friend void operator&(Counted) = delete; }; int Counted::count = 0; @@ -47,7 +47,7 @@ struct ThrowsCounted { ++count; } ThrowsCounted(ThrowsCounted const&) { assert(false); } - ~ThrowsCounted() { --count; } + ~ThrowsCounted() { assert(count > 0); --count; } friend void operator&(ThrowsCounted) = delete; }; int ThrowsCounted::count = 0; @@ -66,10 +66,8 @@ void test_ctor_throws() std::uninitialized_default_construct_n(It(p), N); assert(false); } catch (...) {} - assert(ThrowsCounted::count == 3); - assert(ThrowsCounted::constructed == 4); // forth construction throws - std::destroy(p, p+3); assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws #endif } Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp Tue Oct 11 16:13:44 2016 @@ -27,7 +27,7 @@ struct Counted { static void reset() { count = constructed = 0; } explicit Counted() { ++count; ++constructed; } Counted(Counted const&) { assert(false); } - ~Counted() { --count; } + ~Counted() { assert(count > 0); --count; } friend void operator&(Counted) = delete; }; int Counted::count = 0; @@ -47,7 +47,7 @@ struct ThrowsCounted { ++count; } ThrowsCounted(ThrowsCounted const&) { assert(false); } - ~ThrowsCounted() { --count; } + ~ThrowsCounted() { assert(count > 0); --count; } friend void operator&(ThrowsCounted) = delete; }; int ThrowsCounted::count = 0; @@ -66,10 +66,8 @@ void test_ctor_throws() std::uninitialized_value_construct(It(p), It(p+N)); assert(false); } catch (...) {} - assert(ThrowsCounted::count == 3); - assert(ThrowsCounted::constructed == 4); // forth construction throws - std::destroy(p, p+3); assert(ThrowsCounted::count == 0); + assert(ThrowsCounted::constructed == 4); // forth construction throws #endif } Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp Tue Oct 11 16:13:44 2016 @@ -27,7 +27,7 @@ struct Counted { static void reset() { count = constructed = 0; } explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } Counted(Counted const&) { assert(false); } - ~Counted() { --count; } + ~Counted() { assert(count > 0); --count; } friend void operator&(Counted) = delete; int value; }; @@ -48,7 +48,7 @@ struct ThrowsCounted { x = 0; } ThrowsCounted(ThrowsCounted const&) { assert(false); } - ~ThrowsCounted() { --count; } + ~ThrowsCounted() { assert(count > 0); --count; } friend void operator&(ThrowsCounted) = delete; }; int ThrowsCounted::count = 0; @@ -68,15 +68,13 @@ void test_ctor_throws() std::uninitialized_move(values, values + N, It(p)); assert(false); } catch (...) {} - assert(ThrowsCounted::count == 3); + assert(ThrowsCounted::count == 0); assert(ThrowsCounted::constructed == 4); // forth construction throws assert(values[0] == 0); assert(values[1] == 0); assert(values[2] == 0); assert(values[3] == 4); assert(values[4] == 5); - std::destroy(p, p+3); - assert(ThrowsCounted::count == 0); #endif } Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp Tue Oct 11 16:13:44 2016 @@ -27,7 +27,7 @@ struct Counted { static void reset() { count = constructed = 0; } explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } Counted(Counted const&) { assert(false); } - ~Counted() { --count; } + ~Counted() { assert(count > 0); --count; } friend void operator&(Counted) = delete; int value; }; @@ -48,7 +48,7 @@ struct ThrowsCounted { x = 0; } ThrowsCounted(ThrowsCounted const&) { assert(false); } - ~ThrowsCounted() { --count; } + ~ThrowsCounted() { assert(count > 0); --count; } friend void operator&(ThrowsCounted) = delete; }; int ThrowsCounted::count = 0; @@ -68,15 +68,13 @@ void test_ctor_throws() std::uninitialized_move_n(values, N, It(p)); assert(false); } catch (...) {} - assert(ThrowsCounted::count == 3); + assert(ThrowsCounted::count == 0); assert(ThrowsCounted::constructed == 4); // forth construction throws assert(values[0] == 0); assert(values[1] == 0); assert(values[2] == 0); assert(values[3] == 4); assert(values[4] == 5); - std::destroy(p, p+3); - assert(ThrowsCounted::count == 0); #endif } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits