169 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: no-exceptions10 11// (bug report: https://llvm.org/PR58392)12// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception13 14#include <cstddef>15#include <memory>16#include <type_traits>17#include <vector>18 19#include "../common.h"20#include "count_new.h"21#include "test_allocator.h"22#include "test_iterators.h"23 24int main(int, char**) {25 using AllocVec = std::vector<int, throwing_allocator<int> >;26 try { // vector()27 AllocVec vec;28 } catch (int) {29 }30 check_new_delete_called();31 32 try { // Throw in vector(size_type) from type33 std::vector<throwing_t> get_alloc(1);34 } catch (int) {35 }36 check_new_delete_called();37 38#if TEST_STD_VER >= 1439 try { // Throw in vector(size_type, value_type) from type40 int throw_after = 1;41 throwing_t v(throw_after);42 std::vector<throwing_t> get_alloc(1, v);43 } catch (int) {44 }45 check_new_delete_called();46 47 try { // Throw in vector(size_type, const allocator_type&) from allocator48 throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);49 AllocVec get_alloc(0, alloc);50 } catch (int) {51 }52 check_new_delete_called();53 54 try { // Throw in vector(size_type, const allocator_type&) from the type55 std::vector<throwing_t> vec(1, std::allocator<throwing_t>());56 } catch (int) {57 }58 check_new_delete_called();59#endif // TEST_STD_VER >= 1460 61 try { // Throw in vector(size_type, value_type, const allocator_type&) from the type62 int throw_after = 1;63 throwing_t v(throw_after);64 std::vector<throwing_t> vec(1, v, std::allocator<throwing_t>());65 } catch (int) {66 }67 check_new_delete_called();68 69 try { // Throw in vector(InputIterator, InputIterator) from input iterator70 std::vector<int> vec(71 (throwing_iterator<int, std::input_iterator_tag>()), throwing_iterator<int, std::input_iterator_tag>(2));72 } catch (int) {73 }74 check_new_delete_called();75 76 try { // Throw in vector(InputIterator, InputIterator) from forward iterator77 std::vector<int> vec(78 (throwing_iterator<int, std::forward_iterator_tag>()), throwing_iterator<int, std::forward_iterator_tag>(2));79 } catch (int) {80 }81 check_new_delete_called();82 83 try { // Throw in vector(InputIterator, InputIterator) from allocator84 int a[] = {1, 2};85 AllocVec vec(cpp17_input_iterator<int*>(a), cpp17_input_iterator<int*>(a + 2));86 } catch (int) {87 }88 check_new_delete_called();89 90 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from input iterator91 std::allocator<int> alloc;92 std::vector<int> vec(93 throwing_iterator<int, std::input_iterator_tag>(), throwing_iterator<int, std::input_iterator_tag>(2), alloc);94 } catch (int) {95 }96 check_new_delete_called();97 98 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from forward iterator99 std::allocator<int> alloc;100 std::vector<int> vec(throwing_iterator<int, std::forward_iterator_tag>(),101 throwing_iterator<int, std::forward_iterator_tag>(2),102 alloc);103 } catch (int) {104 }105 check_new_delete_called();106 107 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator108 int a[] = {1, 2};109 throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);110 AllocVec vec(cpp17_input_iterator<int*>(a), cpp17_input_iterator<int*>(a + 2), alloc);111 } catch (int) {112 }113 check_new_delete_called();114 115 try { // Throw in vector(InputIterator, InputIterator, const allocator_type&) from allocator116 int a[] = {1, 2};117 throwing_allocator<int> alloc(/*throw_on_ctor = */ false, /*throw_on_copy = */ true);118 AllocVec vec(forward_iterator<int*>(a), forward_iterator<int*>(a + 2), alloc);119 } catch (int) {120 }121 check_new_delete_called();122 123 try { // Throw in vector(const vector&) from type124 std::vector<throwing_t> vec;125 int throw_after = 1;126 vec.emplace_back(throw_after);127 auto vec2 = vec;128 } catch (int) {129 }130 check_new_delete_called();131 132 try { // Throw in vector(const vector&, const allocator_type&) from type133 std::vector<throwing_t> vec;134 int throw_after = 1;135 vec.emplace_back(throw_after);136 std::vector<throwing_t> vec2(vec, std::allocator<int>());137 } catch (int) {138 }139 check_new_delete_called();140 141 try { // Throw in vector(vector&&, const allocator_type&) from type during element-wise move142 std::vector<throwing_t, test_allocator<throwing_t> > vec(test_allocator<throwing_t>(1));143 int throw_after = 10;144 throwing_t v(throw_after);145 vec.insert(vec.end(), 6, v);146 std::vector<throwing_t, test_allocator<throwing_t> > vec2(std::move(vec), test_allocator<throwing_t>(2));147 } catch (int) {148 }149 check_new_delete_called();150 151#if TEST_STD_VER >= 11152 try { // Throw in vector(initializer_list<value_type>) from type153 int throw_after = 1;154 std::vector<throwing_t> vec({throwing_t(throw_after)});155 } catch (int) {156 }157 check_new_delete_called();158 159 try { // Throw in vector(initializer_list<value_type>, const allocator_type&) constructor from type160 int throw_after = 1;161 std::vector<throwing_t> vec({throwing_t(throw_after)}, std::allocator<throwing_t>());162 } catch (int) {163 }164 check_new_delete_called();165#endif // TEST_STD_VER >= 11166 167 return 0;168}169