xref: /llvm-project/libcxx/test/std/containers/sequences/vector.bool/ctor_exceptions.pass.cpp (revision c5cd1e958c2cea9fe5a6a9087c3481537d598e24)
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<bool> constructors don't leak memory when an operation inside the constructor throws an exception
13 
14 #include <cstddef>
15 #include <memory>
16 #include <type_traits>
17 #include <vector>
18 
19 #include "../vector/common.h"
20 #include "count_new.h"
21 #include "test_iterators.h"
22 
23 int main(int, char**) {
24   using AllocVec = std::vector<bool, throwing_allocator<bool> >;
25 
26   try { // Throw in vector() from allocator
27     AllocVec vec;
28   } catch (int) {
29   }
30   check_new_delete_called();
31 
32 #if TEST_STD_VER >= 14
33   try { // Throw in vector(size_type, const allocator_type&) from allocator
34     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
35     AllocVec get_alloc(0, alloc);
36   } catch (int) {
37   }
38   check_new_delete_called();
39 #endif // TEST_STD_VER >= 14
40 
41   try { // Throw in vector(size_type, const value_type&, const allocator_type&) from allocator
42     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
43     AllocVec get_alloc(0, true, alloc);
44   } catch (int) {
45   }
46   check_new_delete_called();
47 
48   try { // Throw in vector(InputIterator, InputIterator) from input iterator
49     std::vector<bool> vec(
50         throwing_iterator<bool, std::input_iterator_tag>(), throwing_iterator<bool, std::input_iterator_tag>(2));
51   } catch (int) {
52   }
53   check_new_delete_called();
54 
55   try { // Throw in vector(InputIterator, InputIterator) from forward iterator
56     std::vector<bool> vec(
57         throwing_iterator<bool, std::forward_iterator_tag>(), throwing_iterator<bool, std::forward_iterator_tag>(2));
58   } catch (int) {
59   }
60   check_new_delete_called();
61 
62   try { // Throw in vector(InputIterator, InputIterator) from allocator
63     bool a[] = {true, true};
64     AllocVec vec(cpp17_input_iterator<bool*>(a), cpp17_input_iterator<bool*>(a + 2));
65   } catch (int) {
66   }
67   check_new_delete_called();
68 
69   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator
70     std::allocator<bool> alloc;
71     std::vector<bool> vec(
72         throwing_iterator<bool, std::input_iterator_tag>(), throwing_iterator<bool, std::input_iterator_tag>(2), alloc);
73   } catch (int) {
74   }
75   check_new_delete_called();
76 
77   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator
78     std::allocator<bool> alloc;
79     std::vector<bool> vec(throwing_iterator<bool, std::forward_iterator_tag>(),
80                           throwing_iterator<bool, std::forward_iterator_tag>(2),
81                           alloc);
82   } catch (int) {
83   }
84   check_new_delete_called();
85 
86   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
87     bool a[] = {true, false};
88     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
89     AllocVec vec(cpp17_input_iterator<bool*>(a), cpp17_input_iterator<bool*>(a + 2), alloc);
90   } catch (int) {
91   }
92   check_new_delete_called();
93 
94   try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator
95     bool a[] = {true, false};
96     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
97     AllocVec vec(forward_iterator<bool*>(a), forward_iterator<bool*>(a + 2), alloc);
98   } catch (int) {
99   }
100   check_new_delete_called();
101 
102 #if TEST_STD_VER >= 11
103   try { // Throw in vector(const vector&, const allocator_type&) from allocator
104     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ false);
105     AllocVec vec(alloc);
106     vec.push_back(true);
107     alloc.throw_on_copy_ = true;
108     AllocVec vec2(vec, alloc);
109   } catch (int) {
110   }
111   check_new_delete_called();
112 
113   try { // Throw in vector(vector&&, const allocator_type&) from allocator
114     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ false);
115     AllocVec vec(alloc);
116     vec.push_back(true);
117     alloc.throw_on_copy_ = true;
118     AllocVec vec2(std::move(vec), alloc);
119   } catch (int) {
120   }
121   check_new_delete_called();
122 
123   try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from allocator
124     throwing_allocator<bool> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);
125     AllocVec vec({true, true}, alloc);
126   } catch (int) {
127   }
128   check_new_delete_called();
129 #endif // TEST_STD_VER >= 11
130 
131   return 0;
132 }
133