| #include <assert.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| |
| 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; |
| } |
| } |
| } |