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