mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-10-28 21:25:06 +00:00
129 lines
2.3 KiB
C++
129 lines
2.3 KiB
C++
// C++ exceptions as the Microsoft compiler emits them, against the system msvcrt.dll: a catch by reference, a catch by value through the
|
|
// copy constructor, a rethrow caught in the same function and in the caller, catch(...), a new exception thrown from a catch block, and
|
|
// the destructors of the locals the exceptions leave. Built for both widths; the entry returns the number of the first check that failed.
|
|
|
|
// The table every type descriptor points to, which a program links statically as the Microsoft libraries do.
|
|
extern "C" const void *const type_info_table[1] __asm__("??_7type_info@@6B@") = {nullptr};
|
|
|
|
static int guards, destroyed;
|
|
|
|
struct Failure {
|
|
int value;
|
|
explicit Failure(int value) : value(value) {}
|
|
Failure(const Failure &other) : value(other.value + 100) {}
|
|
~Failure() { ++destroyed; }
|
|
};
|
|
|
|
struct Guard {
|
|
~Guard() { ++guards; }
|
|
};
|
|
|
|
__declspec(noinline) void thrower(int value)
|
|
{
|
|
Guard guard;
|
|
if (value)
|
|
throw Failure(value);
|
|
}
|
|
|
|
__declspec(noinline) int by_reference()
|
|
{
|
|
try {
|
|
thrower(7);
|
|
} catch (Failure &failure) {
|
|
return failure.value;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
__declspec(noinline) int by_value()
|
|
{
|
|
try {
|
|
thrower(3);
|
|
} catch (int) {
|
|
return -1;
|
|
} catch (Failure failure) {
|
|
return failure.value;
|
|
}
|
|
return -2;
|
|
}
|
|
|
|
__declspec(noinline) int rethrown()
|
|
{
|
|
try {
|
|
try {
|
|
thrower(1);
|
|
} catch (Failure &) {
|
|
throw;
|
|
}
|
|
} catch (Failure &failure) {
|
|
return failure.value;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
__declspec(noinline) int anything()
|
|
{
|
|
try {
|
|
throw 42;
|
|
} catch (...) {
|
|
return 5;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
__declspec(noinline) void passes_on()
|
|
{
|
|
Guard guard;
|
|
try {
|
|
thrower(9);
|
|
} catch (Failure &) {
|
|
throw;
|
|
}
|
|
}
|
|
|
|
__declspec(noinline) int caller_catches()
|
|
{
|
|
try {
|
|
passes_on();
|
|
} catch (Failure &failure) {
|
|
return failure.value;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
__declspec(noinline) int replaced()
|
|
{
|
|
try {
|
|
try {
|
|
thrower(2);
|
|
} catch (Failure &) {
|
|
throw 17;
|
|
}
|
|
} catch (int value) {
|
|
return value;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
extern "C" int raven_entry()
|
|
{
|
|
if (by_reference() != 7)
|
|
return 1;
|
|
if (by_value() != 103)
|
|
return 2;
|
|
if (rethrown() != 1)
|
|
return 3;
|
|
if (anything() != 5)
|
|
return 4;
|
|
if (caller_catches() != 9)
|
|
return 5;
|
|
if (replaced() != 17)
|
|
return 6;
|
|
// One guard in each call that threw, and the one of passes_on, which the rethrow left.
|
|
if (guards != 6)
|
|
return 7;
|
|
if (destroyed < 3)
|
|
return 8;
|
|
return 0;
|
|
}
|