Implement P0040r3: Extending memory management tools
authorEric Fiselier <eric@efcs.ca>
Sun, 24 Jul 2016 03:51:39 +0000 (03:51 +0000)
committerEric Fiselier <eric@efcs.ca>
Sun, 24 Jul 2016 03:51:39 +0000 (03:51 +0000)
llvm-svn: 276544

12 files changed:
libcxx/include/memory
libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_at.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/specialized.destroy/destroy_n.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp [new file with mode: 0644]
libcxx/test/support/test_throw.h [new file with mode: 0644]
libcxx/www/cxx1z_status.html

index 7a3281e..5cdb60f 100644 (file)
@@ -180,6 +180,33 @@ template <class ForwardIterator, class Size, class T>
 ForwardIterator
 uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
 
+template <class T>
+void destroy_at(T* location);
+
+template <class ForwardIterator>
+ void destroy(ForwardIterator first, ForwardIterator last);
+
+template <class ForwardIterator, class Size>
+ ForwardIterator destroy_n(ForwardIterator first, Size n);
+
+template <class InputIterator, class ForwardIterator>
+ ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result);
+
+template <class InputIterator, class Size, class ForwardIterator>
+ pair<InputIterator,ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
+
+template <class ForwardIterator>
+ void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
+
+template <class ForwardIterator, class Size>
+ ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
+
+template <class ForwardIterator>
+ void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
+
+template <class ForwardIterator, class Size>
+ ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
+
 template <class Y> struct auto_ptr_ref {};
 
 template<class X>
@@ -3671,6 +3698,87 @@ uninitialized_fill_n(_ForwardIterator __f, _Size __n, const _Tp& __x)
     return __f;
 }
 
+#if _LIBCPP_STD_VER > 14
+
+template <class _ForwardIterator>
+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 <class _ForwardIterator, class _Size>
+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 <class _ForwardIterator>
+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 <class _ForwardIterator, class _Size>
+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 <class _InputIt, class _ForwardIt>
+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 <class _InputIt, class _Size, class _ForwardIt>
+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 <class _Tp>
+inline _LIBCPP_INLINE_VISIBILITY
+void destroy_at(_Tp* __loc) {
+    _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at");
+    __loc->~_Tp();
+}
+
+template <class _ForwardIterator>
+inline _LIBCPP_INLINE_VISIBILITY
+void destroy(_ForwardIterator __first, _ForwardIterator __last) {
+    for (; __first != __last; ++__first)
+        _VSTD::destroy_at(_VSTD::addressof(*__first));
+}
+
+template <class _ForwardIterator, class _Size>
+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 (file)
index 0000000..2ad9d04
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt>
+// void destroy(ForwardIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<Counted*>;
+    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 (file)
index 0000000..4d44e4e
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class _Tp>
+// void destroy_at(_Tp*);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+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 (file)
index 0000000..d1eaca5
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt, class Size>
+// ForwardIt destroy_n(ForwardIt, Size s);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<Counted*>;
+    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 (file)
index 0000000..6bdb49c
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt>
+// void uninitialized_default_construct(ForwardIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<Counted*>;
+    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<int*>;
+    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 (file)
index 0000000..f59ea82
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt>
+// void uninitialized_default_construct(ForwardIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<Counted*>;
+    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<int*>;
+    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 (file)
index 0000000..3f73b60
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt>
+// void uninitialized_value_construct(ForwardIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<Counted*>;
+    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<int*>;
+    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 (file)
index 0000000..65f9523
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class ForwardIt>
+// void uninitialized_value_construct(ForwardIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<Counted*>;
+    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<int*>;
+    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 (file)
index 0000000..51fb06b
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class InputIt, class ForwardIt>
+// ForwardIt uninitialized_move(InputIt, InputIt, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<int*>;
+    using FIt = forward_iterator<Counted*>;
+    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 (file)
index 0000000..58866e1
--- /dev/null
@@ -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
+
+// <memory>
+
+// template <class InputIt, class Size, class ForwardIt>
+// pair<InputIt, ForwardIt> uninitialized_move_n(InputIt, Size, ForwardIt);
+
+#include <memory>
+#include <cstdlib>
+#include <cassert>
+
+#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<int>();
+      }
+      ++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<ThrowsCounted*>;
+    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<int*>;
+    using FIt = forward_iterator<Counted*>;
+    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 (file)
index 0000000..805cb04
--- /dev/null
@@ -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 <cstdlib>
+
+template <class Ex>
+TEST_NORETURN
+inline void test_throw() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+       throw Ex();
+#else
+       std::abort();
+#endif
+}
+
+#endif // SUPPORT_TEST_THROW_H
index 9ce2e00..3af3806 100644 (file)
@@ -95,7 +95,7 @@
        <tr><td><a href="http://wg21.link/P0077R2">P0077R2</a></td><td>LWG</td><td><tt>is_callable</tt>, the missing INVOKE related trait</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
        <tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
        <tr><td><a href="http://wg21.link/p0032r3">p0032r3</a></td><td>LWG</td><td>Homogeneous interface for variant, any and optional</td><td>Oulu</td><td></td><td></td></tr>
-       <tr><td><a href="http://wg21.link/p0040r3">p0040r3</a></td><td>LWG</td><td>Extending memory management tools</td><td>Oulu</td><td></td><td></td></tr>
+       <tr><td><a href="http://wg21.link/p0040r3">p0040r3</a></td><td>LWG</td><td>Extending memory management tools</td><td>Oulu</td><td>Complete</td><td>4.0</td></tr>
        <tr><td><a href="http://wg21.link/p0063r3">p0063r3</a></td><td>LWG</td><td>C++17 should refer to C11 instead of C99</td><td>Oulu</td><td></td><td></td></tr>
        <tr><td><a href="http://wg21.link/p0067r3">p0067r3</a></td><td>LWG</td><td>Elementary string conversions</td><td>Oulu</td><td>Postponed to Issaquah</td><td></td></tr>
        <tr><td><a href="http://wg21.link/p0083r3">p0083r3</a></td><td>LWG</td><td>Splicing Maps and Sets</td><td>Oulu</td><td></td><td></td></tr>