1 //===----------------------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: libcpp-no-exceptions
11 // Test asan vector annotations with a class that throws in a CTOR.
12
13 #include <vector>
14 #include <cassert>
15
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
54 bool should_throw;
55 };
56
test_push_back()57 void test_push_back() {
58 std::vector<X> v;
59 v.reserve(2);
60 v.push_back(X(2));
61 assert(v.size() == 1);
62 try {
63 v.push_back(X(66));
64 assert(0);
65 } catch (int e) {
66 assert(v.size() == 1);
67 }
68 assert(v.size() == 1);
69 assert(is_contiguous_container_asan_correct(v));
70 }
71
test_emplace_back()72 void test_emplace_back() {
73 #ifndef _LIBCPP_HAS_NO_VARIADICS
74 std::vector<X> v;
75 v.reserve(2);
76 v.push_back(X(2));
77 assert(v.size() == 1);
78 try {
79 v.emplace_back(42);
80 assert(0);
81 } catch (int e) {
82 assert(v.size() == 1);
83 }
84 assert(v.size() == 1);
85 assert(is_contiguous_container_asan_correct(v));
86 #endif // _LIBCPP_HAS_NO_VARIADICS
87 }
88
test_insert_range()89 void test_insert_range() {
90 std::vector<X> v;
91 v.reserve(4);
92 v.push_back(X(1));
93 v.push_back(X(2));
94 assert(v.size() == 2);
95 assert(v.capacity() >= 4);
96 try {
97 char a[2] = {21, 42};
98 v.insert(v.end(), a, a + 2);
99 assert(0);
100 } catch (int e) {
101 assert(v.size() == 3);
102 }
103 assert(v.size() == 3);
104 assert(is_contiguous_container_asan_correct(v));
105 }
106
test_insert()107 void test_insert() {
108 std::vector<X> v;
109 v.reserve(3);
110 v.insert(v.end(), X(1));
111 v.insert(v.begin(), X(2));
112 assert(v.size() == 2);
113 try {
114 v.insert(v.end(), X(66));
115 assert(0);
116 } catch (int e) {
117 assert(v.size() == 2);
118 }
119 assert(v.size() == 2);
120 assert(is_contiguous_container_asan_correct(v));
121 }
122
test_emplace()123 void test_emplace() {
124 #ifndef _LIBCPP_HAS_NO_VARIADICS
125 std::vector<X> v;
126 v.reserve(3);
127 v.insert(v.end(), X(1));
128 v.insert(v.begin(), X(2));
129 assert(v.size() == 2);
130 try {
131 v.emplace(v.end(), 42);
132 assert(0);
133 } catch (int e) {
134 assert(v.size() == 2);
135 }
136 assert(v.size() == 2);
137 assert(is_contiguous_container_asan_correct(v));
138 #endif // _LIBCPP_HAS_NO_VARIADICS
139 }
140
test_insert_range2()141 void test_insert_range2() {
142 std::vector<X> v;
143 v.reserve(4);
144 v.insert(v.end(), X(1));
145 v.insert(v.begin(), X(2));
146 assert(v.size() == 2);
147 assert(v.capacity() >= 4);
148 try {
149 char a[2] = {10, 42};
150 v.insert(v.begin(), a, a + 2);
151 assert(0);
152 } catch (int e) {
153 assert(v.size() <= 4);
154 assert(is_contiguous_container_asan_correct(v));
155 return;
156 }
157 assert(0);
158 }
159
test_insert_n()160 void test_insert_n() {
161 std::vector<X> v;
162 v.reserve(10);
163 v.insert(v.end(), X(1));
164 v.insert(v.begin(), X(2));
165 assert(v.size() == 2);
166 try {
167 v.insert(v.begin(), 1, X(66));
168 assert(0);
169 } catch (int e) {
170 assert(v.size() <= 3);
171 assert(is_contiguous_container_asan_correct(v));
172 return;
173 }
174 assert(0);
175 }
176
177
test_insert_n2()178 void test_insert_n2() {
179 std::vector<ThrowOnCopy> v(10);
180 v.reserve(100);
181 assert(v.size() == 10);
182 v[6].should_throw = true;
183 try {
184 v.insert(v.cbegin(), 5, ThrowOnCopy());
185 assert(0);
186 } catch (int e) {
187 assert(v.size() == 11);
188 assert(is_contiguous_container_asan_correct(v));
189 return;
190 }
191 assert(0);
192 }
193
test_resize()194 void test_resize() {
195 std::vector<X> v;
196 v.reserve(3);
197 v.push_back(X(0));
198 try {
199 v.resize(3);
200 assert(0);
201 } catch (int e) {
202 assert(v.size() == 1);
203 }
204 assert(v.size() == 1);
205 assert(is_contiguous_container_asan_correct(v));
206 }
207
test_resize_param()208 void test_resize_param() {
209 std::vector<X> v;
210 v.reserve(3);
211 v.push_back(X(0));
212 try {
213 v.resize(3, X(66));
214 assert(0);
215 } catch (int e) {
216 assert(v.size() == 1);
217 }
218 assert(v.size() == 1);
219 assert(is_contiguous_container_asan_correct(v));
220 }
221
main()222 int main() {
223 test_push_back();
224 test_emplace_back();
225 test_insert_range();
226 test_insert();
227 test_emplace();
228 test_insert_range2();
229 test_insert_n();
230 test_insert_n2();
231 test_resize();
232 test_resize_param();
233 }
234