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