#include #include #include void println(const char* s) { puts(s); fflush(stdout); } struct exception {}; struct rust_panic {}; struct drop_check { bool* ok; ~drop_check() { println("~drop_check"); if (ok) *ok = true; } }; extern "C" { void rust_catch_callback(void (*cb)(), bool* rust_ok); void throw_cxx_exception() { println("throwing C++ exception"); throw exception(); } void test_cxx_exception() { bool rust_ok = false; try { rust_catch_callback(throw_cxx_exception, &rust_ok); assert(false && "unreachable"); } catch (exception e) { println("caught C++ exception"); assert(rust_ok); return; } assert(false && "did not catch thrown C++ exception"); } void cxx_catch_callback(void (*cb)(), bool* cxx_ok) { drop_check x; x.ok = NULL; try { cb(); } catch (rust_panic e) { assert(false && "shouldn't be able to catch a rust panic"); } catch (...) { println("caught foreign exception in catch (...)"); // Foreign exceptions are caught by catch (...). We only set the ok // flag if we successfully caught the panic. The destructor of // drop_check will then set the flag to true if it is executed. x.ok = cxx_ok; throw; } } }