1 #include <assert.h> 2 #include <stddef.h> 3 #include <stdio.h> 4 println(const char * s)5void println(const char* s) { 6 puts(s); 7 fflush(stdout); 8 } 9 10 struct exception {}; 11 struct rust_panic {}; 12 13 struct drop_check { 14 bool* ok; ~drop_checkdrop_check15 ~drop_check() { 16 println("~drop_check"); 17 18 if (ok) 19 *ok = true; 20 } 21 }; 22 23 extern "C" { 24 void rust_catch_callback(void (*cb)(), bool* rust_ok); 25 throw_cxx_exception()26 void throw_cxx_exception() { 27 println("throwing C++ exception"); 28 throw exception(); 29 } 30 test_cxx_exception()31 void test_cxx_exception() { 32 bool rust_ok = false; 33 try { 34 rust_catch_callback(throw_cxx_exception, &rust_ok); 35 assert(false && "unreachable"); 36 } catch (exception e) { 37 println("caught C++ exception"); 38 assert(rust_ok); 39 return; 40 } 41 assert(false && "did not catch thrown C++ exception"); 42 } 43 cxx_catch_callback(void (* cb)(),bool * cxx_ok)44 void cxx_catch_callback(void (*cb)(), bool* cxx_ok) { 45 drop_check x; 46 x.ok = NULL; 47 try { 48 cb(); 49 } catch (rust_panic e) { 50 assert(false && "shouldn't be able to catch a rust panic"); 51 } catch (...) { 52 println("caught foreign exception in catch (...)"); 53 // Foreign exceptions are caught by catch (...). We only set the ok 54 // flag if we successfully caught the panic. The destructor of 55 // drop_check will then set the flag to true if it is executed. 56 x.ok = cxx_ok; 57 throw; 58 } 59 } 60 } 61