xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp (revision 52dd4dbb1ad30ed057c532148cc95f34efe34aa0)
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 
9 struct 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 
16 struct 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 
23 struct 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 
30 void 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 
35 void 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 
43 void 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 
52 void 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 
62 void 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 
71 void 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 
80 void 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 
89 void 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 
100 void throw_catch_pointer_c() noexcept {
101   try {
102     int a = 1;
103     throw &a;
104   } catch(const int *) {}
105 }
106 
107 void throw_catch_pointer_v() noexcept {
108   try {
109     int a = 1;
110     throw &a;
111   } catch(volatile int *) {}
112 }
113 
114 void throw_catch_pointer_cv() noexcept {
115   try {
116     int a = 1;
117     throw &a;
118   } catch(const volatile int *) {}
119 }
120 
121 void 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 
130 void throw_catch_multi_ptr_2() noexcept {
131   try {
132     char **p = 0;
133     throw p;
134   } catch (const char *const *) {
135   }
136 }
137 
138 void throw_catch_multi_ptr_3() noexcept {
139   try {
140     char **p = 0;
141     throw p;
142   } catch (volatile char *const *) {
143   }
144 }
145 
146 void 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.
157 void throw_catch_multi_ptr_5() noexcept {
158   try {
159     double *a[2][3];
160     throw a;
161   } catch (double *(*)[3]) {
162   }
163 }
164 
165 
166 void 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 
175 void 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 
184 void 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 
193 void 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 
202 void 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 
211 void 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 
220 class base {};
221 class derived: public base {};
222 
223 void 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 
231 void throw_derived_alias_catch_base() noexcept {
232   using alias = derived;
233 
234   try {
235     throw alias();
236   } catch(base &) {
237   }
238 }
239 
240 void throw_derived_catch_base_alias() noexcept {
241   using alias = base;
242 
243   try {
244     throw derived();
245   } catch(alias &) {
246   }
247 }
248 
249 void throw_derived_catch_base_ptr_c() noexcept {
250   try {
251     derived d;
252     throw &d;
253   } catch(const base *) {
254   }
255 }
256 
257 void 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 
267 class A {};
268 class B : A {};
269 
270 // The following alias hell is deliberately created for testing.
271 using aliasedA = A;
272 class C : protected aliasedA {};
273 
274 typedef aliasedA moreAliasedA;
275 class D : public moreAliasedA {};
276 
277 using moreMoreAliasedA = moreAliasedA;
278 using aliasedD = D;
279 class E : public moreMoreAliasedA, public aliasedD {};
280 
281 void 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 
290 void 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 
299 void 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 
308 void 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 
317 void 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 
326 void 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 
335 void 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 
345 void 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 
356 void 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 
366 void 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 
377 void 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 
387 namespace 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 
398 namespace 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 
409 namespace 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 
420 struct baseMember {
421     int *iptr;
422     virtual void foo(){};
423 };
424 
425 struct derivedMember : baseMember {
426     void foo() override {};
427 };
428 
429 void 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 
437 void throw_basefn_catch_basefn() noexcept {
438   try {
439     throw &baseMember::foo;
440   } catch(void(baseMember::*)()) {
441   }
442 }
443 
444 void 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 
453 void 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 
461 void 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 
470 void 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 
479 void 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 
490 void 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 
502 void 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 
514 void 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 
526 void 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 
538 void 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 
551 void implicit_int_thrower() {
552   throw 1;
553 }
554 
555 void explicit_int_thrower() noexcept(false) {
556   throw 1;
557 }
558 
559 void 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 
564 void 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 
569 void 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 
577 template<typename T>
578 void 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 
584 void 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 
589 void 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 
594 void 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 
599 namespace std {
600 class bad_alloc {};
601 }
602 
603 void alloc() {
604   throw std::bad_alloc();
605 }
606 
607 void 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 
612 void 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 
617 void 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 
622 void 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 
630 class ignored1 {};
631 class ignored2 {};
632 
633 void 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 
638 void 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 
647 void 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 
653 void thrower(int n) {
654   throw n;
655 }
656 
657 int 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 
664 int indirectly_recursive(int n) noexcept;
665 
666 int recursion_helper(int n) {
667   indirectly_recursive(n);
668 }
669 
670 int 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 
677 struct super_throws {
678   super_throws() noexcept(false) { throw 42; }
679 };
680 
681 struct 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 
686 struct 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 
693 struct 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 
700 struct init {
701   explicit init(int, int) noexcept(false) { throw 42; }
702 };
703 
704 struct 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 
711 int 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 
720 void 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 
723 void test_basic_throw() noexcept(false) { throw 42; }
724 
725 void only_calls_non_throwing() noexcept {
726   test_basic_no_throw();
727 }
728 
729 void 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 
735 namespace PR55143 { namespace PR40583 {
736 
737 struct 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 
746 struct 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 
760 void pointer_exception_can_not_escape_with_const_void_handler() noexcept {
761   // 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
762   const int value = 42;
763   try {
764     throw &value;
765   } catch (const void *) {
766   }
767 }
768 
769 void pointer_exception_can_not_escape_with_void_handler() noexcept {
770   // 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
771   int value = 42;
772   try {
773     throw &value;
774   } catch (void *) {
775   }
776 }
777