1 //===--------------- catch_member_function_pointer_02.cpp -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Can a noexcept member function pointer be caught by a non-noexcept catch clause?
10 // UNSUPPORTED: no-exceptions, no-noexcept-function-type
11 
12 // Support for catching a function pointer including noexcept was shipped in macOS 10.13
13 // XFAIL: use_system_cxx_lib && {{.+}}-apple-macosx10.{{9|10|11|12}}
14 
15 // GCC supports noexcept function types but this test still fails.
16 // This is likely a bug in their implementation. Investigation needed.
17 // XFAIL: gcc-11
18 
19 #include <cassert>
20 
21 struct X {
22   template<bool Noexcept> void f() noexcept(Noexcept) {}
23 };
24 template<bool Noexcept> using FnType = void (X::*)() noexcept(Noexcept);
25 
26 template<bool ThrowNoexcept, bool CatchNoexcept>
27 void check()
28 {
29     try
30     {
31         auto p = &X::f<ThrowNoexcept>;
32         throw p;
33         assert(false);
34     }
35     catch (FnType<CatchNoexcept> p)
36     {
37         assert(ThrowNoexcept || !CatchNoexcept);
38         assert(p == &X::f<ThrowNoexcept>);
39     }
40     catch (...)
41     {
42         assert(!ThrowNoexcept && CatchNoexcept);
43     }
44 }
45 
46 void check_deep() {
47     FnType<true> p = &X::f<true>;
48     try
49     {
50         throw &p;
51     }
52     catch (FnType<false> *q)
53     {
54         assert(false);
55     }
56     catch (FnType<true> *q)
57     {
58     }
59     catch (...)
60     {
61         assert(false);
62     }
63 }
64 
65 int main(int, char**)
66 {
67     check<false, false>();
68     check<false, true>();
69     check<true, false>();
70     check<true, true>();
71     check_deep();
72 
73     return 0;
74 }
75