Re: [v3 PATCH] PR libstdc++/77619
On 18/09/16 21:07 +0300, Ville Voutilainen wrote: diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 3d12628..c7ca1f8 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -83,6 +83,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ::new(static_cast(__p)) _T1(__value); } #endif Blank line here please. + template +inline void +_Construct_novalue(_T1* __p) +{ ::new(static_cast(__p)) _T1; } /** * Destroy the object pointed to by a pointer type. diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index c5c81fb..b4213d5 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -640,6 +644,104 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION allocator<_Tp>&) { return std::__uninitialized_default_n(__first, __n); } + template +struct __uninitialized_default_novalue_1 +{ + template +static void +__uninit_default_novalue(_ForwardIterator __first, +_ForwardIterator __last) +{ ... + } The left brace is indented with spaces and the right one with a tab, might as well make them the same. +}; + + template<> +struct __uninitialized_default_novalue_1 +{ + template +static void +__uninit_default_novalue(_ForwardIterator __first, +_ForwardIterator __last) +{ + } Ditto. +}; + + template +struct __uninitialized_default_novalue_n_1 +{ + template +static _ForwardIterator +__uninit_default_novalue_n(_ForwardIterator __first, _Size __n) +{ + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } Ditto. +}; + + template<> +struct __uninitialized_default_novalue_n_1 +{ + template +static _ForwardIterator +__uninit_default_novalue_n(_ForwardIterator __first, _Size __n) +{ + } Ditto. +}; + + // __uninitialized_default_novalue + // Fills [first, last) with std::distance(first, last) default-initialized + // value_types(s). + template +inline void +__uninitialized_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) +{ + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; Aha! A non-whitespace comment ... __assignable isn't used. If it's not needed it can be removed. + std::__uninitialized_default_novalue_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue(__first, __last); +} + + // __uninitialized_default_n + // Fills [first, first + n) with n default-initialized value_type(s). + template +inline _ForwardIterator +__uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) +{ + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; Ditto. + return __uninitialized_default_novalue_n_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue_n(__first, __n); +} template @@ -669,6 +771,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION random_access_iterator_tag) { return std::uninitialized_copy(__first, __first + __n, __result); } + template +pair<_InputIterator, _ForwardIterator> +__uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) +{ + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return {__first, __cur}; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } +} + + template +inline pair<_RandomAccessIterator, _ForwardIterator> +__uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) +{ + auto second = uninitialized_copy(__first, __first + __n, __result); + auto first = std::next(__first, __n
[v3 PATCH] PR libstdc++/77619
Tested on Linux-x64. 2016-09-19 Ville Voutilainen PR libstdc++/77619 * include/bits/stl_construct.h: (_Construct_novalue): New. (_Destroy_n_aux, _Destroy_n): New. * include/bits/stl_uninitialized.h: (type_traits): New include in C++11 mode. (__uninitialized_default_novalue_1): New. (__uninitialized_default_novalue_n_1): Likewise. (__uninitialized_default_novalue): Likewise. (__uninitialized_default_novalue_n): Likewise. (__uninitialized_copy_n_pair): Likewise. (uninitialized_default_construct): Use __uninitialized_default_novalue. (uninitialized_default_construct_n): Use __uninitialized_default_novalue_n. (uninitialized_value_construct): Use __uninitialized_default. (uninitialized_value_construct_n): Use __uninitialized_default_n. (uninitialized_move): Use uninitialized_copy. (uninitialized_move_n): Use __uninitialized_copy_n_pair. (destroy_at): Use _Destroy. (destroy): Likewise. (destroy_n): Likewise. * testsuite/20_util/specialized_algorithms/ memory_management_tools/1.cc: Add tests for exceptions, add tests for trivial cases for construct and move. diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 3d12628..c7ca1f8 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -83,6 +83,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ::new(static_cast(__p)) _T1(__value); } #endif + template +inline void +_Construct_novalue(_T1* __p) +{ ::new(static_cast(__p)) _T1; } /** * Destroy the object pointed to by a pointer type. @@ -127,6 +131,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __destroy(__first, __last); } + template +struct _Destroy_n_aux +{ + template +static _ForwardIterator +__destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } +}; + + template<> +struct _Destroy_n_aux +{ + template +static _ForwardIterator +__destroy_n(_ForwardIterator __first, _Size __count) + { +std::advance(__first, __count); +return __first; + } +}; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template +inline _ForwardIterator +_Destroy_n(_ForwardIterator __first, _Size __count) +{ + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; + return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + __destroy_n(__first, __count); +} + /** * Destroy a range of objects using the supplied allocator. For * nondefault allocators we do not optimize away invocation of diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index c5c81fb..b4213d5 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -60,6 +60,10 @@ #include #endif +#if __cplusplus >= 201103L +#include +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -640,6 +644,104 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION allocator<_Tp>&) { return std::__uninitialized_default_n(__first, __n); } + template +struct __uninitialized_default_novalue_1 +{ + template +static void +__uninit_default_novalue(_ForwardIterator __first, +_ForwardIterator __last) +{ + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } +}; + + template<> +struct __uninitialized_default_novalue_1 +{ + template +static void +__uninit_default_novalue(_ForwardIterator __first, +_ForwardIterator __last) +{ + } +}; + + template +struct __uninitialized_default_novalue_n_1 +{ + template +static _ForwardIterator +__uninit_default_novalue_n(_ForwardIterator __first, _Size __n) +{ + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_