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+ // <vector>
12+
13+ // Make sure elements are destroyed when exceptions thrown in __construct_at_end
14+
15+ #include < cassert>
16+ #include < cstddef>
17+ #include < memory>
18+ #include < vector>
19+
20+ #include " test_macros.h"
21+ #if TEST_STD_VER >= 20
22+ # include < ranges>
23+ #endif
24+
25+ #include " common.h"
26+ #include " count_new.h"
27+
28+ struct throw_context {
29+ static int num;
30+ static int limit;
31+
32+ throw_context (int lim = 2 ) {
33+ num = 0 ;
34+ limit = lim;
35+ }
36+
37+ static void inc () {
38+ ++num;
39+ if (num >= limit) {
40+ --num;
41+ throw 1 ;
42+ }
43+ }
44+
45+ static void dec () { --num; }
46+ };
47+
48+ int throw_context::num = 0 ;
49+ int throw_context::limit = 0 ;
50+
51+ int debug = 0 ;
52+
53+ class throw_element {
54+ public:
55+ throw_element () : data(new int (1 )) {
56+ try {
57+ throw_context::inc ();
58+ } catch (int ) {
59+ delete data;
60+ throw ;
61+ }
62+ }
63+
64+ throw_element (throw_element const & other) : data(new int (1 )) {
65+ (void )other;
66+ try {
67+ throw_context::inc ();
68+ } catch (int ) {
69+ delete data;
70+ throw ;
71+ }
72+ }
73+
74+ ~throw_element () {
75+ if (data) {
76+ delete data;
77+ throw_context::dec ();
78+ if (debug)
79+ printf (" dctor\n " );
80+ }
81+ }
82+
83+ throw_element& operator =(throw_element const & other) {
84+ (void )other;
85+ // nothing to do
86+ return *this ;
87+ }
88+
89+ private:
90+ int * data;
91+ };
92+
93+ int main (int , char *[]) {
94+ using AllocType = std::allocator<throw_element>;
95+
96+ // vector(size_type __n)
97+ {
98+ throw_context ctx;
99+ try {
100+ std::vector<throw_element> v (3 );
101+ } catch (int ) {
102+ }
103+ check_new_delete_called ();
104+ }
105+
106+ // vector(size_type __n, const allocator_type& __a)
107+ {
108+ throw_context ctx;
109+ AllocType alloc;
110+ try {
111+ std::vector<throw_element> v (3 , alloc);
112+ } catch (int ) {
113+ }
114+ check_new_delete_called ();
115+ }
116+
117+ // vector(size_type __n, const value_type& __x)
118+ {
119+ throw_context ctx (3 );
120+ try {
121+ throw_element e;
122+ std::vector<throw_element> v (3 , e);
123+ } catch (int ) {
124+ }
125+ check_new_delete_called ();
126+ }
127+
128+ // vector(size_type __n, const value_type& __x, const allocator_type& __a)
129+ {
130+ throw_context ctx (3 );
131+ try {
132+ throw_element e;
133+ AllocType alloc;
134+ std::vector<throw_element> v (4 , e, alloc);
135+ } catch (int ) {
136+ }
137+ check_new_delete_called ();
138+ }
139+
140+ // vector(_ForwardIterator __first, _ForwardIterator __last)
141+ {
142+ throw_context ctx (4 );
143+ try {
144+ std::vector<throw_element> v1 (2 );
145+ std::vector<throw_element> v2 (v1.begin (), v1.end ());
146+ } catch (int ) {
147+ }
148+ check_new_delete_called ();
149+ }
150+
151+ // vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
152+ {
153+ throw_context ctx (4 );
154+ AllocType alloc;
155+ try {
156+ std::vector<throw_element> v1 (2 );
157+ std::vector<throw_element> v2 (v1.begin (), v1.end (), alloc);
158+ } catch (int ) {
159+ }
160+ check_new_delete_called ();
161+ }
162+
163+ #if _LIBCPP_STD_VER >= 23
164+ // vector(from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
165+ {
166+ throw_context ctx (4 );
167+ try {
168+ std::vector<throw_element> r (2 );
169+ std::vector<throw_element> v (std::from_range, std::views::counted (r.begin (), 2 ));
170+ } catch (int ) {
171+ }
172+ check_new_delete_called ();
173+ }
174+ #endif
175+
176+ // vector(const vector& __x)
177+ {
178+ throw_context ctx (4 );
179+ try {
180+ std::vector<throw_element> v1 (2 );
181+ std::vector<throw_element> v2 (v1);
182+ } catch (int ) {
183+ }
184+ check_new_delete_called ();
185+ }
186+
187+ // vector(initializer_list<value_type> __il)
188+ {
189+ throw_context ctx (6 );
190+ try {
191+ throw_element e;
192+ std::vector<throw_element> v ({e, e, e});
193+ } catch (int ) {
194+ }
195+ check_new_delete_called ();
196+ }
197+
198+ // vector(initializer_list<value_type> __il, const allocator_type& __a)
199+ {
200+ throw_context ctx (6 );
201+ AllocType alloc;
202+ try {
203+ throw_element e;
204+ std::vector<throw_element> v ({e, e, e}, alloc);
205+ } catch (int ) {
206+ }
207+ check_new_delete_called ();
208+ }
209+
210+ // void resize(size_type __sz)
211+ {
212+ // cap < size
213+ throw_context ctx;
214+ std::vector<throw_element> v;
215+ v.reserve (1 );
216+ try {
217+ v.resize (4 );
218+ } catch (int ) {
219+ }
220+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
221+ }
222+ check_new_delete_called ();
223+
224+ // void resize(size_type __sz, const_reference __x)
225+ {
226+ // cap < size
227+ throw_context ctx (3 );
228+ std::vector<throw_element> v;
229+ v.reserve (1 );
230+ try {
231+ throw_element e;
232+ v.resize (4 , e);
233+ } catch (int ) {
234+ }
235+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
236+ }
237+ check_new_delete_called ();
238+
239+ // void assign(_ForwardIterator __first, _ForwardIterator __last)
240+ {
241+ // new size <= cap && new size > size
242+ throw_context ctx (4 );
243+ std::vector<throw_element> v;
244+ v.reserve (3 );
245+ try {
246+ std::vector<throw_element> data (2 );
247+ v.assign (data.begin (), data.end ());
248+ } catch (int ) {
249+ }
250+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
251+ }
252+ check_new_delete_called ();
253+
254+ {
255+ // new size > cap
256+ throw_context ctx (4 );
257+ std::vector<throw_element> v;
258+ try {
259+ std::vector<throw_element> data (2 );
260+ v.assign (data.begin (), data.end ());
261+ } catch (int ) {
262+ }
263+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
264+ }
265+ check_new_delete_called ();
266+
267+ #if _LIBCPP_STD_VER >= 23
268+ // void assign_range(_Range&& __range)
269+ {
270+ throw_context ctx (5 );
271+ std::vector<throw_element> v;
272+ try {
273+ std::vector<throw_element> r (3 );
274+ v.assign_range (r);
275+ } catch (int ) {
276+ }
277+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
278+ }
279+ check_new_delete_called ();
280+ #endif
281+
282+ // vector& operator=(initializer_list<value_type> __il)
283+ {
284+ throw_context ctx (5 );
285+ std::vector<throw_element> v;
286+ try {
287+ throw_element e;
288+ v = {e, e};
289+ } catch (int ) {
290+ }
291+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
292+ }
293+ check_new_delete_called ();
294+
295+ // vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(const vector& __x)
296+ {
297+ throw_context ctx (4 );
298+ std::vector<throw_element> v;
299+ try {
300+ std::vector<throw_element> data (2 );
301+ v = data;
302+ } catch (int ) {
303+ }
304+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
305+ }
306+ check_new_delete_called ();
307+
308+ // iterator insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last)
309+ {
310+ throw_context ctx (6 );
311+ std::vector<throw_element> v;
312+ v.reserve (10 );
313+ try {
314+ std::vector<throw_element> data (3 );
315+ v.insert (v.begin (), data.begin (), data.end ());
316+ } catch (int ) {
317+ }
318+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
319+ }
320+ check_new_delete_called ();
321+
322+ #if _LIBCPP_STD_VER >= 23
323+ // iterator insert_range(const_iterator __position, _Range&& __range)
324+ {
325+ throw_context ctx (3 );
326+ std::vector<throw_element> v;
327+ try {
328+ std::vector<throw_element> data (2 );
329+ v.insert_range (v.begin (), data);
330+ } catch (int ) {
331+ }
332+ check_new_delete_called ();
333+ }
334+ #endif
335+
336+ return 0 ;
337+ }
0 commit comments