1 // RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-escape %t -- \
2 // RUN: -config="{CheckOptions: [ \
3 // RUN: {key: bugprone-exception-escape.IgnoredExceptions, value: 'ignored1,ignored2'}, \
4 // RUN: {key: bugprone-exception-escape.FunctionsThatShouldNotThrow, value: 'enabled1,enabled2,enabled3'} \
5 // RUN: ]}" \
6 // RUN: -- -fexceptions
7
8 struct throwing_destructor {
~throwing_destructorthrowing_destructor9 ~throwing_destructor() {
10 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions
11 throw 1;
12 }
13 };
14
15 struct throwing_move_constructor {
throwing_move_constructorthrowing_move_constructor16 throwing_move_constructor(throwing_move_constructor&&) {
17 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions
18 throw 1;
19 }
20 };
21
22 struct throwing_move_assignment {
operator =throwing_move_assignment23 throwing_move_assignment& operator=(throwing_move_assignment&&) {
24 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
25 throw 1;
26 }
27 };
28
throwing_noexcept()29 void throwing_noexcept() noexcept {
30 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions
31 throw 1;
32 }
33
throwing_throw_nothing()34 void throwing_throw_nothing() throw() {
35 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions
36 throw 1;
37 }
38
throw_and_catch()39 void throw_and_catch() noexcept {
40 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions
41 try {
42 throw 1;
43 } catch(int &) {
44 }
45 }
46
throw_and_catch_some(int n)47 void throw_and_catch_some(int n) noexcept {
48 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions
49 try {
50 if (n) throw 1;
51 throw 1.1;
52 } catch(int &) {
53 }
54 }
55
throw_and_catch_each(int n)56 void throw_and_catch_each(int n) noexcept {
57 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions
58 try {
59 if (n) throw 1;
60 throw 1.1;
61 } catch(int &) {
62 } catch(double &) {
63 }
64 }
65
throw_and_catch_all(int n)66 void throw_and_catch_all(int n) noexcept {
67 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions
68 try {
69 if (n) throw 1;
70 throw 1.1;
71 } catch(...) {
72 }
73 }
74
throw_and_rethrow()75 void throw_and_rethrow() noexcept {
76 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions
77 try {
78 throw 1;
79 } catch(int &) {
80 throw;
81 }
82 }
83
throw_catch_throw()84 void throw_catch_throw() noexcept {
85 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions
86 try {
87 throw 1;
88 } catch(int &) {
89 throw 2;
90 }
91 }
92
throw_catch_rethrow_the_rest(int n)93 void throw_catch_rethrow_the_rest(int n) noexcept {
94 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions
95 try {
96 if (n) throw 1;
97 throw 1.1;
98 } catch(int &) {
99 } catch(...) {
100 throw;
101 }
102 }
103
104 class base {};
105 class derived: public base {};
106
throw_derived_catch_base()107 void throw_derived_catch_base() noexcept {
108 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions
109 try {
110 throw derived();
111 } catch(base &) {
112 }
113 }
114
try_nested_try(int n)115 void try_nested_try(int n) noexcept {
116 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions
117 try {
118 try {
119 if (n) throw 1;
120 throw 1.1;
121 } catch(int &) {
122 }
123 } catch(double &) {
124 }
125 }
126
bad_try_nested_try(int n)127 void bad_try_nested_try(int n) noexcept {
128 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions
129 try {
130 if (n) throw 1;
131 try {
132 throw 1.1;
133 } catch(int &) {
134 }
135 } catch(double &) {
136 }
137 }
138
try_nested_catch()139 void try_nested_catch() noexcept {
140 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions
141 try {
142 try {
143 throw 1;
144 } catch(int &) {
145 throw 1.1;
146 }
147 } catch(double &) {
148 }
149 }
150
catch_nested_try()151 void catch_nested_try() noexcept {
152 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions
153 try {
154 throw 1;
155 } catch(int &) {
156 try {
157 throw 1;
158 } catch(int &) {
159 }
160 }
161 }
162
bad_catch_nested_try()163 void bad_catch_nested_try() noexcept {
164 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions
165 try {
166 throw 1;
167 } catch(int &) {
168 try {
169 throw 1.1;
170 } catch(int &) {
171 }
172 } catch(double &) {
173 }
174 }
175
implicit_int_thrower()176 void implicit_int_thrower() {
177 throw 1;
178 }
179
180 void explicit_int_thrower() throw(int);
181
indirect_implicit()182 void indirect_implicit() noexcept {
183 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions
184 implicit_int_thrower();
185 }
186
indirect_explicit()187 void indirect_explicit() noexcept {
188 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions
189 explicit_int_thrower();
190 }
191
indirect_catch()192 void indirect_catch() noexcept {
193 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions
194 try {
195 implicit_int_thrower();
196 } catch(int&) {
197 }
198 }
199
200 template<typename T>
dependent_throw()201 void dependent_throw() noexcept(sizeof(T)<4) {
202 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions
203 if (sizeof(T) > 4)
204 throw 1;
205 }
206
swap(int &,int &)207 void swap(int&, int&) {
208 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions
209 throw 1;
210 }
211
212 namespace std {
213 class bad_alloc {};
214 }
215
alloc()216 void alloc() {
217 throw std::bad_alloc();
218 }
219
allocator()220 void allocator() noexcept {
221 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions
222 alloc();
223 }
224
enabled1()225 void enabled1() {
226 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions
227 throw 1;
228 }
229
enabled2()230 void enabled2() {
231 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions
232 enabled1();
233 }
234
enabled3()235 void enabled3() {
236 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions
237 try {
238 enabled1();
239 } catch(...) {
240 }
241 }
242
243 class ignored1 {};
244 class ignored2 {};
245
this_does_not_count()246 void this_does_not_count() noexcept {
247 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions
248 throw ignored1();
249 }
250
this_does_not_count_either(int n)251 void this_does_not_count_either(int n) noexcept {
252 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions
253 try {
254 throw 1;
255 if (n) throw ignored2();
256 } catch(int &) {
257 }
258 }
259
this_counts(int n)260 void this_counts(int n) noexcept {
261 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions
262 if (n) throw 1;
263 throw ignored1();
264 }
265
thrower(int n)266 void thrower(int n) {
267 throw n;
268 }
269
directly_recursive(int n)270 int directly_recursive(int n) noexcept {
271 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions
272 if (n == 0)
273 thrower(n);
274 return directly_recursive(n);
275 }
276
277 int indirectly_recursive(int n) noexcept;
278 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
279
recursion_helper(int n)280 int recursion_helper(int n) {
281 indirectly_recursive(n);
282 }
283
indirectly_recursive(int n)284 int indirectly_recursive(int n) noexcept {
285 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
286 if (n == 0)
287 thrower(n);
288 return recursion_helper(n);
289 }
290
291 struct super_throws {
super_throwssuper_throws292 super_throws() noexcept(false) { throw 42; }
293 };
294
295 struct sub_throws : super_throws {
sub_throwssub_throws296 sub_throws() noexcept : super_throws() {}
297 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions
298 };
299
300 struct super_throws_again {
301 super_throws_again() throw(int);
302 };
303
304 struct sub_throws_again : super_throws_again {
sub_throws_againsub_throws_again305 sub_throws_again() noexcept : super_throws_again() {}
306 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws_again' which should not throw exceptions
307 };
308
309 struct init_member_throws {
310 super_throws s;
311
init_member_throwsinit_member_throws312 init_member_throws() noexcept : s() {}
313 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions
314 };
315
316 struct implicit_init_member_throws {
317 super_throws s;
318
implicit_init_member_throwsimplicit_init_member_throws319 implicit_init_member_throws() noexcept {}
320 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions
321 };
322
323 struct init {
initinit324 explicit init(int, int) noexcept(false) { throw 42; }
325 };
326
327 struct in_class_init_throws {
328 init i{1, 2};
329
in_class_init_throwsin_class_init_throws330 in_class_init_throws() noexcept {}
331 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions
332 };
333
main()334 int main() {
335 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
336 throw 1;
337 return 0;
338 }
339