Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / compiler-rt / test / tsan / exceptions.cpp
blob386145d32719386be5020b383f3ca7aebc3df45b
1 // RUN: %clangxx_tsan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
2 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
4 #include "test.h"
5 #include <setjmp.h>
7 __attribute__((noinline)) void throws_int() {
8 throw 42;
11 __attribute__((noinline)) void callee_throws() {
12 try {
13 throws_int();
14 } catch (int) {
15 fprintf(stderr, "callee_throws caught exception\n");
19 __attribute__((noinline)) void throws_catches_rethrows() {
20 try {
21 throws_int();
22 } catch (int) {
23 fprintf(stderr, "throws_catches_rethrows caught exception\n");
24 throw;
28 __attribute__((noinline)) void callee_rethrows() {
29 try {
30 throws_catches_rethrows();
31 } catch (int) {
32 fprintf(stderr, "callee_rethrows caught exception\n");
36 __attribute__((noinline)) void throws_and_catches() {
37 try {
38 throws_int();
39 } catch (int) {
40 fprintf(stderr, "throws_and_catches caught exception\n");
44 __attribute__((noinline)) void nested_try() {
45 try {
46 try {
47 throws_int();
48 } catch (double) {
49 fprintf(stderr, "nested_try inner block caught exception\n");
51 } catch (int) {
52 fprintf(stderr, "nested_try outer block caught exception\n");
56 __attribute__((noinline)) void nested_try2() {
57 try {
58 try {
59 throws_int();
60 } catch (int) {
61 fprintf(stderr, "nested_try inner block caught exception\n");
63 } catch (double) {
64 fprintf(stderr, "nested_try outer block caught exception\n");
68 class ClassWithDestructor {
69 public:
70 ClassWithDestructor() {
71 fprintf(stderr, "ClassWithDestructor\n");
73 ~ClassWithDestructor() {
74 fprintf(stderr, "~ClassWithDestructor\n");
78 __attribute__((noinline)) void local_object_then_throw() {
79 ClassWithDestructor obj;
80 throws_int();
83 __attribute__((noinline)) void cpp_object_with_destructor() {
84 try {
85 local_object_then_throw();
86 } catch (int) {
87 fprintf(stderr, "cpp_object_with_destructor caught exception\n");
91 __attribute__((noinline)) void recursive_call(long n) {
92 if (n > 0) {
93 recursive_call(n - 1);
94 } else {
95 throws_int();
99 __attribute__((noinline)) void multiframe_unwind() {
100 try {
101 recursive_call(5);
102 } catch (int) {
103 fprintf(stderr, "multiframe_unwind caught exception\n");
107 __attribute__((noinline)) void longjmp_unwind() {
108 jmp_buf env;
109 int i = setjmp(env);
110 if (i != 0) {
111 fprintf(stderr, "longjmp_unwind jumped\n");
112 return;
115 try {
116 longjmp(env, 42);
117 } catch (int) {
118 fprintf(stderr, "longjmp_unwind caught exception\n");
122 __attribute__((noinline)) void recursive_call_longjmp(jmp_buf env, long n) {
123 if (n > 0) {
124 recursive_call_longjmp(env, n - 1);
125 } else {
126 longjmp(env, 42);
130 __attribute__((noinline)) void longjmp_unwind_multiple_frames() {
131 jmp_buf env;
132 int i = setjmp(env);
133 if (i != 0) {
134 fprintf(stderr, "longjmp_unwind_multiple_frames jumped\n");
135 return;
138 try {
139 recursive_call_longjmp(env, 5);
140 } catch (int) {
141 fprintf(stderr, "longjmp_unwind_multiple_frames caught exception\n");
145 #define CHECK_SHADOW_STACK(val) \
146 fprintf(stderr, (val == __tsan_testonly_shadow_stack_current_size() \
147 ? "OK.\n" \
148 : "Shadow stack leak!\n"));
150 int main(int argc, const char * argv[]) {
151 fprintf(stderr, "Hello, World!\n");
152 unsigned long shadow_stack_size = __tsan_testonly_shadow_stack_current_size();
154 throws_and_catches();
155 CHECK_SHADOW_STACK(shadow_stack_size);
157 callee_throws();
158 CHECK_SHADOW_STACK(shadow_stack_size);
160 callee_rethrows();
161 CHECK_SHADOW_STACK(shadow_stack_size);
163 nested_try();
164 CHECK_SHADOW_STACK(shadow_stack_size);
166 nested_try2();
167 CHECK_SHADOW_STACK(shadow_stack_size);
169 cpp_object_with_destructor();
170 CHECK_SHADOW_STACK(shadow_stack_size);
172 multiframe_unwind();
173 CHECK_SHADOW_STACK(shadow_stack_size);
175 longjmp_unwind();
176 CHECK_SHADOW_STACK(shadow_stack_size);
178 longjmp_unwind_multiple_frames();
179 CHECK_SHADOW_STACK(shadow_stack_size);
181 return 0;
184 // CHECK: Hello, World!
185 // CHECK-NOT: Shadow stack leak