1// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-escape %t -- \
2// RUN: -config="{CheckOptions: { \
3// RUN: bugprone-exception-escape.IgnoredExceptions: 'ignored1,ignored2', \
4// RUN: bugprone-exception-escape.FunctionsThatShouldNotThrow: 'enabled1,enabled2,enabled3' \
5// RUN: }}" \
6// RUN: -- -fexceptions
7// FIXME: Fix the checker to work in C++17 or later mode.
8
9struct throwing_destructor {
10 ~throwing_destructor() {
11 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions
12 throw 1;
13 }
14};
15// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~throwing_destructor' here
16
17struct throwing_move_constructor {
18 throwing_move_constructor(throwing_move_constructor&&) {
19 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions
20 throw 1;
21 }
22};
23// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_move_constructor' here
24
25struct throwing_move_assignment {
26 throwing_move_assignment& operator=(throwing_move_assignment&&) {
27 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
28 throw 1;
29 }
30};
31// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator=' here
32
33void throwing_noexcept() noexcept {
34 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions
35 throw 1;
36}
37// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_noexcept' here
38
39void 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
47void 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// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_and_catch_some' here
56
57void throw_and_catch_each(int n) noexcept {
58 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions
59 try {
60 if (n) throw 1;
61 throw 1.1;
62 } catch(int &) {
63 } catch(double &) {
64 }
65}
66
67void throw_and_catch_all(int n) noexcept {
68 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions
69 try {
70 if (n) throw 1;
71 throw 1.1;
72 } catch(...) {
73 }
74}
75
76void throw_and_rethrow() noexcept {
77 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions
78 try {
79 throw 1;
80 } catch(int &) {
81 throw;
82 }
83}
84// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_and_rethrow' here
85
86void throw_catch_throw() noexcept {
87 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions
88 try {
89 throw 1;
90 } catch(int &) {
91 throw 2;
92 }
93}
94// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_catch_throw' here
95
96void throw_catch_rethrow_the_rest(int n) noexcept {
97 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions
98 try {
99 if (n) throw 1;
100 throw 1.1;
101 } catch(int &) {
102 } catch(...) {
103 throw;
104 }
105}
106// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_catch_rethrow_the_rest' here
107
108void throw_catch_pointer_c() noexcept {
109 try {
110 int a = 1;
111 throw &a;
112 } catch(const int *) {}
113}
114
115void throw_catch_pointer_v() noexcept {
116 try {
117 int a = 1;
118 throw &a;
119 } catch(volatile int *) {}
120}
121
122void throw_catch_pointer_cv() noexcept {
123 try {
124 int a = 1;
125 throw &a;
126 } catch(const volatile int *) {}
127}
128
129void throw_catch_multi_ptr_1() noexcept {
130 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_multi_ptr_1' which should not throw exceptions
131 try {
132 char **p = 0;
133 throw p;
134 } catch (const char **) {
135 }
136}
137// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_catch_multi_ptr_1' here
138
139void throw_catch_multi_ptr_2() noexcept {
140 try {
141 char **p = 0;
142 throw p;
143 } catch (const char *const *) {
144 }
145}
146
147void throw_catch_multi_ptr_3() noexcept {
148 try {
149 char **p = 0;
150 throw p;
151 } catch (volatile char *const *) {
152 }
153}
154
155void throw_catch_multi_ptr_4() noexcept {
156 try {
157 char **p = 0;
158 throw p;
159 } catch (volatile const char *const *) {
160 }
161}
162
163// FIXME: In this case 'a' is convertible to the handler and should be caught
164// but in reality it's thrown. Note that clang doesn't report a warning for
165// this either.
166void throw_catch_multi_ptr_5() noexcept {
167 try {
168 double *a[2][3];
169 throw a;
170 } catch (double *(*)[3]) {
171 }
172}
173
174
175void throw_c_catch_pointer() noexcept {
176 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer' which should not throw exceptions
177 try {
178 int a = 1;
179 const int *p = &a;
180 throw p;
181 } catch(int *) {}
182}
183// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer' here
184
185void throw_c_catch_pointer_v() noexcept {
186 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer_v' which should not throw exceptions
187 try {
188 int a = 1;
189 const int *p = &a;
190 throw p;
191 } catch(volatile int *) {}
192}
193// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer_v' here
194
195void throw_v_catch_pointer() noexcept {
196 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer' which should not throw exceptions
197 try {
198 int a = 1;
199 volatile int *p = &a;
200 throw p;
201 } catch(int *) {}
202}
203// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer' here
204
205void throw_v_catch_pointer_c() noexcept {
206 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer_c' which should not throw exceptions
207 try {
208 int a = 1;
209 volatile int *p = &a;
210 throw p;
211 } catch(const int *) {}
212}
213// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer_c' here
214
215void throw_cv_catch_pointer_c() noexcept {
216 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_c' which should not throw exceptions
217 try {
218 int a = 1;
219 const volatile int *p = &a;
220 throw p;
221 } catch(const int *) {}
222}
223// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_c' here
224
225void throw_cv_catch_pointer_v() noexcept {
226 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_v' which should not throw exceptions
227 try {
228 int a = 1;
229 const volatile int *p = &a;
230 throw p;
231 } catch(volatile int *) {}
232}
233// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_v' here
234
235class base {};
236class derived: public base {};
237
238void throw_derived_catch_base() noexcept {
239 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions
240 try {
241 throw derived();
242 } catch(base &) {
243 }
244}
245
246void throw_derived_alias_catch_base() noexcept {
247 using alias = derived;
248
249 try {
250 throw alias();
251 } catch(base &) {
252 }
253}
254
255void throw_derived_catch_base_alias() noexcept {
256 using alias = base;
257
258 try {
259 throw derived();
260 } catch(alias &) {
261 }
262}
263
264void throw_derived_catch_base_ptr_c() noexcept {
265 try {
266 derived d;
267 throw &d;
268 } catch(const base *) {
269 }
270}
271
272void throw_derived_catch_base_ptr() noexcept {
273 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ptr' which should not throw exceptions
274 try {
275 derived d;
276 const derived *p = &d;
277 throw p;
278 } catch(base *) {
279 }
280}
281// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'const derived *' may be thrown in function 'throw_derived_catch_base_ptr' here
282
283class A {};
284class B : A {};
285
286// The following alias hell is deliberately created for testing.
287using aliasedA = A;
288class C : protected aliasedA {};
289
290typedef aliasedA moreAliasedA;
291class D : public moreAliasedA {};
292
293using moreMoreAliasedA = moreAliasedA;
294using aliasedD = D;
295class E : public moreMoreAliasedA, public aliasedD {};
296
297void throw_derived_catch_base_private() noexcept {
298 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private' which should not throw exceptions
299 try {
300 B b;
301 throw b;
302 } catch(A) {
303 }
304}
305// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B' may be thrown in function 'throw_derived_catch_base_private' here
306
307void throw_derived_catch_base_private_ptr() noexcept {
308 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions
309 try {
310 B b;
311 throw &b;
312 } catch(A *) {
313 }
314}
315// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B *' may be thrown in function 'throw_derived_catch_base_private_ptr' here
316
317void throw_derived_catch_base_protected() noexcept {
318 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions
319 try {
320 C c;
321 throw c;
322 } catch(A) {
323 }
324}
325// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C' may be thrown in function 'throw_derived_catch_base_protected' here
326
327void throw_derived_catch_base_protected_ptr() noexcept {
328 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions
329 try {
330 C c;
331 throw &c;
332 } catch(A *) {
333 }
334}
335// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C *' may be thrown in function 'throw_derived_catch_base_protected_ptr' here
336
337void throw_derived_catch_base_ambiguous() noexcept {
338 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions
339 try {
340 E e;
341 throw e;
342 } catch(A) {
343 }
344}
345// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous' here
346
347void throw_derived_catch_base_ambiguous_ptr() noexcept {
348 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions
349 try {
350 E e;
351 throw e;
352 } catch(A) {
353 }
354}
355// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' here
356
357void throw_alias_catch_original() noexcept {
358 using alias = int;
359
360 try {
361 alias a = 3;
362 throw a;
363 } catch (int) {
364 }
365}
366
367void throw_alias_catch_original_warn() noexcept {
368 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_alias_catch_original_warn' which should not throw exceptions
369 using alias = float;
370
371 try {
372 alias a = 3;
373 throw a;
374 } catch (int) {
375 }
376}
377// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'float' may be thrown in function 'throw_alias_catch_original_warn' here
378
379void throw_original_catch_alias() noexcept {
380 using alias = char;
381
382 try {
383 char **p = 0;
384 throw p;
385 } catch (volatile const alias *const *) {
386 }
387}
388
389void throw_original_catch_alias_warn() noexcept {
390 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_warn' which should not throw exceptions
391 using alias = int;
392
393 try {
394 char **p = 0;
395 throw p;
396 } catch (volatile const alias *const *) {
397 }
398}
399// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_warn' here
400
401void throw_original_catch_alias_2() noexcept {
402 using alias = const char *const;
403
404 try {
405 char **p = 0;
406 throw p;
407 } catch (volatile alias *) {
408 }
409}
410
411namespace a {
412 int foo() { return 0; };
413
414 void throw_regular_catch_regular() noexcept {
415 try {
416 throw &foo;
417 } catch(int (*)()) {
418 }
419 }
420}
421
422namespace b {
423 inline int foo() { return 0; };
424
425 void throw_inline_catch_regular() noexcept {
426 try {
427 throw &foo;
428 } catch(int (*)()) {
429 }
430 }
431}
432
433namespace c {
434 inline int foo() noexcept { return 0; };
435
436 void throw_noexcept_catch_regular() noexcept {
437 try {
438 throw &foo;
439 } catch(int (*)()) {
440 }
441 }
442}
443
444struct baseMember {
445 int *iptr;
446 virtual void foo(){};
447};
448
449struct derivedMember : baseMember {
450 void foo() override {};
451};
452
453void throw_basefn_catch_derivedfn() noexcept {
454 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basefn_catch_derivedfn' which should not throw exceptions
455 try {
456 throw &baseMember::foo;
457 } catch(void(derivedMember::*)()) {
458 }
459}
460// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'void (baseMember::*)()' may be thrown in function 'throw_basefn_catch_derivedfn' here
461
462void throw_basefn_catch_basefn() noexcept {
463 try {
464 throw &baseMember::foo;
465 } catch(void(baseMember::*)()) {
466 }
467}
468
469void throw_basem_catch_basem_throw() noexcept {
470 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_basem_throw' which should not throw exceptions
471 try {
472 auto ptr = &baseMember::iptr;
473 throw &ptr;
474 } catch(const int* baseMember::* const *) {
475 }
476}
477// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_basem_throw' here
478
479void throw_basem_catch_basem() noexcept {
480 try {
481 auto ptr = &baseMember::iptr;
482 throw &ptr;
483 } catch(const int* const baseMember::* const *) {
484 }
485}
486
487void throw_basem_catch_derivedm() noexcept {
488 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_derivedm' which should not throw exceptions
489 try {
490 auto ptr = &baseMember::iptr;
491 throw &ptr;
492 } catch(const int* const derivedMember::* const *) {
493 }
494}
495// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_derivedm' here
496
497void throw_derivedm_catch_basem() noexcept {
498 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions
499 try {
500 int *derivedMember::* ptr = &derivedMember::iptr;
501 throw &ptr;
502 } catch(const int* const baseMember::* const *) {
503 }
504}
505// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *derivedMember::**' may be thrown in function 'throw_derivedm_catch_basem' here
506
507void throw_original_catch_alias_2_warn() noexcept {
508 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions
509 using alias = const int *const;
510
511 try {
512 char **p = 0;
513 throw p;
514 } catch (volatile alias *) {
515 }
516}
517// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_2_warn' here
518
519void try_nested_try(int n) noexcept {
520 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions
521 try {
522 try {
523 if (n) throw 1;
524 throw 1.1;
525 } catch(int &) {
526 }
527 } catch(double &) {
528 }
529}
530
531void bad_try_nested_try(int n) noexcept {
532 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions
533 try {
534 if (n) throw 1;
535 try {
536 throw 1.1;
537 } catch(int &) {
538 }
539 } catch(double &) {
540 }
541}
542// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: unhandled exception of type 'int' may be thrown in function 'bad_try_nested_try' here
543
544void try_nested_catch() noexcept {
545 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions
546 try {
547 try {
548 throw 1;
549 } catch(int &) {
550 throw 1.1;
551 }
552 } catch(double &) {
553 }
554}
555
556void catch_nested_try() noexcept {
557 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions
558 try {
559 throw 1;
560 } catch(int &) {
561 try {
562 throw 1;
563 } catch(int &) {
564 }
565 }
566}
567
568void bad_catch_nested_try() noexcept {
569 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions
570 try {
571 throw 1;
572 } catch(int &) {
573 try {
574 throw 1.1;
575 } catch(int &) {
576 }
577 } catch(double &) {
578 }
579}
580// CHECK-MESSAGES: :[[@LINE-6]]:7: note: frame #0: unhandled exception of type 'double' may be thrown in function 'bad_catch_nested_try' here
581
582void implicit_int_thrower() {
583 throw 1;
584}
585
586void explicit_int_thrower() noexcept(false) {
587 throw 1;
588}
589
590void indirect_implicit() noexcept {
591 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions
592 implicit_int_thrower();
593}
594// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'implicit_int_thrower' here
595// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here
596
597void indirect_explicit() noexcept {
598 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions
599 explicit_int_thrower();
600}
601// CHECK-MESSAGES: :[[@LINE-14]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'explicit_int_thrower' here
602// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here
603
604void indirect_catch() noexcept {
605 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions
606 try {
607 implicit_int_thrower();
608 } catch(int&) {
609 }
610}
611
612template<typename T>
613void dependent_throw() noexcept(sizeof(T)<4) {
614 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions
615 if (sizeof(T) > 4)
616 throw 1;
617}
618
619void swap(int&, int&) {
620 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions
621 throw 1;
622}
623// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'swap' here
624
625void iter_swap(int&, int&) {
626 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions
627 throw 1;
628}
629// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_swap' here
630
631void iter_move(int&) {
632 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions
633 throw 1;
634}
635// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_move' here
636
637namespace std {
638class bad_alloc {};
639}
640
641void alloc() {
642 throw std::bad_alloc();
643}
644
645void allocator() noexcept {
646 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions
647 alloc();
648}
649
650void enabled1() {
651 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions
652 throw 1;
653}
654// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here
655
656void enabled2() {
657 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions
658 enabled1();
659}
660// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here
661// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'enabled2' calls function 'enabled1' here
662
663void enabled3() {
664 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions
665 try {
666 enabled1();
667 } catch(...) {
668 }
669}
670
671void deep_level3_thrower() {
672 throw 42;
673}
674
675void deep_level2_caller() {
676 deep_level3_thrower();
677}
678
679void deep_level1_caller() {
680 deep_level2_caller();
681}
682
683void deep_stack_test() noexcept {
684// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'deep_stack_test' which should not throw exceptions
685 deep_level1_caller();
686}
687// CHECK-MESSAGES: :[[@LINE-15]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'deep_level3_thrower' here
688// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #1: function 'deep_level2_caller' calls function 'deep_level3_thrower' here
689// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #2: function 'deep_level1_caller' calls function 'deep_level2_caller' here
690// CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #3: function 'deep_stack_test' calls function 'deep_level1_caller' here
691
692// Template function call stack
693template<typename T>
694void template_thrower(T t) {
695 throw T{};
696}
697
698template<typename T>
699void template_caller(T t) {
700 template_thrower<T>(t);
701}
702
703void template_stack_test() noexcept {
704// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'template_stack_test' which should not throw exceptions
705 template_caller<char>(t: 'a');
706}
707// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #0: unhandled exception of type 'char' may be thrown in function 'template_thrower<char>' here
708// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #1: function 'template_caller<char>' calls function 'template_thrower<char>' here
709// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #2: function 'template_stack_test' calls function 'template_caller<char>' here
710
711// template function without instantiation is not warned
712template<typename T>
713void template_function_stack_test(T t) noexcept {
714 template_thrower(t);
715}
716
717void multiple_exception_types(int choice) noexcept {
718// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'multiple_exception_types' which should not throw exceptions
719 if (choice == 1) {
720 throw 42;
721 } else if (choice == 2) {
722 throw 3.14;
723 } else if (choice == 3) {
724 throw "string";
725 }
726}
727// CHECK-MESSAGES: note: frame #0: unhandled exception of type '{{(int|double|const char \*)}}' may be thrown in function 'multiple_exception_types' here
728
729class ignored1 {};
730class ignored2 {};
731
732void this_does_not_count() noexcept {
733 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions
734 throw ignored1();
735}
736
737void this_does_not_count_either(int n) noexcept {
738 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions
739 try {
740 throw 1;
741 if (n) throw ignored2();
742 } catch(int &) {
743 }
744}
745
746void this_counts(int n) noexcept {
747 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions
748 if (n) throw 1;
749 throw ignored1();
750}
751// CHECK-MESSAGES: :[[@LINE-3]]:10: note: frame #0: unhandled exception of type 'int' may be thrown in function 'this_counts' here
752
753void thrower(int n) {
754 throw n;
755}
756
757int directly_recursive(int n) noexcept {
758 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions
759 if (n == 0)
760 thrower(n);
761 return directly_recursive(n);
762}
763// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here
764// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'directly_recursive' calls function 'thrower' here
765
766int indirectly_recursive(int n) noexcept;
767
768int recursion_helper(int n) {
769 indirectly_recursive(n);
770 return 0;
771}
772
773int indirectly_recursive(int n) noexcept {
774 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions
775 if (n == 0)
776 thrower(n);
777 return recursion_helper(n);
778}
779// CHECK-MESSAGES: :[[@LINE-25]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here
780// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'indirectly_recursive' calls function 'thrower' here
781
782struct super_throws {
783 super_throws() noexcept(false) { throw 42; }
784};
785
786struct sub_throws : super_throws {
787 sub_throws() noexcept : super_throws() {}
788 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions
789};
790// CHECK-MESSAGES: :[[@LINE-7]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here
791// CHECK-MESSAGES: :[[@LINE-4]]:27: note: frame #1: function 'sub_throws' calls function 'super_throws' here
792
793struct init_member_throws {
794 super_throws s;
795
796 init_member_throws() noexcept : s() {}
797 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions
798};
799// CHECK-MESSAGES: :[[@LINE-16]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here
800// CHECK-MESSAGES: :[[@LINE-4]]:35: note: frame #1: function 'init_member_throws' calls function 'super_throws' here
801
802struct implicit_init_member_throws {
803 super_throws s;
804
805 implicit_init_member_throws() noexcept {}
806 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions
807};
808// CHECK-MESSAGES: :[[@LINE-25]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here
809// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #1: function 'implicit_init_member_throws' calls function 'super_throws'
810
811struct init {
812 explicit init(int, int) noexcept(false) { throw 42; }
813};
814
815struct in_class_init_throws {
816 init i{1, 2};
817
818 in_class_init_throws() noexcept {}
819 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions
820};
821// CHECK-MESSAGES: :[[@LINE-9]]:45: note: frame #0: unhandled exception of type 'int' may be thrown in function 'init' here
822// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #1: function 'in_class_init_throws' calls function 'init' here
823
824int main() {
825 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
826 throw 1;
827 return 0;
828}
829// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'main' here
830
831// The following function all incorrectly throw exceptions, *but* calling them
832// should not yield a warning because they are marked as noexcept.
833
834void test_basic_no_throw() noexcept { throw 42; }
835// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions
836// CHECK-MESSAGES: :[[@LINE-2]]:39: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_no_throw' here
837
838void test_basic_throw() noexcept(false) { throw 42; }
839
840void only_calls_non_throwing() noexcept {
841 test_basic_no_throw();
842}
843
844void calls_non_and_throwing() noexcept {
845// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_non_and_throwing' which should not throw exceptions
846 test_basic_no_throw();
847 test_basic_throw();
848}
849// CHECK-MESSAGES: :[[@LINE-11]]:43: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_throw' here
850// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'calls_non_and_throwing' calls function 'test_basic_throw' here
851
852namespace PR55143 { namespace PR40583 {
853
854struct test_explicit_throw {
855 test_explicit_throw() throw(int) { throw 42; }
856 test_explicit_throw(const test_explicit_throw&) throw(int) { throw 42; }
857 test_explicit_throw(test_explicit_throw&&) throw(int) { throw 42; }
858 test_explicit_throw& operator=(const test_explicit_throw&) throw(int) { throw 42; }
859 test_explicit_throw& operator=(test_explicit_throw&&) throw(int) { throw 42; }
860 ~test_explicit_throw() throw(int) { throw 42; }
861};
862
863struct test_implicit_throw {
864 test_implicit_throw() { throw 42; }
865 test_implicit_throw(const test_implicit_throw&) { throw 42; }
866 test_implicit_throw(test_implicit_throw&&) { throw 42; }
867 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions
868 // CHECK-MESSAGES: :[[@LINE-2]]:50: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_implicit_throw' here
869 test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; }
870 test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; }
871 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
872 // CHECK-MESSAGES: :[[@LINE-2]]:61: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator='
873 ~test_implicit_throw() { throw 42; }
874 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions
875 // CHECK-MESSAGES: :[[@LINE-2]]:30: note: frame #0: unhandled exception of type 'int' may be thrown in function '~test_implicit_throw' here
876};
877
878}}
879
880void pointer_exception_can_not_escape_with_const_void_handler() noexcept {
881 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_const_void_handler' which should not throw exceptions
882 const int value = 42;
883 try {
884 throw &value;
885 } catch (const void *) {
886 }
887}
888
889void pointer_exception_can_not_escape_with_void_handler() noexcept {
890 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_void_handler' which should not throw exceptions
891 int value = 42;
892 try {
893 throw &value;
894 } catch (void *) {
895 }
896}
897

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp