xref: /llvm-project/libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp (revision b9a2658a3e8bd13b0f9e7a8a440832a95b377216)
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: no-exceptions
10 
11 // (bug report: https://llvm.org/PR58392)
12 // Check that vector constructors don't leak memory when an operation inside the constructor throws an exception
13 
14 // XFAIL: FROZEN-CXX03-HEADERS-FIXME
15 
16 #include <cstddef>
17 #include <memory>
18 #include <type_traits>
19 #include <vector>
20 
21 #include "../common.h"
22 #include "count_new.h"
23 #include "test_allocator.h"
24 #include "test_iterators.h"
25 
26 int main(int, char**) {
27   using AllocVec = std::vector<int, throwing_allocator<int> >;
28   try { // vector()
29     AllocVec vec;
30   } catch (int) {
31   }
32   check_new_delete_called();
33 
34   try { // Throw in vector(size_type) from type
35     std::vector<throwing_t> get_alloc(1);
36   } catch (int) {
37   }
38   check_new_delete_called();
39 
40 #if TEST_STD_VER >= 14
41   try { // Throw in vector(size_type, value_type) from type
42     int throw_after = 1;
43     throwing_t v(throw_after);
44     std::vector<throwing_t> get_alloc(1, v);
45   } catch (int) {
46   }
47   check_new_delete_called();
48 
49   try { // Throw in vector(size_type, const allocator_type&) from allocator
50     throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
51     AllocVec get_alloc(0, alloc);
52   } catch (int) {
53   }
54   check_new_delete_called();
55 
56   try { // Throw in vector(size_type, const allocator_type&) from the type
57     std::vector<throwing_t> vec(1, std::allocator<throwing_t>());
58   } catch (int) {
59   }
60   check_new_delete_called();
61 #endif // TEST_STD_VER >= 14
62 
63   try { // Throw in vector(size_type, value_type, const allocator_type&) from the type
64     int throw_after = 1;
65     throwing_t v(throw_after);
66     std::vector<throwing_t> vec(1, v, std::allocator<throwing_t>());
67   } catch (int) {
68   }
69   check_new_delete_called();
70 
71   try { // Throw in vector(InputIterator, InputIterator) from input iterator
72     std::vector<int> vec(
73         (throwing_iterator<int, std::input_iterator_tag>()), throwing_iterator<int, std::input_iterator_tag>(2));
74   } catch (int) {
75   }
76   check_new_delete_called();
77 
78   try { // Throw in vector(InputIterator, InputIterator) from forward iterator
79     std::vector<int> vec(
80         (throwing_iterator<int, std::forward_iterator_tag>()), throwing_iterator<int, std::forward_iterator_tag>(2));
81   } catch (int) {
82   }
83   check_new_delete_called();
84 
85   try { // Throw in vector(InputIterator, InputIterator) from allocator
86     int a[] = {1, 2};
87     AllocVec vec(cpp17_input_iterator<int*>(a), cpp17_input_iterator<int*>(a + 2));
88   } catch (int) {
89   }
90   check_new_delete_called();
91 
92   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
93     std::allocator<int> alloc;
94     std::vector<int> vec(
95         throwing_iterator<int, std::input_iterator_tag>(), throwing_iterator<int, std::input_iterator_tag>(2), alloc);
96   } catch (int) {
97   }
98   check_new_delete_called();
99 
100   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
101     std::allocator<int> alloc;
102     std::vector<int> vec(throwing_iterator<int, std::forward_iterator_tag>(),
103                          throwing_iterator<int, std::forward_iterator_tag>(2),
104                          alloc);
105   } catch (int) {
106   }
107   check_new_delete_called();
108 
109   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
110     int a[] = {1, 2};
111     throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
112     AllocVec vec(cpp17_input_iterator<int*>(a), cpp17_input_iterator<int*>(a + 2), alloc);
113   } catch (int) {
114   }
115   check_new_delete_called();
116 
117   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
118     int a[] = {1, 2};
119     throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
120     AllocVec vec(forward_iterator<int*>(a), forward_iterator<int*>(a + 2), alloc);
121   } catch (int) {
122   }
123   check_new_delete_called();
124 
125   try { // Throw in vector(const vector&) from type
126     std::vector<throwing_t> vec;
127     int throw_after = 1;
128     vec.emplace_back(throw_after);
129     auto vec2 = vec;
130   } catch (int) {
131   }
132   check_new_delete_called();
133 
134   try { // Throw in vector(const vector&, const allocator_type&) from type
135     std::vector<throwing_t> vec;
136     int throw_after = 1;
137     vec.emplace_back(throw_after);
138     std::vector<throwing_t> vec2(vec, std::allocator<int>());
139   } catch (int) {
140   }
141   check_new_delete_called();
142 
143   try { // Throw in vector(vector&&, const allocator_type&) from type during element-wise move
144     std::vector<throwing_t, test_allocator<throwing_t> > vec(test_allocator<throwing_t>(1));
145     int throw_after = 10;
146     throwing_t v(throw_after);
147     vec.insert(vec.end(), 6, v);
148     std::vector<throwing_t, test_allocator<throwing_t> > vec2(std::move(vec), test_allocator<throwing_t>(2));
149   } catch (int) {
150   }
151   check_new_delete_called();
152 
153 #if TEST_STD_VER >= 11
154   try { // Throw in vector(initializer_list<value_type>) from type
155     int throw_after = 1;
156     std::vector<throwing_t> vec({throwing_t(throw_after)});
157   } catch (int) {
158   }
159   check_new_delete_called();
160 
161   try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type
162     int throw_after = 1;
163     std::vector<throwing_t> vec({throwing_t(throw_after)}, std::allocator<throwing_t>());
164   } catch (int) {
165   }
166   check_new_delete_called();
167 #endif // TEST_STD_VER >= 11
168 
169   return 0;
170 }
171