//===--------------------- inherited_exception.cpp ------------------------===// | |
// | |
// The LLVM Compiler Infrastructure | |
// | |
// This file is dual licensed under the MIT and the University of Illinois Open | |
// Source Licenses. See LICENSE.TXT for details. | |
// | |
//===----------------------------------------------------------------------===// | |
// | |
// This test case checks specifically the cases under C++ ABI 15.3.1, and 15.3.2 | |
// | |
// C++ ABI 15.3: | |
// A handler is a match for an exception object of type E if | |
// / * The handler is of type cv T or cv T& and E and T are the same type \ | |
// | (ignoring the top-level cv-qualifiers), or | | |
// | * the handler is of type cv T or cv T& and T is an unambiguous base | | |
// \ class of E, or / | |
// * the handler is of type cv1 T* cv2 and E is a pointer type that can | |
// be converted to the type of the handler by either or both of | |
// o a standard pointer conversion (4.10 [conv.ptr]) not involving | |
// conversions to private or protected or ambiguous classes | |
// o a qualification conversion | |
// * the handler is a pointer or pointer to member type and E is | |
// std::nullptr_t | |
// | |
//===----------------------------------------------------------------------===// | |
#include <assert.h> | |
struct Base { | |
int b1; | |
}; | |
struct Base2 { | |
int b2; | |
}; | |
struct Child : public Base, public Base2 { | |
int c; | |
}; | |
void f1() { | |
Child child; | |
child.b1 = 10; | |
child.b2 = 11; | |
child.c = 12; | |
throw child; | |
} | |
void f2() { | |
Child child; | |
child.b1 = 10; | |
child.b2 = 11; | |
child.c = 12; | |
throw static_cast<Base2&>(child); | |
} | |
void f3() { | |
static Child child; | |
child.b1 = 10; | |
child.b2 = 11; | |
child.c = 12; | |
throw static_cast<Base2*>(&child); | |
} | |
int main() | |
{ | |
try | |
{ | |
f1(); | |
assert(false); | |
} | |
catch (const Child& c) | |
{ | |
assert(true); | |
} | |
catch (const Base& b) | |
{ | |
assert(false); | |
} | |
catch (...) | |
{ | |
assert(false); | |
} | |
try | |
{ | |
f1(); | |
assert(false); | |
} | |
catch (const Base& c) | |
{ | |
assert(true); | |
} | |
catch (const Child& b) | |
{ | |
assert(false); | |
} | |
catch (...) | |
{ | |
assert(false); | |
} | |
try | |
{ | |
f1(); | |
assert(false); | |
} | |
catch (const Base2& c) | |
{ | |
assert(true); | |
} | |
catch (const Child& b) | |
{ | |
assert(false); | |
} | |
catch (...) | |
{ | |
assert(false); | |
} | |
try | |
{ | |
f2(); | |
assert(false); | |
} | |
catch (const Child& c) | |
{ | |
assert(false); | |
} | |
catch (const Base& b) | |
{ | |
assert(false); | |
} | |
catch (const Base2& b) | |
{ | |
assert(true); | |
} | |
catch (...) | |
{ | |
assert(false); | |
} | |
try | |
{ | |
f3(); | |
assert(false); | |
} | |
catch (const Base* c) | |
{ | |
assert(false); | |
} | |
catch (const Child* b) | |
{ | |
assert(false); | |
} | |
catch (const Base2* c) | |
{ | |
assert(true); | |
} | |
catch (...) | |
{ | |
assert(false); | |
} | |
} |