1 //===--------------- catch_member_function_pointer_01.cpp -----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // GCC incorrectly allows PMF type "void (T::*)()" to be caught as "void (T::*)() const"
11 // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69375
12 // XFAIL: gcc
13 // UNSUPPORTED: libcxxabi-no-exceptions
14 #include <cassert>
15 
16 struct A
17 {
18     void foo() {}
19     void bar() const {}
20 };
21 
22 typedef void (A::*mf1)();
23 typedef void (A::*mf2)() const;
24 
25 struct B : public A
26 {
27 };
28 
29 typedef void (B::*dmf1)();
30 typedef void (B::*dmf2)() const;
31 
32 template <class Tp>
33 bool can_convert(Tp) { return true; }
34 
35 template <class>
36 bool can_convert(...) { return false; }
37 
38 
39 void test1()
40 {
41     try
42     {
43         throw &A::foo;
44         assert(false);
45     }
46     catch (mf2)
47     {
48         assert(false);
49     }
50     catch (mf1)
51     {
52     }
53 }
54 
55 void test2()
56 {
57     try
58     {
59         throw &A::bar;
60         assert(false);
61     }
62     catch (mf1)
63     {
64         assert(false);
65     }
66     catch (mf2)
67     {
68     }
69 }
70 
71 
72 
73 void test_derived()
74 {
75     try
76     {
77         throw (mf1)0;
78         assert(false);
79     }
80     catch (dmf2)
81     {
82        assert(false);
83     }
84     catch (dmf1)
85     {
86        assert(false);
87     }
88     catch (mf1)
89     {
90     }
91 
92     try
93     {
94         throw (mf2)0;
95         assert(false);
96     }
97     catch (dmf1)
98     {
99        assert(false);
100     }
101     catch (dmf2)
102     {
103        assert(false);
104     }
105     catch (mf2)
106     {
107     }
108 
109     assert(!can_convert<mf1>((dmf1)0));
110     assert(!can_convert<mf2>((dmf1)0));
111     try
112     {
113         throw (dmf1)0;
114         assert(false);
115     }
116     catch (mf2)
117     {
118        assert(false);
119     }
120     catch (mf1)
121     {
122        assert(false);
123     }
124     catch (...)
125     {
126     }
127 
128     assert(!can_convert<mf1>((dmf2)0));
129     assert(!can_convert<mf2>((dmf2)0));
130     try
131     {
132         throw (dmf2)0;
133         assert(false);
134     }
135     catch (mf2)
136     {
137        assert(false);
138     }
139     catch (mf1)
140     {
141         assert(false);
142     }
143     catch (...)
144     {
145     }
146 }
147 
148 void test_void()
149 {
150     assert(!can_convert<void*>(&A::foo));
151     try
152     {
153         throw &A::foo;
154         assert(false);
155     }
156     catch (void*)
157     {
158         assert(false);
159     }
160     catch(...)
161     {
162     }
163 }
164 
165 int main()
166 {
167     test1();
168     test2();
169     test_derived();
170     test_void();
171 }
172