//===--------------- catch_member_function_pointer_01.cpp -----------------===// | |
// | |
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
// See https://llvm.org/LICENSE.txt for license information. | |
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
// | |
//===----------------------------------------------------------------------===// | |
// GCC incorrectly allows PMF type "void (T::*)()" to be caught as "void (T::*)() const" | |
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69375 | |
// XFAIL: gcc | |
// UNSUPPORTED: libcxxabi-no-exceptions | |
#include <cassert> | |
struct A | |
{ | |
void foo() {} | |
void bar() const {} | |
}; | |
typedef void (A::*mf1)(); | |
typedef void (A::*mf2)() const; | |
struct B : public A | |
{ | |
}; | |
typedef void (B::*dmf1)(); | |
typedef void (B::*dmf2)() const; | |
template <class Tp> | |
bool can_convert(Tp) { return true; } | |
template <class> | |
bool can_convert(...) { return false; } | |
void test1() | |
{ | |
try | |
{ | |
throw &A::foo; | |
assert(false); | |
} | |
catch (mf2) | |
{ | |
assert(false); | |
} | |
catch (mf1) | |
{ | |
} | |
} | |
void test2() | |
{ | |
try | |
{ | |
throw &A::bar; | |
assert(false); | |
} | |
catch (mf1) | |
{ | |
assert(false); | |
} | |
catch (mf2) | |
{ | |
} | |
} | |
void test_derived() | |
{ | |
try | |
{ | |
throw (mf1)0; | |
assert(false); | |
} | |
catch (dmf2) | |
{ | |
assert(false); | |
} | |
catch (dmf1) | |
{ | |
assert(false); | |
} | |
catch (mf1) | |
{ | |
} | |
try | |
{ | |
throw (mf2)0; | |
assert(false); | |
} | |
catch (dmf1) | |
{ | |
assert(false); | |
} | |
catch (dmf2) | |
{ | |
assert(false); | |
} | |
catch (mf2) | |
{ | |
} | |
assert(!can_convert<mf1>((dmf1)0)); | |
assert(!can_convert<mf2>((dmf1)0)); | |
try | |
{ | |
throw (dmf1)0; | |
assert(false); | |
} | |
catch (mf2) | |
{ | |
assert(false); | |
} | |
catch (mf1) | |
{ | |
assert(false); | |
} | |
catch (...) | |
{ | |
} | |
assert(!can_convert<mf1>((dmf2)0)); | |
assert(!can_convert<mf2>((dmf2)0)); | |
try | |
{ | |
throw (dmf2)0; | |
assert(false); | |
} | |
catch (mf2) | |
{ | |
assert(false); | |
} | |
catch (mf1) | |
{ | |
assert(false); | |
} | |
catch (...) | |
{ | |
} | |
} | |
void test_void() | |
{ | |
assert(!can_convert<void*>(&A::foo)); | |
try | |
{ | |
throw &A::foo; | |
assert(false); | |
} | |
catch (void*) | |
{ | |
assert(false); | |
} | |
catch(...) | |
{ | |
} | |
} | |
int main() | |
{ | |
test1(); | |
test2(); | |
test_derived(); | |
test_void(); | |
} |