blob: cb5f6dfad90bfb27b677d38e866f3d7906402cd7 [file] [log] [blame]
Stephen Hines0e2c34f2015-03-23 12:09:02 -07001// 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-optzns | \
6// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
7
Pirama Arumuga Nainar33337ca2015-05-06 11:48:57 -07008extern "C" unsigned long _exception_code();
Stephen Hines0e2c34f2015-03-23 12:09:02 -07009extern "C" void might_throw();
10
11struct HasCleanup {
12 HasCleanup();
13 ~HasCleanup();
14 int padding;
15};
16
17extern "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 void @use_cxx()
25// CXXEH: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
26// CXXEH: invoke void @might_throw()
27// CXXEH: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
28//
29// CXXEH: [[cont]]
30// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
31// CXXEH: ret void
32//
33// CXXEH: [[lpad]]
34// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
35// CXXEH-NEXT: cleanup
36// CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
37// CXXEH: br label %[[resume:[^ ]*]]
38//
39// CXXEH: [[resume]]
40// CXXEH: resume
41
42// NOCXX-LABEL: define void @use_cxx()
43// NOCXX-NOT: invoke
44// NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
45// NOCXX-NOT: invoke
46// NOCXX: call void @might_throw()
47// NOCXX-NOT: invoke
48// NOCXX: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
49// NOCXX-NOT: invoke
50// NOCXX: ret void
51
52extern "C" void use_seh() {
53 __try {
54 might_throw();
55 } __except(1) {
56 }
57}
58
59// Make sure we use __C_specific_handler for SEH.
60
61// CHECK-LABEL: define void @use_seh()
62// CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]]
63// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
64//
65// CHECK: [[cont]]
66// CHECK: br label %[[ret:[^ ]*]]
67//
68// CHECK: [[lpad]]
69// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
70// CHECK-NEXT: catch i8*
71//
72// CHECK: br label %[[ret]]
73//
74// CHECK: [[ret]]
75// CHECK: ret void
76
77void use_seh_in_lambda() {
78 ([]() {
79 __try {
80 might_throw();
81 } __except(1) {
82 }
83 })();
84 HasCleanup x;
85 might_throw();
86}
87
88// CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
89// CXXEH: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
90
91// NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
92// NOCXX-NOT: invoke
93// NOCXX: ret void
94
95// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this)
96// CHECK: invoke void @might_throw() #[[NOINLINE]]
97// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
98
Pirama Arumuga Nainar33337ca2015-05-06 11:48:57 -070099static int my_unique_global;
100
101extern "C" inline void use_seh_in_inline_func() {
102 __try {
103 might_throw();
104 } __except(_exception_code() == 424242) {
105 }
106 __try {
107 might_throw();
108 } __finally {
109 my_unique_global = 1234;
110 }
111}
112
113void use_inline() {
114 use_seh_in_inline_func();
115}
116
117// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat {
118// CHECK: invoke void @might_throw()
119//
120// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
121// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)
122//
123// CHECK: invoke void @might_throw()
124//
125// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
126// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext false, i8* %[[fp]])
127// CHECK: ret void
128//
129// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
130// CHECK-NEXT: cleanup
131// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
132// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext true, i8* %[[fp]])
133
134// 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)
135// CHECK: icmp eq i32 %{{.*}}, 424242
136// CHECK: zext i1 %{{.*}} to i32
137// CHECK: ret i32
138
139// CHECK-LABEL: define internal void @"\01?fin$0@0@use_seh_in_inline_func@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
140// CHECK: store i32 1234, i32* @my_unique_global
141
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700142// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }