1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03, c++11, c++14
11
12// <memory>
13
14// template <class InputIt, class Size, class ForwardIt>
15// pair<InputIt, ForwardIt> uninitialized_move_n(InputIt, Size, ForwardIt);
16
17#include <memory>
18#include <cstdlib>
19#include <cassert>
20
21#include "test_macros.h"
22#include "test_iterators.h"
23
24struct Counted {
25  static int count;
26  static int constructed;
27  static void reset() { count = constructed =  0; }
28  explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; }
29  Counted(Counted const&) { assert(false); }
30  ~Counted() { assert(count > 0); --count; }
31  friend void operator&(Counted) = delete;
32  int value;
33};
34int Counted::count = 0;
35int Counted::constructed = 0;
36
37struct ThrowsCounted {
38  static int count;
39  static int constructed;
40  static int throw_after;
41  static void reset() { throw_after = count = constructed =  0; }
42  explicit ThrowsCounted(int&& x) {
43      ++constructed;
44      if (throw_after > 0 && --throw_after == 0) {
45        TEST_THROW(1);
46      }
47      ++count;
48      x = 0;
49  }
50  ThrowsCounted(ThrowsCounted const&) { assert(false); }
51  ~ThrowsCounted() { assert(count > 0); --count; }
52  friend void operator&(ThrowsCounted) = delete;
53};
54int ThrowsCounted::count = 0;
55int ThrowsCounted::constructed = 0;
56int ThrowsCounted::throw_after = 0;
57
58void test_ctor_throws()
59{
60#ifndef TEST_HAS_NO_EXCEPTIONS
61    using It = forward_iterator<ThrowsCounted*>;
62    const int N = 5;
63    int values[N] = {1, 2, 3, 4, 5};
64    alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {};
65    ThrowsCounted* p = (ThrowsCounted*)pool;
66    try {
67        ThrowsCounted::throw_after = 4;
68        std::uninitialized_move_n(values, N, It(p));
69        assert(false);
70    } catch (...) {}
71    assert(ThrowsCounted::count == 0);
72    assert(ThrowsCounted::constructed == 4); // forth construction throws
73    assert(values[0] == 0);
74    assert(values[1] == 0);
75    assert(values[2] == 0);
76    assert(values[3] == 4);
77    assert(values[4] == 5);
78#endif
79}
80
81void test_counted()
82{
83    using It = input_iterator<int*>;
84    using FIt = forward_iterator<Counted*>;
85    const int N = 5;
86    int values[N] = {1, 2, 3, 4, 5};
87    alignas(Counted) char pool[sizeof(Counted)*N] = {};
88    Counted* p = (Counted*)pool;
89    auto ret = std::uninitialized_move_n(It(values), 1, FIt(p));
90    assert(ret.first == It(values +1));
91    assert(ret.second == FIt(p +1));
92    assert(Counted::constructed == 1);
93    assert(Counted::count == 1);
94    assert(p[0].value == 1);
95    assert(values[0] == 0);
96    ret = std::uninitialized_move_n(It(values+1), N-1, FIt(p+1));
97    assert(ret.first == It(values+N));
98    assert(ret.second == FIt(p + N));
99    assert(Counted::count == 5);
100    assert(Counted::constructed == 5);
101    assert(p[1].value == 2);
102    assert(p[2].value == 3);
103    assert(p[3].value == 4);
104    assert(p[4].value == 5);
105    assert(values[1] == 0);
106    assert(values[2] == 0);
107    assert(values[3] == 0);
108    assert(values[4] == 0);
109    std::destroy(p, p+N);
110    assert(Counted::count == 0);
111}
112
113int main()
114{
115    test_counted();
116    test_ctor_throws();
117}