1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // <memory>
12 
13 // template <class ForwardIt>
14 // void uninitialized_value_construct(ForwardIt, ForwardIt);
15 
16 #include <memory>
17 #include <cstdlib>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 #include "test_iterators.h"
22 
23 struct Counted {
24   static int count;
25   static int constructed;
resetCounted26   static void reset() { count = constructed =  0; }
CountedCounted27   explicit Counted() { ++count; ++constructed; }
CountedCounted28   Counted(Counted const&) { assert(false); }
~CountedCounted29   ~Counted() { assert(count > 0); --count; }
30   friend void operator&(Counted) = delete;
31 };
32 int Counted::count = 0;
33 int Counted::constructed = 0;
34 
35 
36 struct ThrowsCounted {
37   static int count;
38   static int constructed;
39   static int throw_after;
resetThrowsCounted40   static void reset() { throw_after = count = constructed =  0; }
ThrowsCountedThrowsCounted41   explicit ThrowsCounted() {
42       ++constructed;
43       if (throw_after > 0 && --throw_after == 0) {
44           TEST_THROW(1);
45       }
46       ++count;
47   }
ThrowsCountedThrowsCounted48   ThrowsCounted(ThrowsCounted const&) { assert(false); }
~ThrowsCountedThrowsCounted49   ~ThrowsCounted() { assert(count > 0); --count; }
50   friend void operator&(ThrowsCounted) = delete;
51 };
52 int ThrowsCounted::count = 0;
53 int ThrowsCounted::constructed = 0;
54 int ThrowsCounted::throw_after = 0;
55 
test_ctor_throws()56 void test_ctor_throws()
57 {
58 #ifndef TEST_HAS_NO_EXCEPTIONS
59     using It = forward_iterator<ThrowsCounted*>;
60     const int N = 5;
61     alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {};
62     ThrowsCounted* p = (ThrowsCounted*)pool;
63     try {
64         ThrowsCounted::throw_after = 4;
65         std::uninitialized_value_construct(It(p), It(p+N));
66         assert(false);
67     } catch (...) {}
68     assert(ThrowsCounted::count == 0);
69     assert(ThrowsCounted::constructed == 4); // forth construction throws
70 #endif
71 }
72 
test_counted()73 void test_counted()
74 {
75     using It = forward_iterator<Counted*>;
76     const int N = 5;
77     alignas(Counted) char pool[sizeof(Counted)*N] = {};
78     Counted* p = (Counted*)pool;
79     std::uninitialized_value_construct(It(p), It(p+1));
80     assert(Counted::count == 1);
81     assert(Counted::constructed == 1);
82     std::uninitialized_value_construct(It(p+1), It(p+N));
83     assert(Counted::count == 5);
84     assert(Counted::constructed == 5);
85     std::destroy(p, p+N);
86     assert(Counted::count == 0);
87 }
88 
test_value_initialized()89 void test_value_initialized()
90 {
91     using It = forward_iterator<int*>;
92     const int N = 5;
93     int pool[N] = {-1, -1, -1, -1, -1};
94     int* p = pool;
95     std::uninitialized_value_construct(It(p), It(p+1));
96     assert(pool[0] == 0);
97     assert(pool[1] == -1);
98     std::uninitialized_value_construct(It(p+1), It(p+N));
99     assert(pool[1] == 0);
100     assert(pool[2] == 0);
101     assert(pool[3] == 0);
102     assert(pool[4] == 0);
103 }
104 
main(int,char **)105 int main(int, char**)
106 {
107     test_counted();
108     test_value_initialized();
109     test_ctor_throws();
110 
111   return 0;
112 }
113