[libcxx] r324596 - [libcxx] Avoid spurious construction of valarray elements
Mikhail Maltsev via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 8 03:33:48 PST 2018
Author: miyuki
Date: Thu Feb 8 03:33:48 2018
New Revision: 324596
URL: http://llvm.org/viewvc/llvm-project?rev=324596&view=rev
Log:
[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
Modified:
libcxx/trunk/include/valarray
libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/copy_assign.pass.cpp
libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/initializer_list_assign.pass.cpp
libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/default.pass.cpp
libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/size.pass.cpp
Modified: libcxx/trunk/include/valarray
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/valarray?rev=324596&r1=324595&r2=324596&view=diff
==============================================================================
--- libcxx/trunk/include/valarray (original)
+++ libcxx/trunk/include/valarray Thu Feb 8 03:33:48 2018
@@ -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
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2805,7 +2825,7 @@ valarray<_Tp>::valarray(const valarray&
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2842,7 +2862,7 @@ valarray<_Tp>::valarray(initializer_list
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2870,7 +2890,7 @@ valarray<_Tp>::valarray(const slice_arra
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2899,7 +2919,7 @@ valarray<_Tp>::valarray(const gslice_arr
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2928,7 +2948,7 @@ valarray<_Tp>::valarray(const mask_array
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2957,7 +2977,7 @@ valarray<_Tp>::valarray(const indirect_a
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
@@ -2968,22 +2988,35 @@ template <class _Tp>
inline
valarray<_Tp>::~valarray()
{
- resize(0);
+ __clear();
}
template <class _Tp>
valarray<_Tp>&
-valarray<_Tp>::operator=(const valarray& __v)
+valarray<_Tp>::__assign_range(const value_type* __f, const value_type* __l)
{
- if (this != &__v)
+ size_t __n = __l - __f;
+ if (size() != __n)
{
- if (size() != __v.size())
- resize(__v.size());
- _VSTD::copy(__v.__begin_, __v.__end_, __begin_);
+ __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>
+valarray<_Tp>&
+valarray<_Tp>::operator=(const valarray& __v)
+{
+ if (this != &__v)
+ return __assign_range(__v.__begin_, __v.__end_);
+ return *this;
+}
+
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp>
@@ -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(cons
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_
_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_
}
catch (...)
{
- resize(0);
+ __clear();
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
Modified: libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/copy_assign.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/copy_assign.pass.cpp?rev=324596&r1=324595&r2=324596&view=diff
==============================================================================
--- libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/copy_assign.pass.cpp (original)
+++ libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/copy_assign.pass.cpp Thu Feb 8 03:33:48 2018
@@ -17,6 +17,21 @@
#include <cassert>
#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()
{
{
@@ -56,4 +71,16 @@ int main()
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);
+ }
}
Modified: libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/initializer_list_assign.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/initializer_list_assign.pass.cpp?rev=324596&r1=324595&r2=324596&view=diff
==============================================================================
--- libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/initializer_list_assign.pass.cpp (original)
+++ libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.assign/initializer_list_assign.pass.cpp Thu Feb 8 03:33:48 2018
@@ -19,6 +19,21 @@
#include <cassert>
#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()
{
{
@@ -55,4 +70,15 @@ int main()
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);
+ }
}
Modified: libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/default.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/default.pass.cpp?rev=324596&r1=324595&r2=324596&view=diff
==============================================================================
--- libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/default.pass.cpp (original)
+++ libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/default.pass.cpp Thu Feb 8 03:33:48 2018
@@ -16,6 +16,13 @@
#include <valarray>
#include <cassert>
+struct S {
+ S() { ctor_called = true; }
+ static bool ctor_called;
+};
+
+bool S::ctor_called = false;
+
int main()
{
{
@@ -34,4 +41,9 @@ int main()
std::valarray<std::valarray<double> > v;
assert(v.size() == 0);
}
+ {
+ std::valarray<S> v;
+ assert(v.size() == 0);
+ assert(!S::ctor_called);
+ }
}
Modified: libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/size.pass.cpp?rev=324596&r1=324595&r2=324596&view=diff
==============================================================================
--- libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/size.pass.cpp (original)
+++ libcxx/trunk/test/std/numerics/numarray/template.valarray/valarray.cons/size.pass.cpp Thu Feb 8 03:33:48 2018
@@ -16,6 +16,15 @@
#include <valarray>
#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()
{
{
@@ -36,4 +45,11 @@ int main()
for (int i = 0; i < 100; ++i)
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);
}
More information about the cfe-commits
mailing list