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