#include <exception>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
struct Base {
int b;
};
struct Base2 {
int b;
};
struct Derived1 : Base {
int b;
};
struct Derived2 : Base {
int b;
};
struct Derived3 : Base2 {
int b;
};
struct Private : private Base {
int b;
};
struct Protected : protected Base {
int b;
};
struct Virtual1 : virtual Base {
int b;
};
struct Virtual2 : virtual Base {
int b;
};
struct Ambiguous1 : Derived1, Derived2 {
int b;
};
struct Ambiguous2 : Derived1, Private {
int b;
};
struct Ambiguous3 : Derived1, Protected {
int b;
};
struct NoPublic1 : Private, Base2 {
int b;
};
struct NoPublic2 : Protected, Base2 {
int b;
};
struct Catchable1 : Derived3, Derived1 {
int b;
};
struct Catchable2 : Virtual1, Virtual2 {
int b;
};
struct Catchable3 : virtual Base, Virtual2 {
int b;
};
template <typename T
,
typename E
>
void assert_catches() {
try {
throw static_cast<E>(0);
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Statements after throw must be unreachable");
} catch (T t) {
assert(t == nullptr);
return;
} catch (...) {
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Should not have entered catch-all");
}
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "The catch should have returned");
}
template <typename T
,
typename E
>
void assert_cannot_catch() {
try {
throw static_cast<E>(0);
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Statements after throw must be unreachable");
} catch (T t) {
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Should not have entered the catch");
} catch (...) {
assert(true);
return;
}
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "The catch-all should have returned");
}
template <typename T
,
typename O
>
void assert_catches_bp() {
O* o = new (O);
try {
throw o;
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Statements after throw must be unreachable");
} catch (T t) {
assert(t == static_cast<T>(o));
delete o;
return;
} catch (...) {
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "Should not have entered catch-all");
}
printf("%s\n", __PRETTY_FUNCTION__);
assert(false && "The catch should have returned");
}
void f1() {
assert_catches<Base*, Catchable1*>();
assert_catches<Base*, Catchable2*>();
assert_catches<Base*, Catchable3*>();
}
void f2() {
assert_cannot_catch<Base*, Ambiguous1*>();
assert_cannot_catch<Base*, Ambiguous2*>();
assert_cannot_catch<Base*, Ambiguous3*>();
assert_cannot_catch<Base*, NoPublic1*>();
assert_cannot_catch<Base*, NoPublic2*>();
}
void f3() {
assert_catches_bp<Base*, Catchable1>();
assert_catches_bp<Base*, Catchable2>();
assert_catches_bp<Base*, Catchable3>();
}
int main(int, char**) {
f1();
f2();
f3();
return 0;
}