xref: /llvm-project/libcxx/test/libcxx/containers/sequences/vector/asan_throw.pass.cpp (revision f4fb72e6d4cee1097e6606e66232fe55e793cd86)
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 // Test asan vector annotations with a class that throws in a CTOR.
11 
12 #include <vector>
13 #include <cassert>
14 
15 #include "test_macros.h"
16 #include "asan_testing.h"
17 
18 class X {
19 public:
X(const X & x)20   X(const X &x) { Init(x.a); }
X(char arg)21   X(char arg) { Init(arg); }
X()22   X() { Init(42); }
operator =(const X & x)23   X &operator=(const X &x) {
24     Init(x.a);
25     return *this;
26   }
Init(char arg)27   void Init(char arg) {
28     if (arg == 42)
29       throw 0;
30     if (arg == 66)
31       arg = 42;
32     a = arg;
33   }
get() const34   char get() const { return a; }
set(char arg)35   void set(char arg) { a = arg; }
36 
37 private:
38   char a;
39 };
40 
41 class ThrowOnCopy {
42 public:
ThrowOnCopy()43     ThrowOnCopy() : should_throw(false) {}
ThrowOnCopy(bool xshould_throw)44     explicit ThrowOnCopy(bool xshould_throw) : should_throw(xshould_throw) {}
45 
ThrowOnCopy(ThrowOnCopy const & other)46     ThrowOnCopy(ThrowOnCopy const & other)
47         : should_throw(other.should_throw)
48     {
49         if (should_throw) {
50             throw 0;
51         }
52     }
53     ThrowOnCopy& operator=(ThrowOnCopy const&) = default;
54 
55     bool should_throw;
56 };
57 
test_push_back()58 void test_push_back() {
59   std::vector<X> v;
60   v.reserve(2);
61   v.push_back(X(2));
62   assert(v.size() == 1);
63   try {
64     v.push_back(X(66));
65     assert(0);
66   } catch (int e) {
67     assert(v.size() == 1);
68   }
69   assert(v.size() == 1);
70   assert(is_contiguous_container_asan_correct(v));
71 }
72 
test_emplace_back()73 void test_emplace_back() {
74 #if TEST_STD_VER >= 11
75   std::vector<X> v;
76   v.reserve(2);
77   v.push_back(X(2));
78   assert(v.size() == 1);
79   try {
80     v.emplace_back(42);
81     assert(0);
82   } catch (int e) {
83     assert(v.size() == 1);
84   }
85   assert(v.size() == 1);
86   assert(is_contiguous_container_asan_correct(v));
87 #endif
88 }
89 
test_insert_range()90 void test_insert_range() {
91   std::vector<X> v;
92   v.reserve(4);
93   v.push_back(X(1));
94   v.push_back(X(2));
95   assert(v.size() == 2);
96   assert(v.capacity() >= 4);
97   try {
98     char a[2] = {21, 42};
99     v.insert(v.end(), a, a + 2);
100     assert(0);
101   } catch (int e) {
102     assert(v.size() == 2);
103   }
104   assert(v.size() == 2);
105   assert(is_contiguous_container_asan_correct(v));
106 }
107 
test_insert()108 void test_insert() {
109   std::vector<X> v;
110   v.reserve(3);
111   v.insert(v.end(), X(1));
112   v.insert(v.begin(), X(2));
113   assert(v.size() == 2);
114   try {
115     v.insert(v.end(), X(66));
116     assert(0);
117   } catch (int e) {
118     assert(v.size() == 2);
119   }
120   assert(v.size() == 2);
121   assert(is_contiguous_container_asan_correct(v));
122 }
123 
test_emplace()124 void test_emplace() {
125 #if TEST_STD_VER >= 11
126   std::vector<X> v;
127   v.reserve(3);
128   v.insert(v.end(), X(1));
129   v.insert(v.begin(), X(2));
130   assert(v.size() == 2);
131   try {
132     v.emplace(v.end(), 42);
133     assert(0);
134   } catch (int e) {
135     assert(v.size() == 2);
136   }
137   assert(v.size() == 2);
138   assert(is_contiguous_container_asan_correct(v));
139 #endif
140 }
141 
test_insert_range2()142 void test_insert_range2() {
143   std::vector<X> v;
144   v.reserve(4);
145   v.insert(v.end(), X(1));
146   v.insert(v.begin(), X(2));
147   assert(v.size() == 2);
148   assert(v.capacity() >= 4);
149   try {
150     char a[2] = {10, 42};
151     v.insert(v.begin(), a, a + 2);
152     assert(0);
153   } catch (int e) {
154     assert(v.size() <= 4);
155     assert(is_contiguous_container_asan_correct(v));
156     return;
157   }
158   assert(0);
159 }
160 
test_insert_n()161 void test_insert_n() {
162   std::vector<X> v;
163   v.reserve(10);
164   v.insert(v.end(), X(1));
165   v.insert(v.begin(), X(2));
166   assert(v.size() == 2);
167   try {
168     v.insert(v.begin(), 1, X(66));
169     assert(0);
170   } catch (int e) {
171     assert(v.size() <= 3);
172     assert(is_contiguous_container_asan_correct(v));
173     return;
174   }
175   assert(0);
176 }
177 
178 
test_insert_n2()179 void test_insert_n2() {
180   std::vector<ThrowOnCopy> v(10);
181   v.reserve(100);
182   assert(v.size() == 10);
183   v[6].should_throw = true;
184   try {
185     v.insert(v.cbegin(), 5, ThrowOnCopy());
186     assert(0);
187   } catch (int e) {
188     assert(v.size() == 11);
189     assert(is_contiguous_container_asan_correct(v));
190     return;
191   }
192   assert(0);
193 }
194 
test_resize()195 void test_resize() {
196   std::vector<X> v;
197   v.reserve(3);
198   v.push_back(X(0));
199   try {
200     v.resize(3);
201     assert(0);
202   } catch (int e) {
203     assert(v.size() == 1);
204   }
205   assert(v.size() == 1);
206   assert(is_contiguous_container_asan_correct(v));
207 }
208 
test_resize_param()209 void test_resize_param() {
210   std::vector<X> v;
211   v.reserve(3);
212   v.push_back(X(0));
213   try {
214     v.resize(3, X(66));
215     assert(0);
216   } catch (int e) {
217     assert(v.size() == 1);
218   }
219   assert(v.size() == 1);
220   assert(is_contiguous_container_asan_correct(v));
221 }
222 
main(int,char **)223 int main(int, char**) {
224   test_push_back();
225   test_emplace_back();
226   test_insert_range();
227   test_insert();
228   test_emplace();
229   test_insert_range2();
230   test_insert_n();
231   test_insert_n2();
232   test_resize();
233   test_resize_param();
234 
235   return 0;
236 }
237