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-optzns | \
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 void @use_cxx()
25 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
26 // CXXEH: call %struct.HasCleanup* @"\01??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 @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
32 // CXXEH: ret void
33 //
34 // CXXEH: [[lpad]]
35 // CXXEH: cleanuppad
36 // CXXEH: call void @"\01??1HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
37 // CXXEH: cleanupret
38 
39 // NOCXX-LABEL: define void @use_cxx()
40 // NOCXX-NOT: invoke
41 // NOCXX: call %struct.HasCleanup* @"\01??0HasCleanup@@QEAA@XZ"(%struct.HasCleanup* %{{.*}})
42 // NOCXX-NOT: invoke
43 // NOCXX: call void @might_throw()
44 // NOCXX-NOT: invoke
45 // NOCXX: call void @"\01??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 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 void use_seh_in_lambda() {
80   ([]() {
81     __try {
82       might_throw();
83     } __except(1) {
84     }
85   })();
86   HasCleanup x;
87   might_throw();
88 }
89 
90 // CXXEH-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
91 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
92 // CXXEH: cleanuppad
93 
94 // NOCXX-LABEL: define void @"\01?use_seh_in_lambda@@YAXXZ"()
95 // NOCXX-NOT: invoke
96 // NOCXX: ret void
97 
98 // CHECK-LABEL: define internal void @"\01??R<lambda_0>@?0??use_seh_in_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this)
99 // CXXEH-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
100 // CHECK: invoke void @might_throw() #[[NOINLINE]]
101 // CHECK: catchpad
102 
103 static int my_unique_global;
104 
105 extern "C" inline void use_seh_in_inline_func() {
106   __try {
107     might_throw();
108   } __except(_exception_code() == 424242) {
109   }
110   __try {
111     might_throw();
112   } __finally {
113     my_unique_global = 1234;
114   }
115 }
116 
117 void use_inline() {
118   use_seh_in_inline_func();
119 }
120 
121 // CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat
122 // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
123 // CHECK: invoke void @might_throw()
124 //
125 // CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
126 //
127 // CHECK: invoke void @might_throw()
128 //
129 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
130 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 0, i8* %[[fp]])
131 // CHECK: ret void
132 //
133 // CHECK: cleanuppad
134 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
135 // CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
136 
137 // 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 // CHECK: icmp eq i32 %{{.*}}, 424242
139 // CHECK: zext i1 %{{.*}} to i32
140 // CHECK: ret i32
141 
142 // 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 // CHECK: store i32 1234, i32* @my_unique_global
144 
145 // CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
146