mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 12:02:36 +08:00
[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:
@@ -1053,6 +1053,9 @@ private:
|
|||||||
friend
|
friend
|
||||||
const _Up*
|
const _Up*
|
||||||
end(const valarray<_Up>& __v);
|
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))
|
_LIBCPP_EXTERN_TEMPLATE(_LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t))
|
||||||
@@ -2750,7 +2753,24 @@ valarray<_Tp>::valarray(size_t __n)
|
|||||||
: __begin_(0),
|
: __begin_(0),
|
||||||
__end_(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>
|
template <class _Tp>
|
||||||
@@ -2780,7 +2800,7 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2805,7 +2825,7 @@ valarray<_Tp>::valarray(const valarray& __v)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2842,7 +2862,7 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2870,7 +2890,7 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2899,7 +2919,7 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2928,7 +2948,7 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2957,7 +2977,7 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia)
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
@@ -2968,7 +2988,24 @@ template <class _Tp>
|
|||||||
inline
|
inline
|
||||||
valarray<_Tp>::~valarray()
|
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>
|
template <class _Tp>
|
||||||
@@ -2976,11 +3013,7 @@ valarray<_Tp>&
|
|||||||
valarray<_Tp>::operator=(const valarray& __v)
|
valarray<_Tp>::operator=(const valarray& __v)
|
||||||
{
|
{
|
||||||
if (this != &__v)
|
if (this != &__v)
|
||||||
{
|
return __assign_range(__v.__begin_, __v.__end_);
|
||||||
if (size() != __v.size())
|
|
||||||
resize(__v.size());
|
|
||||||
_VSTD::copy(__v.__begin_, __v.__end_, __begin_);
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2991,7 +3024,7 @@ inline
|
|||||||
valarray<_Tp>&
|
valarray<_Tp>&
|
||||||
valarray<_Tp>::operator=(valarray&& __v) _NOEXCEPT
|
valarray<_Tp>::operator=(valarray&& __v) _NOEXCEPT
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
__begin_ = __v.__begin_;
|
__begin_ = __v.__begin_;
|
||||||
__end_ = __v.__end_;
|
__end_ = __v.__end_;
|
||||||
__v.__begin_ = nullptr;
|
__v.__begin_ = nullptr;
|
||||||
@@ -3004,10 +3037,7 @@ inline
|
|||||||
valarray<_Tp>&
|
valarray<_Tp>&
|
||||||
valarray<_Tp>::operator=(initializer_list<value_type> __il)
|
valarray<_Tp>::operator=(initializer_list<value_type> __il)
|
||||||
{
|
{
|
||||||
if (size() != __il.size())
|
return __assign_range(__il.begin(), __il.end());
|
||||||
resize(__il.size());
|
|
||||||
_VSTD::copy(__il.begin(), __il.end(), __begin_);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _LIBCPP_CXX03_LANG
|
#endif // _LIBCPP_CXX03_LANG
|
||||||
@@ -3680,7 +3710,7 @@ valarray<_Tp>::apply(value_type __f(const value_type&)) const
|
|||||||
|
|
||||||
template <class _Tp>
|
template <class _Tp>
|
||||||
void
|
void
|
||||||
valarray<_Tp>::resize(size_t __n, value_type __x)
|
valarray<_Tp>::__clear()
|
||||||
{
|
{
|
||||||
if (__begin_ != nullptr)
|
if (__begin_ != nullptr)
|
||||||
{
|
{
|
||||||
@@ -3689,6 +3719,13 @@ valarray<_Tp>::resize(size_t __n, value_type __x)
|
|||||||
_VSTD::__libcpp_deallocate(__begin_);
|
_VSTD::__libcpp_deallocate(__begin_);
|
||||||
__begin_ = __end_ = nullptr;
|
__begin_ = __end_ = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class _Tp>
|
||||||
|
void
|
||||||
|
valarray<_Tp>::resize(size_t __n, value_type __x)
|
||||||
|
{
|
||||||
|
__clear();
|
||||||
if (__n)
|
if (__n)
|
||||||
{
|
{
|
||||||
__begin_ = __end_ = static_cast<value_type*>(_VSTD::__allocate(__n * sizeof(value_type)));
|
__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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
resize(0);
|
__clear();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||||
|
|||||||
@@ -17,6 +17,21 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
S() : x_(0) { default_ctor_called = true; }
|
||||||
|
S(int x) : x_(x) {}
|
||||||
|
int x_;
|
||||||
|
static bool default_ctor_called;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool S::default_ctor_called = false;
|
||||||
|
|
||||||
|
bool operator==(const S& lhs, const S& rhs)
|
||||||
|
{
|
||||||
|
return lhs.x_ == rhs.x_;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -56,4 +71,16 @@ int main()
|
|||||||
assert(v2[i][j] == v[i][j]);
|
assert(v2[i][j] == v[i][j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef S T;
|
||||||
|
T a[] = {T(1), T(2), T(3), T(4), T(5)};
|
||||||
|
const unsigned N = sizeof(a)/sizeof(a[0]);
|
||||||
|
std::valarray<T> v(a, N);
|
||||||
|
std::valarray<T> v2;
|
||||||
|
v2 = v;
|
||||||
|
assert(v2.size() == v.size());
|
||||||
|
for (std::size_t i = 0; i < v2.size(); ++i)
|
||||||
|
assert(v2[i] == v[i]);
|
||||||
|
assert(!S::default_ctor_called);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,21 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
S() : x_(0) { default_ctor_called = true; }
|
||||||
|
S(int x) : x_(x) {}
|
||||||
|
int x_;
|
||||||
|
static bool default_ctor_called;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool S::default_ctor_called = false;
|
||||||
|
|
||||||
|
bool operator==(const S& lhs, const S& rhs)
|
||||||
|
{
|
||||||
|
return lhs.x_ == rhs.x_;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -55,4 +70,15 @@ int main()
|
|||||||
assert(v2[i][j] == a[i][j]);
|
assert(v2[i][j] == a[i][j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef S T;
|
||||||
|
T a[] = {T(1), T(2), T(3), T(4), T(5)};
|
||||||
|
const unsigned N = sizeof(a)/sizeof(a[0]);
|
||||||
|
std::valarray<T> v2;
|
||||||
|
v2 = {T(1), T(2), T(3), T(4), T(5)};
|
||||||
|
assert(v2.size() == N);
|
||||||
|
for (std::size_t i = 0; i < v2.size(); ++i)
|
||||||
|
assert(v2[i] == a[i]);
|
||||||
|
assert(!S::default_ctor_called);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,13 @@
|
|||||||
#include <valarray>
|
#include <valarray>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
S() { ctor_called = true; }
|
||||||
|
static bool ctor_called;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool S::ctor_called = false;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -34,4 +41,9 @@ int main()
|
|||||||
std::valarray<std::valarray<double> > v;
|
std::valarray<std::valarray<double> > v;
|
||||||
assert(v.size() == 0);
|
assert(v.size() == 0);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
std::valarray<S> v;
|
||||||
|
assert(v.size() == 0);
|
||||||
|
assert(!S::ctor_called);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,15 @@
|
|||||||
#include <valarray>
|
#include <valarray>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
S() : x(1) {}
|
||||||
|
~S() { ++cnt_dtor; }
|
||||||
|
int x;
|
||||||
|
static size_t cnt_dtor;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t S::cnt_dtor = 0;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -36,4 +45,11 @@ int main()
|
|||||||
for (int i = 0; i < 100; ++i)
|
for (int i = 0; i < 100; ++i)
|
||||||
assert(v[i].size() == 0);
|
assert(v[i].size() == 0);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
std::valarray<S> v(100);
|
||||||
|
assert(v.size() == 100);
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
assert(v[i].x == 1);
|
||||||
|
}
|
||||||
|
assert(S::cnt_dtor == 100);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user