forked from mirror/libcxxabi
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
3.3 KiB
C++
175 lines
3.3 KiB
C++
//===--------------------- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// UNSUPPORTED: libcxxabi-no-exceptions
|
|
|
|
// Clang emits warnings about exceptions of type 'Child' being caught by
|
|
// an earlier handler of type 'Base'. Congrats clang, you've just
|
|
// diagnosed the behavior under test.
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic ignored "-Wexceptions"
|
|
#endif
|
|
|
|
#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);
|
|
}
|
|
}
|