blob: d7268bf38529eff76609c34c089d9952e646d499 [file] [log] [blame]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +00001// 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
3extern "C" void might_throw();
4
5// Simplify the generated IR with noexcept.
6extern "C" void recover() noexcept(true);
7extern "C" void handle_exception(void *e) noexcept(true);
8
9extern "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
35extern "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
Reid Kleckner67cf0352015-04-07 00:09:59 +000051extern "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
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000063struct A {
64 A();
65 A(const A &o);
66 ~A();
67 int a;
68};
69
70struct B : A {
71 B();
72 B(const B &o);
73 ~B();
74 int b;
75};
76
77extern "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
94extern "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()
David Majnemer1f192e22015-04-01 04:45:52 +0000111
112extern "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
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000119
120extern "C" void catch_nested() {
121 try {
122 might_throw();
123 } catch (int) {
124 try {
125 might_throw();
126 } catch (int) {
127 might_throw();
128 }
129 }
130}
131
132// WIN64-LABEL: define void @catch_nested()
133// WIN64: invoke void @might_throw()
134// WIN64-NEXT: to label %[[cont1:[^ ]*]] unwind label %[[lp1:[^ ]*]]
135// WIN64: [[cont1]]
136//
137// WIN64: [[lp1]]
138// WIN64: landingpad { i8*, i32 }
139// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null)
140// WIN64: invoke void @might_throw()
141// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]]
142//
143// WIN64: [[cont2]]
144// WIN64-NEXT: br label %[[trycont:[^ ]*]]
145//
146// WIN64: [[lp2]]
147// WIN64: landingpad { i8*, i32 }
148// WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* null)
149// WIN64-NEXT: call void @might_throw()
150// WIN64-NEXT: call void @llvm.eh.endcatch()
151// WIN64-NEXT: br label %[[trycont]]
152//
153// WIN64: [[trycont]]
154// WIN64: call void @llvm.eh.endcatch()