1 // UNSUPPORTED: libunwind-no-exceptions
2 // Tell lit to add -lc++abi/-lcxxrt/-lsupc++, etc. to the linker flags:
3 // ADDITIONAL_LINK_FLAGS: %{link_libcxxabi}
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 
8 static int dtors_called = 0;
9 
10 struct WithCleanup {
WithCleanupWithCleanup11   WithCleanup(const char *func) : func(func) {
12     fprintf(stderr, "Created object with destructor in %s!\n", func);
13   }
WithCleanupWithCleanup14   WithCleanup(const WithCleanup &other) : func(other.func) {
15     fprintf(stderr, "struct WithCleanup(%s) copied!\n", func);
16   }
~WithCleanupWithCleanup17   ~WithCleanup() {
18     fprintf(stderr, "Calling destructor in %s!\n", func);
19     dtors_called++;
20   }
21 
22 private:
23   const char *func;
24 };
25 
26 struct SomeException {
SomeExceptionSomeException27   SomeException(const char *message) : message(message) {}
28   const char *message;
29 };
30 
raise_exception(bool raise)31 __attribute__((noinline)) int raise_exception(bool raise) {
32   if (raise) {
33     fprintf(stderr, "About to throw an exception...\n");
34     throw SomeException("Exception occurred.");
35   } else {
36     fprintf(stderr, "Not throwing yet...\n");
37   }
38   return 0;
39 };
40 
test_function()41 __attribute__((noinline)) void test_function() {
42   fprintf(stderr, "%s: enter\n", __func__);
43   raise_exception(false);
44   WithCleanup object(__func__);
45   raise_exception(true);
46   fprintf(stderr, "ERROR: returned from raise_exception!\n");
47   abort();
48 }
49 
main()50 int main() {
51   try {
52     WithCleanup object(__func__);
53     fprintf(stderr, "About to call test_function!\n");
54     test_function();
55     fprintf(stderr, "ERROR: returned from test_function!\n");
56     abort();
57   } catch (const SomeException &s) {
58     fprintf(stderr, "%s: caught exception with message: %s\n", __func__,
59             s.message);
60   }
61   if (dtors_called != 2) {
62     fprintf(stderr, "Expected 2 destructors to be called but got %d\n",
63             dtors_called);
64     abort();
65   }
66   fprintf(stderr, "Success!\n");
67   return (0);
68 }
69