1 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc -mconstructor-aliases -fexceptions -fcxx-exceptions | FileCheck -check-prefix WIN64 %s
2
3 extern "C" void might_throw();
4
5 // Simplify the generated IR with noexcept.
6 extern "C" void recover() noexcept(true);
7 extern "C" void handle_exception(void *e) noexcept(true);
8
catch_all()9 extern "C" void catch_all() {
10 try {
11 might_throw();
12 } catch (...) {
13 recover();
14 }
15 }
16
17 // WIN64-LABEL: define void @catch_all()
18 // WIN64: invoke void @might_throw()
19 // WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
20 //
21 // WIN64: [[cont]]
22 // WIN64: br label %[[ret:[^ ]*]]
23 //
24 // WIN64: [[lpad]]
25 // WIN64: landingpad { i8*, i32 }
26 // WIN64-NEXT: catch i8* null
27 // WIN64: call void @llvm.eh.begincatch(i8* %{{[^,]*}}, i8* null)
28 // WIN64: call void @recover()
29 // WIN64: call void @llvm.eh.endcatch()
30 // WIN64: br label %[[ret]]
31 //
32 // WIN64: [[ret]]
33 // WIN64: ret void
34
catch_int()35 extern "C" void catch_int() {
36 try {
37 might_throw();
38 } catch (int e) {
39 handle_exception(&e);
40 }
41 }
42
43 // WIN64-LABEL: define void @catch_int()
44 // WIN64: landingpad { i8*, i32 }
45 // WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr:[^ ]*]] to i8*
46 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
47 // WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8*
48 // WIN64: call void @handle_exception(i8* %[[e_i8]])
49 // WIN64: call void @llvm.eh.endcatch()
50
catch_int_unnamed()51 extern "C" void catch_int_unnamed() {
52 try {
53 might_throw();
54 } catch (int) {
55 }
56 }
57
58 // WIN64-LABEL: define void @catch_int_unnamed()
59 // WIN64: landingpad { i8*, i32 }
60 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null)
61 // WIN64: call void @llvm.eh.endcatch()
62
63 struct A {
64 A();
65 A(const A &o);
66 ~A();
67 int a;
68 };
69
70 struct B : A {
71 B();
72 B(const B &o);
73 ~B();
74 int b;
75 };
76
catch_a_byval()77 extern "C" void catch_a_byval() {
78 try {
79 might_throw();
80 } catch (A e) {
81 handle_exception(&e);
82 }
83 }
84
85 // WIN64-LABEL: define void @catch_a_byval()
86 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
87 // WIN64: landingpad { i8*, i32 }
88 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
89 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
90 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
91 // WIN64: call void @handle_exception(i8* %[[e_i8]])
92 // WIN64: call void @llvm.eh.endcatch()
93
catch_a_ref()94 extern "C" void catch_a_ref() {
95 try {
96 might_throw();
97 } catch (A &e) {
98 handle_exception(&e);
99 }
100 }
101
102 // WIN64-LABEL: define void @catch_a_ref()
103 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
104 // WIN64: landingpad { i8*, i32 }
105 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A** %[[e_addr]] to i8*
106 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
107 // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
108 // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
109 // WIN64: call void @handle_exception(i8* %[[eptr_i8]])
110 // WIN64: call void @llvm.eh.endcatch()
111
fn_with_exc_spec()112 extern "C" void fn_with_exc_spec() throw(int) {
113 might_throw();
114 }
115
116 // WIN64-LABEL: define void @fn_with_exc_spec()
117 // WIN64: call void @might_throw()
118 // WIN64-NEXT: ret void
119