xref: /llvm-project/clang/test/CodeGenCXX/exceptions-seh.cpp (revision 0fcb26c5b6487bf9b31670122f8c931ac020bb34)
1 // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
2 // RUN:         -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
3 // RUN:         FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
4 // RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
5 // RUN:         -o - -mconstructor-aliases -O1 -disable-llvm-passes | \
6 // RUN:         FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
7 
8 extern "C" unsigned long _exception_code();
9 extern "C" void might_throw();
10 
11 struct HasCleanup {
12   HasCleanup();
13   ~HasCleanup();
14   int padding;
15 };
16 
use_cxx()17 extern "C" void use_cxx() {
18   HasCleanup x;
19   might_throw();
20 }
21 
22 // Make sure we use __CxxFrameHandler3 for C++ EH.
23 
24 // CXXEH-LABEL: define dso_local void @use_cxx()
25 // CXXEH-SAME:  personality ptr @__CxxFrameHandler3
26 // CXXEH: call noundef ptr @"??0HasCleanup@@QEAA@XZ"(ptr {{[^,]*}} %{{.*}})
27 // CXXEH: invoke void @might_throw()
28 // CXXEH:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
29 //
30 // CXXEH: [[cont]]
31 // CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(ptr {{[^,]*}} %{{.*}})
32 // CXXEH: ret void
33 //
34 // CXXEH: [[lpad]]
35 // CXXEH: cleanuppad
36 // CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(ptr {{[^,]*}} %{{.*}})
37 // CXXEH: cleanupret
38 
39 // NOCXX-LABEL: define dso_local void @use_cxx()
40 // NOCXX-NOT: invoke
41 // NOCXX: call noundef ptr @"??0HasCleanup@@QEAA@XZ"(ptr {{[^,]*}} %{{.*}})
42 // NOCXX-NOT: invoke
43 // NOCXX: call void @might_throw()
44 // NOCXX-NOT: invoke
45 // NOCXX: call void @"??1HasCleanup@@QEAA@XZ"(ptr {{[^,]*}} %{{.*}})
46 // NOCXX-NOT: invoke
47 // NOCXX: ret void
48 
use_seh()49 extern "C" void use_seh() {
50   __try {
51     might_throw();
52   } __except(1) {
53   }
54 }
55 
56 // Make sure we use __C_specific_handler for SEH.
57 
58 // CHECK-LABEL: define dso_local void @use_seh()
59 // CHECK-SAME:  personality ptr @__C_specific_handler
60 // CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]]
61 // CHECK:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
62 //
63 // CHECK: [[lpad]]
64 // CHECK-NEXT: %[[switch:.*]] = catchswitch within none [label %[[cpad:.*]]] unwind to caller
65 //
66 // CHECK: [[cpad]]
67 // CHECK-NEXT: catchpad within %[[switch]]
68 // CHECK: catchret {{.*}} label %[[except:[^ ]*]]
69 //
70 // CHECK: [[except]]
71 // CHECK: br label %[[ret:[^ ]*]]
72 //
73 // CHECK: [[ret]]
74 // CHECK: ret void
75 //
76 // CHECK: [[cont]]
77 // CHECK: br label %[[ret]]
78 
nested_finally()79 extern "C" void nested_finally() {
80   __try {
81     might_throw();
82   } __finally {
83     __try {
84       might_throw();
85     } __finally {
86     }
87   }
88 }
89 
90 // CHECK-LABEL: define dso_local void @nested_finally() #{{[0-9]+}}
91 // CHECK-SAME:  personality ptr @__C_specific_handler
92 // CHECK: invoke void @might_throw()
93 // CHECK: call void @"?fin$0@0@nested_finally@@"(i8 noundef 1, ptr {{.*}})
94 
95 // CHECK-LABEL: define internal void @"?fin$0@0@nested_finally@@"
96 // CHECK-SAME:  personality ptr @__C_specific_handler
97 // CHECK: invoke void @might_throw()
98 // CHECK: call void @"?fin$1@0@nested_finally@@"(i8 noundef 1, ptr {{.*}})
99 
use_seh_in_lambda()100 void use_seh_in_lambda() {
101   ([]() {
102     __try {
103       might_throw();
104     } __except(1) {
105     }
106   })();
107   HasCleanup x;
108   might_throw();
109 }
110 
111 // CXXEH-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
112 // CXXEH-SAME:  personality ptr @__CxxFrameHandler3
113 // CXXEH: cleanuppad
114 
115 // NOCXX-LABEL: define dso_local void @"?use_seh_in_lambda@@YAXXZ"()
116 // NOCXX-NOT: invoke
117 // NOCXX: ret void
118 
119 // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(ptr {{[^,]*}} %this)
120 // CXXEH-SAME:  personality ptr @__C_specific_handler
121 // CHECK: invoke void @might_throw() #[[NOINLINE]]
122 // CHECK: catchpad
123 
124 class use_seh_in_constructor { use_seh_in_constructor(); };
use_seh_in_constructor()125 use_seh_in_constructor::use_seh_in_constructor(){
126   __try {
127   } __finally {
128   }
129 }
130 
131 // CHECK: define internal void @"?fin$0@0@?0use_seh_in_constructor@@"
132 
133 static int my_unique_global;
134 
use_seh_in_inline_func()135 extern "C" inline void use_seh_in_inline_func() {
136   __try {
137     might_throw();
138   } __except(_exception_code() == 424242) {
139   }
140   __try {
141     might_throw();
142   } __finally {
143     my_unique_global = 1234;
144   }
145 }
146 
use_inline()147 void use_inline() {
148   use_seh_in_inline_func();
149 }
150 
151 // CHECK-LABEL: define linkonce_odr dso_local void @use_seh_in_inline_func() #{{[0-9]+}}
152 // CHECK-SAME:  personality ptr @__C_specific_handler
153 // CHECK: invoke void @might_throw()
154 //
155 // CHECK: catchpad {{.*}} [ptr @"?filt$0@0@use_seh_in_inline_func@@"]
156 //
157 // CHECK: invoke void @might_throw()
158 //
159 // CHECK: %[[fp:[^ ]*]] = call ptr @llvm.localaddress()
160 // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef 0, ptr noundef %[[fp]])
161 // CHECK: ret void
162 //
163 // CHECK: cleanuppad
164 // CHECK: %[[fp:[^ ]*]] = call ptr @llvm.localaddress()
165 // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef 1, ptr noundef %[[fp]])
166 
167 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@use_seh_in_inline_func@@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer) #{{[0-9]+}}
168 // CHECK: icmp eq i32 %{{.*}}, 424242
169 // CHECK: zext i1 %{{.*}} to i32
170 // CHECK: ret i32
171 
172 // CHECK-LABEL: define internal void @"?fin$0@0@use_seh_in_inline_func@@"(i8 noundef %abnormal_termination, ptr noundef %frame_pointer) #{{[0-9]+}}
173 // CHECK: store i32 1234, ptr @my_unique_global
174 
175 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
176 
seh_in_noexcept()177 void seh_in_noexcept() noexcept { __try {} __finally {} }
178