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 | |
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 i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) |
26 | // CXXEH: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) |
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"(%struct.HasCleanup* %{{.*}}) |
32 | // CXXEH: ret void |
33 | // |
34 | // CXXEH: [[lpad]] |
35 | // CXXEH: cleanuppad |
36 | // CXXEH: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) |
37 | // CXXEH: cleanupret |
38 | |
39 | // NOCXX-LABEL: define dso_local void @use_cxx() |
40 | // NOCXX-NOT: invoke |
41 | // NOCXX: call %struct.HasCleanup* @"??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) |
42 | // NOCXX-NOT: invoke |
43 | // NOCXX: call void @might_throw() |
44 | // NOCXX-NOT: invoke |
45 | // NOCXX: call void @"??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}}) |
46 | // NOCXX-NOT: invoke |
47 | // NOCXX: ret void |
48 | |
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 i8* bitcast (i32 (...)* @__C_specific_handler to i8*) |
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 | |
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 i8* bitcast (i32 (...)* @__C_specific_handler to i8*) |
92 | // CHECK: invoke void @might_throw() |
93 | // CHECK: call void @"?fin$0@0@nested_finally@@"(i8 1, i8* {{.*}}) |
94 | |
95 | // CHECK-LABEL: define internal void @"?fin$0@0@nested_finally@@" |
96 | // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) |
97 | // CHECK: invoke void @might_throw() |
98 | // CHECK: call void @"?fin$1@0@nested_finally@@"(i8 1, i8* {{.*}}) |
99 | |
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 i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) |
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"(%class.anon* %this) |
120 | // CXXEH-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) |
121 | // CHECK: invoke void @might_throw() #[[NOINLINE]] |
122 | // CHECK: catchpad |
123 | |
124 | static int my_unique_global; |
125 | |
126 | extern "C" inline void use_seh_in_inline_func() { |
127 | __try { |
128 | might_throw(); |
129 | } __except(_exception_code() == 424242) { |
130 | } |
131 | __try { |
132 | might_throw(); |
133 | } __finally { |
134 | my_unique_global = 1234; |
135 | } |
136 | } |
137 | |
138 | void use_inline() { |
139 | use_seh_in_inline_func(); |
140 | } |
141 | |
142 | // CHECK-LABEL: define linkonce_odr dso_local void @use_seh_in_inline_func() #{{[0-9]+}} |
143 | // CHECK-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) |
144 | // CHECK: invoke void @might_throw() |
145 | // |
146 | // CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"?filt$0@0@use_seh_in_inline_func@@" to i8*)] |
147 | // |
148 | // CHECK: invoke void @might_throw() |
149 | // |
150 | // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() |
151 | // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]]) |
152 | // CHECK: ret void |
153 | // |
154 | // CHECK: cleanuppad |
155 | // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress() |
156 | // CHECK: call void @"?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]]) |
157 | |
158 | // CHECK-LABEL: define internal i32 @"?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} |
159 | // CHECK: icmp eq i32 %{{.*}}, 424242 |
160 | // CHECK: zext i1 %{{.*}} to i32 |
161 | // CHECK: ret i32 |
162 | |
163 | // CHECK-LABEL: define internal void @"?fin$0@0@use_seh_in_inline_func@@"(i8 %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} |
164 | // CHECK: store i32 1234, i32* @my_unique_global |
165 | |
166 | // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } |
167 | |