From: Eric Fiselier Date: Sun, 24 Jul 2016 03:51:39 +0000 (+0000) Subject: Implement P0040r3: Extending memory management tools X-Git-Tag: llvmorg-4.0.0-rc1~14379 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e4d9c316d2e7add22fb6640000f2f3a30ed31fc0;p=platform%2Fupstream%2Fllvm.git Implement P0040r3: Extending memory management tools llvm-svn: 276544 --- diff --git a/libcxx/include/memory b/libcxx/include/memory index 7a3281e..5cdb60f 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -180,6 +180,33 @@ template ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x); +template +void destroy_at(T* location); + +template + void destroy(ForwardIterator first, ForwardIterator last); + +template + ForwardIterator destroy_n(ForwardIterator first, Size n); + +template + ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result); + +template + pair uninitialized_move_n(InputIterator first, Size n, ForwardIterator result); + +template + void uninitialized_value_construct(ForwardIterator first, ForwardIterator last); + +template + ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n); + +template + void uninitialized_default_construct(ForwardIterator first, ForwardIterator last); + +template + ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n); + template struct auto_ptr_ref {}; template @@ -3671,6 +3698,87 @@ uninitialized_fill_n(_ForwardIterator __f, _Size __n, const _Tp& __x) return __f; } +#if _LIBCPP_STD_VER > 14 + +template +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; +} + +template +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; +} + + +template +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(); +} + +template +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; +} + + +template +inline _LIBCPP_INLINE_VISIBILITY +_ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __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; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +pair<_InputIt, _ForwardIt> +uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __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 +inline _LIBCPP_INLINE_VISIBILITY +void destroy_at(_Tp* __loc) { + _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at"); + __loc->~_Tp(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void destroy(_ForwardIterator __first, _ForwardIterator __last) { + for (; __first != __last; ++__first) + _VSTD::destroy_at(_VSTD::addressof(*__first)); +} + +template +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 + class _LIBCPP_EXCEPTION_ABI bad_weak_ptr : public std::exception { diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp new file mode 100644 index 0000000..2ad9d04 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void destroy(ForwardIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +int main() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_fill(p, p+N, Counted()); + assert(Counted::count == 5); + std::destroy(p, p+1); + p += 1; + assert(Counted::count == 4); + std::destroy(It(p), It(p + 4)); + assert(Counted::count == 0); +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp new file mode 100644 index 0000000..4d44e4e --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void destroy_at(_Tp*); + +#include +#include +#include + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +struct VCounted { + static int count; + static void reset() { count = 0; } + VCounted() { ++count; } + VCounted(VCounted const&) { ++count; } + virtual ~VCounted() { --count; } + friend void operator&(VCounted) = delete; +}; +int VCounted::count = 0; + +struct DCounted : VCounted { + friend void operator&(DCounted) = delete; +}; + +int main() +{ + { + void* mem1 = std::malloc(sizeof(Counted)); + void* mem2 = std::malloc(sizeof(Counted)); + assert(mem1 && mem2); + assert(Counted::count == 0); + Counted* ptr1 = ::new(mem1) Counted(); + Counted* ptr2 = ::new(mem2) Counted(); + assert(Counted::count == 2); + std::destroy_at(ptr1); + assert(Counted::count == 1); + std::destroy_at(ptr2); + assert(Counted::count == 0); + } + { + void* mem1 = std::malloc(sizeof(DCounted)); + void* mem2 = std::malloc(sizeof(DCounted)); + assert(mem1 && mem2); + assert(DCounted::count == 0); + DCounted* ptr1 = ::new(mem1) DCounted(); + DCounted* ptr2 = ::new(mem2) DCounted(); + assert(DCounted::count == 2); + assert(VCounted::count == 2); + std::destroy_at(ptr1); + assert(VCounted::count == 1); + std::destroy_at(ptr2); + assert(VCounted::count == 0); + } +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp new file mode 100644 index 0000000..d1eaca5 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// ForwardIt destroy_n(ForwardIt, Size s); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" + +struct Counted { + static int count; + static void reset() { count = 0; } + Counted() { ++count; } + Counted(Counted const&) { ++count; } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; + +int main() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_fill(p, p+N, Counted()); + assert(Counted::count == 5); + Counted* np = std::destroy_n(p, 1); + assert(np == p+1); + assert(Counted::count == 4); + p += 1; + It it = std::destroy_n(It(p), 4); + assert(it == It(p+4)); + assert(Counted::count == 0); +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp new file mode 100644 index 0000000..6bdb49c --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp @@ -0,0 +1,115 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void uninitialized_default_construct(ForwardIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + 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); +#endif +} + +void test_counted() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_default_construct(It(p), It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + std::uninitialized_default_construct(It(p+1), It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + std::uninitialized_default_construct(It(p), It(p+1)); + assert(pool[0] == -1); + assert(pool[1] == -1); + std::uninitialized_default_construct(It(p+1), It(p+N)); + assert(pool[1] == -1); + assert(pool[2] == -1); + assert(pool[3] == -1); + assert(pool[4] == -1); +} + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp new file mode 100644 index 0000000..f59ea82 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp @@ -0,0 +1,119 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void uninitialized_default_construct(ForwardIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + 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); +#endif +} + +void test_counted() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + It e = std::uninitialized_default_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + e = std::uninitialized_default_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + auto e = std::uninitialized_default_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(pool[0] == -1); + assert(pool[1] == -1); + e = std::uninitialized_default_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(pool[1] == -1); + assert(pool[2] == -1); + assert(pool[3] == -1); + assert(pool[4] == -1); +} + + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp new file mode 100644 index 0000000..3f73b60 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void uninitialized_value_construct(ForwardIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + 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); +#endif +} + +void test_counted() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + std::uninitialized_value_construct(It(p), It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + std::uninitialized_value_construct(It(p+1), It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + std::uninitialized_value_construct(It(p), It(p+1)); + assert(pool[0] == 0); + assert(pool[1] == -1); + std::uninitialized_value_construct(It(p+1), It(p+N)); + assert(pool[1] == 0); + assert(pool[2] == 0); + assert(pool[3] == 0); + assert(pool[4] == 0); +} + +int main() +{ + test_counted(); + test_value_initialized(); + test_ctor_throws(); +} diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp new file mode 100644 index 0000000..65f9523 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// void uninitialized_value_construct(ForwardIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted() { ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted() { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_value_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); +#endif +} + +void test_counted() +{ + using It = forward_iterator; + const int N = 5; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + It e = std::uninitialized_value_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(Counted::count == 1); + assert(Counted::constructed = 1); + e = std::uninitialized_value_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +void test_value_initialized() +{ + using It = forward_iterator; + const int N = 5; + int pool[N] = {-1, -1, -1, -1, -1}; + int* p = pool; + It e = std::uninitialized_value_construct_n(It(p), 1); + assert(e == It(p+1)); + assert(pool[0] == 0); + assert(pool[1] == -1); + e = std::uninitialized_value_construct_n(It(p+1), 4); + assert(e == It(p+N)); + assert(pool[1] == 0); + assert(pool[2] == 0); + assert(pool[3] == 0); + assert(pool[4] == 0); +} + +int main() +{ + test_counted(); + test_value_initialized(); +} \ No newline at end of file diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp new file mode 100644 index 0000000..51fb06b --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// ForwardIt uninitialized_move(InputIt, InputIt, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; + int value; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted(int&& x) { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + x = 0; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_move(values, values + N, It(p)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 3); + 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 +} + +void test_counted() +{ + using It = input_iterator; + using FIt = forward_iterator; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + auto ret = std::uninitialized_move(It(values), It(values + 1), FIt(p)); + assert(ret == FIt(p +1)); + assert(Counted::constructed = 1); + assert(Counted::count == 1); + assert(p[0].value == 1); + assert(values[0] == 0); + ret = std::uninitialized_move(It(values+1), It(values+N), FIt(p+1)); + assert(ret == FIt(p + N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + assert(p[1].value == 2); + assert(p[2].value == 3); + assert(p[3].value == 4); + assert(p[4].value == 5); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 0); + assert(values[4] == 0); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +int main() { + test_counted(); + test_ctor_throws(); +} \ No newline at end of file diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp new file mode 100644 index 0000000..58866e1 --- /dev/null +++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template +// pair uninitialized_move_n(InputIt, Size, ForwardIt); + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_throw.h" + +struct Counted { + static int count; + static int constructed; + static void reset() { count = constructed = 0; } + explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; } + Counted(Counted const&) { assert(false); } + ~Counted() { --count; } + friend void operator&(Counted) = delete; + int value; +}; +int Counted::count = 0; +int Counted::constructed = 0; + +struct ThrowsCounted { + static int count; + static int constructed; + static int throw_after; + static void reset() { throw_after = count = constructed = 0; } + explicit ThrowsCounted(int&& x) { + ++constructed; + if (throw_after > 0 && --throw_after == 0) { + test_throw(); + } + ++count; + x = 0; + } + ThrowsCounted(ThrowsCounted const&) { assert(false); } + ~ThrowsCounted() { --count; } + friend void operator&(ThrowsCounted) = delete; +}; +int ThrowsCounted::count = 0; +int ThrowsCounted::constructed = 0; +int ThrowsCounted::throw_after = 0; + +void test_ctor_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using It = forward_iterator; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {}; + ThrowsCounted* p = (ThrowsCounted*)pool; + try { + ThrowsCounted::throw_after = 4; + std::uninitialized_move_n(values, N, It(p)); + assert(false); + } catch (...) {} + assert(ThrowsCounted::count == 3); + 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 +} + +void test_counted() +{ + using It = input_iterator; + using FIt = forward_iterator; + const int N = 5; + int values[N] = {1, 2, 3, 4, 5}; + alignas(Counted) char pool[sizeof(Counted)*N] = {}; + Counted* p = (Counted*)pool; + auto ret = std::uninitialized_move_n(It(values), 1, FIt(p)); + assert(ret.first == It(values +1)); + assert(ret.second == FIt(p +1)); + assert(Counted::constructed = 1); + assert(Counted::count == 1); + assert(p[0].value == 1); + assert(values[0] == 0); + ret = std::uninitialized_move_n(It(values+1), N-1, FIt(p+1)); + assert(ret.first == It(values+N)); + assert(ret.second == FIt(p + N)); + assert(Counted::count == 5); + assert(Counted::constructed == 5); + assert(p[1].value == 2); + assert(p[2].value == 3); + assert(p[3].value == 4); + assert(p[4].value == 5); + assert(values[1] == 0); + assert(values[2] == 0); + assert(values[3] == 0); + assert(values[4] == 0); + std::destroy(p, p+N); + assert(Counted::count == 0); +} + +int main() +{ + test_counted(); + test_ctor_throws(); +} \ No newline at end of file diff --git a/libcxx/test/support/test_throw.h b/libcxx/test/support/test_throw.h new file mode 100644 index 0000000..805cb04 --- /dev/null +++ b/libcxx/test/support/test_throw.h @@ -0,0 +1,27 @@ +// -*- C++ -*- +//===---------------------------- test_macros.h ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_TEST_THROW_H +#define SUPPORT_TEST_THROW_H + +#include "test_macros.h" +#include + +template +TEST_NORETURN +inline void test_throw() { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw Ex(); +#else + std::abort(); +#endif +} + +#endif // SUPPORT_TEST_THROW_H diff --git a/libcxx/www/cxx1z_status.html b/libcxx/www/cxx1z_status.html index 9ce2e00..3af3806 100644 --- a/libcxx/www/cxx1z_status.html +++ b/libcxx/www/cxx1z_status.html @@ -95,7 +95,7 @@ P0077R2LWGis_callable, the missing INVOKE related traitJacksonvilleComplete3.9 p0032r3LWGHomogeneous interface for variant, any and optionalOulu - p0040r3LWGExtending memory management toolsOulu + p0040r3LWGExtending memory management toolsOuluComplete4.0 p0063r3LWGC++17 should refer to C11 instead of C99Oulu p0067r3LWGElementary string conversionsOuluPostponed to Issaquah p0083r3LWGSplicing Maps and SetsOulu