[libcxx] Avoid spurious construction of valarray elements

Summary:
Currently libc++ implements some operations on valarray by using the
resize method. This method has a parameter with a default value.
Because of this, valarray may spuriously construct and destruct
objects of valarray's element type.
    
This patch fixes this issue and adds corresponding test cases.


Reviewers: EricWF, mclow.lists

Reviewed By: mclow.lists

Subscribers: rogfer01, cfe-commits

Differential Revision: https://reviews.llvm.org/D41992

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@324596 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Maltsev
2018-02-08 11:33:48 +00:00
parent 4c153004af
commit 171ed2198d
5 changed files with 139 additions and 21 deletions

View File

@@ -1053,6 +1053,9 @@ private:
friend
const _Up*
end(const valarray<_Up>& __v);
void __clear();
valarray& __assign_range(const value_type* __f, const value_type* __l);
};
_LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t))
@@ -2750,7 +2753,24 @@ valarray<_Tp>::valarray(size_t __n)
: __begin_(0),
__end_(0)
{
resize(__n);
if (__n)
{
__begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
for (; __n; --__n, ++__end_)
::new (__end_) value_type();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
}
template <class _Tp>
@@ -2780,7 +2800,7 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2805,7 +2825,7 @@ valarray<_Tp>::valarray(const valarray& __v)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2842,7 +2862,7 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2870,7 +2890,7 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2899,7 +2919,7 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2928,7 +2948,7 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2957,7 +2977,7 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2968,7 +2988,24 @@ template <class _Tp>
inline
valarray<_Tp>::~valarray()
{
resize(0);
__clear();
}
template <class _Tp>
valarray<_Tp>&
valarray<_Tp>::__assign_range(const value_type* __f, const value_type* __l)
{
size_t __n = __l - __f;
if (size() != __n)
{
__clear();
__begin_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
__end_ = __begin_ + __n;
_VSTD::uninitialized_copy(__f, __l, __begin_);
} else {
_VSTD::copy(__f, __l, __begin_);
}
return *this;
}
template <class _Tp>
@@ -2976,11 +3013,7 @@ valarray<_Tp>&
valarray<_Tp>::operator=(const valarray& __v)
{
if (this != &__v)
{
if (size() != __v.size())
resize(__v.size());
_VSTD::copy(__v.__begin_, __v.__end_, __begin_);
}
return __assign_range(__v.__begin_, __v.__end_);
return *this;
}
@@ -2991,7 +3024,7 @@ inline
valarray<_Tp>&
valarray<_Tp>::operator=(valarray&& __v) _NOEXCEPT
{
resize(0);
__clear();
__begin_ = __v.__begin_;
__end_ = __v.__end_;
__v.__begin_ = nullptr;
@@ -3004,10 +3037,7 @@ inline
valarray<_Tp>&
valarray<_Tp>::operator=(initializer_list<value_type> __il)
{
if (size() != __il.size())
resize(__il.size());
_VSTD::copy(__il.begin(), __il.end(), __begin_);
return *this;
return __assign_range(__il.begin(), __il.end());
}
#endif // _LIBCPP_CXX03_LANG
@@ -3680,7 +3710,7 @@ valarray<_Tp>::apply(value_type __f(const value_type&)) const
template <class _Tp>
void
valarray<_Tp>::resize(size_t __n, value_type __x)
valarray<_Tp>::__clear()
{
if (__begin_ != nullptr)
{
@@ -3689,6 +3719,13 @@ valarray<_Tp>::resize(size_t __n, value_type __x)
_VSTD::__libcpp_deallocate(__begin_);
__begin_ = __end_ = nullptr;
}
}
template <class _Tp>
void
valarray<_Tp>::resize(size_t __n, value_type __x)
{
__clear();
if (__n)
{
__begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
@@ -3702,7 +3739,7 @@ valarray<_Tp>::resize(size_t __n, value_type __x)
}
catch (...)
{
resize(0);
__clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS