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

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