]> git.lizzy.rs Git - rust.git/blob - src/test/run-make-fulldeps/foreign-exceptions/foo.cpp
Add a test to check that swallowed Rust panics are dropped properly.
[rust.git] / src / test / run-make-fulldeps / foreign-exceptions / foo.cpp
1 #include <assert.h>
2 #include <stddef.h>
3 #include <stdio.h>
4
5 void 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;
15     ~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
26     static void callback() {
27         println("throwing C++ exception");
28         throw exception();
29     }
30
31     void throw_cxx_exception() {
32         bool rust_ok = false;
33         try {
34             rust_catch_callback(callback, &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
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     void swallow_exception(void (*cb)()) {
62         try {
63             // Do a rethrow to ensure that the exception is only dropped once.
64             // This is necessary since we don't support copying exceptions.
65             try {
66                 cb();
67             } catch (...) {
68                 println("rethrowing Rust panic");
69                 throw;
70             };
71         } catch (rust_panic e) {
72             assert(false && "shouldn't be able to catch a rust panic");
73         } catch (...) {
74             println("swallowing foreign exception in catch (...)");
75         }
76     }
77 }