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+ #if TEST_STD_VER >= 14
107+ // vector(size_type __n, const allocator_type& __a)
108+ {
109+ throw_context ctx;
110+ AllocType alloc;
111+ try {
112+ std::vector<throw_element> v (3 , alloc);
113+ } catch (int ) {
114+ }
115+ check_new_delete_called ();
116+ }
117+ #endif
118+
119+ // vector(size_type __n, const value_type& __x)
120+ {
121+ throw_context ctx (3 );
122+ try {
123+ throw_element e;
124+ std::vector<throw_element> v (3 , e);
125+ } catch (int ) {
126+ }
127+ check_new_delete_called ();
128+ }
129+
130+ // vector(size_type __n, const value_type& __x, const allocator_type& __a)
131+ {
132+ throw_context ctx (3 );
133+ try {
134+ throw_element e;
135+ AllocType alloc;
136+ std::vector<throw_element> v (4 , e, alloc);
137+ } catch (int ) {
138+ }
139+ check_new_delete_called ();
140+ }
141+
142+ // vector(_ForwardIterator __first, _ForwardIterator __last)
143+ {
144+ throw_context ctx (4 );
145+ try {
146+ std::vector<throw_element> v1 (2 );
147+ std::vector<throw_element> v2 (v1.begin (), v1.end ());
148+ } catch (int ) {
149+ }
150+ check_new_delete_called ();
151+ }
152+
153+ // vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
154+ {
155+ throw_context ctx (4 );
156+ AllocType alloc;
157+ try {
158+ std::vector<throw_element> v1 (2 );
159+ std::vector<throw_element> v2 (v1.begin (), v1.end (), alloc);
160+ } catch (int ) {
161+ }
162+ check_new_delete_called ();
163+ }
164+
165+ #if TEST_STD_VER >= 23
166+ // vector(from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
167+ {
168+ throw_context ctx (4 );
169+ try {
170+ std::vector<throw_element> r (2 );
171+ std::vector<throw_element> v (std::from_range, std::views::counted (r.begin (), 2 ));
172+ } catch (int ) {
173+ }
174+ check_new_delete_called ();
175+ }
176+ #endif
177+
178+ // vector(const vector& __x)
179+ {
180+ throw_context ctx (4 );
181+ try {
182+ std::vector<throw_element> v1 (2 );
183+ std::vector<throw_element> v2 (v1);
184+ } catch (int ) {
185+ }
186+ check_new_delete_called ();
187+ }
188+
189+ #if TEST_STD_VER > 3
190+ // vector(initializer_list<value_type> __il)
191+ {
192+ throw_context ctx (6 );
193+ try {
194+ throw_element e;
195+ std::vector<throw_element> v ({e, e, e});
196+ } catch (int ) {
197+ }
198+ check_new_delete_called ();
199+ }
200+
201+ // vector(initializer_list<value_type> __il, const allocator_type& __a)
202+ {
203+ throw_context ctx (6 );
204+ AllocType alloc;
205+ try {
206+ throw_element e;
207+ std::vector<throw_element> v ({e, e, e}, alloc);
208+ } catch (int ) {
209+ }
210+ check_new_delete_called ();
211+ }
212+ #endif
213+
214+ // void resize(size_type __sz)
215+ {
216+ // cap < size
217+ throw_context ctx;
218+ std::vector<throw_element> v;
219+ v.reserve (5 );
220+ try {
221+ v.resize (4 );
222+ } catch (int ) {
223+ }
224+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
225+ }
226+ check_new_delete_called ();
227+
228+ // void resize(size_type __sz, const_reference __x)
229+ {
230+ // cap < size
231+ throw_context ctx (3 );
232+ std::vector<throw_element> v;
233+ v.reserve (5 );
234+ try {
235+ throw_element e;
236+ v.resize (4 , e);
237+ } catch (int ) {
238+ }
239+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
240+ }
241+ check_new_delete_called ();
242+
243+ // void assign(_ForwardIterator __first, _ForwardIterator __last)
244+ {
245+ // new size <= cap && new size > size
246+ throw_context ctx (4 );
247+ std::vector<throw_element> v;
248+ v.reserve (3 );
249+ try {
250+ std::vector<throw_element> data (2 );
251+ v.assign (data.begin (), data.end ());
252+ } catch (int ) {
253+ }
254+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
255+ }
256+ check_new_delete_called ();
257+
258+ {
259+ // new size > cap
260+ throw_context ctx (4 );
261+ std::vector<throw_element> v;
262+ try {
263+ std::vector<throw_element> data (2 );
264+ v.assign (data.begin (), data.end ());
265+ } catch (int ) {
266+ }
267+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
268+ }
269+ check_new_delete_called ();
270+
271+ #if TEST_STD_VER >= 23
272+ // void assign_range(_Range&& __range)
273+ {
274+ throw_context ctx (5 );
275+ std::vector<throw_element> v;
276+ try {
277+ std::vector<throw_element> r (3 );
278+ v.assign_range (r);
279+ } catch (int ) {
280+ }
281+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
282+ }
283+ check_new_delete_called ();
284+ #endif
285+
286+ #if TEST_STD_VER > 3
287+ // vector& operator=(initializer_list<value_type> __il)
288+ {
289+ throw_context ctx (5 );
290+ std::vector<throw_element> v;
291+ try {
292+ throw_element e;
293+ v = {e, e};
294+ } catch (int ) {
295+ }
296+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
297+ }
298+ check_new_delete_called ();
299+ #endif
300+
301+ // vector<_Tp, _Allocator>& vector<_Tp, _Allocator>::operator=(const vector& __x)
302+ {
303+ throw_context ctx (4 );
304+ std::vector<throw_element> v;
305+ try {
306+ std::vector<throw_element> data (2 );
307+ v = data;
308+ } catch (int ) {
309+ }
310+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
311+ }
312+ check_new_delete_called ();
313+
314+ // iterator insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last)
315+ {
316+ throw_context ctx (6 );
317+ std::vector<throw_element> v;
318+ v.reserve (10 );
319+ try {
320+ std::vector<throw_element> data (3 );
321+ v.insert (v.begin (), data.begin (), data.end ());
322+ } catch (int ) {
323+ }
324+ assert (globalMemCounter.new_called == globalMemCounter.delete_called + 1 );
325+ }
326+ check_new_delete_called ();
327+
328+ #if TEST_STD_VER >= 23
329+ // iterator insert_range(const_iterator __position, _Range&& __range)
330+ {
331+ throw_context ctx (3 );
332+ std::vector<throw_element> v;
333+ try {
334+ std::vector<throw_element> data (2 );
335+ v.insert_range (v.begin (), data);
336+ } catch (int ) {
337+ }
338+ check_new_delete_called ();
339+ }
340+ #endif
341+
342+ return 0 ;
343+ }
0 commit comments