blob: d14edf8986bcd3c19e8bb88dc408e49db1471577 [file] [log] [blame]
Reid Kleckner10aa7702015-09-16 20:15:55 +00001// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \
2// RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions -fnew-ms-eh \
3// RUN: | FileCheck -check-prefix WIN64 %s
Reid Klecknerfff8e7f2015-03-03 19:21:04 +00004
5extern "C" void might_throw();
6
7// Simplify the generated IR with noexcept.
8extern "C" void recover() noexcept(true);
9extern "C" void handle_exception(void *e) noexcept(true);
10
11extern "C" void catch_all() {
12 try {
13 might_throw();
14 } catch (...) {
15 recover();
16 }
17}
18
19// WIN64-LABEL: define void @catch_all()
20// WIN64: invoke void @might_throw()
21// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
22//
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000023// WIN64: [[lpad]]
Reid Kleckner10aa7702015-09-16 20:15:55 +000024// WIN64: catchpad [i8* null, i32 64, i8* null]
25// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}}
26//
27// WIN64: [[catchit]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000028// WIN64: call void @recover()
Reid Kleckner10aa7702015-09-16 20:15:55 +000029// WIN64: catchret %{{.*}} to label %[[catchret:[^ ]*]]
30//
31// WIN64: [[catchret]]
32// WIN64-NEXT: br label %[[ret:[^ ]*]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000033//
34// WIN64: [[ret]]
35// WIN64: ret void
Reid Kleckner10aa7702015-09-16 20:15:55 +000036//
37// WIN64: [[cont]]
38// WIN64: br label %[[ret]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000039
40extern "C" void catch_int() {
41 try {
42 might_throw();
43 } catch (int e) {
44 handle_exception(&e);
45 }
46}
47
48// WIN64-LABEL: define void @catch_int()
Reid Kleckner10aa7702015-09-16 20:15:55 +000049// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000050// WIN64: %[[e_i8:[^ ]*]] = bitcast i32* %[[e_addr]] to i8*
51// WIN64: call void @handle_exception(i8* %[[e_i8]])
Reid Kleckner10aa7702015-09-16 20:15:55 +000052// WIN64: catchret
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000053
Reid Kleckner67cf0352015-04-07 00:09:59 +000054extern "C" void catch_int_unnamed() {
55 try {
56 might_throw();
57 } catch (int) {
58 }
59}
60
61// WIN64-LABEL: define void @catch_int_unnamed()
Reid Kleckner10aa7702015-09-16 20:15:55 +000062// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
63// WIN64: catchret
Reid Kleckner67cf0352015-04-07 00:09:59 +000064
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000065struct A {
66 A();
67 A(const A &o);
68 ~A();
69 int a;
70};
71
72struct B : A {
73 B();
74 B(const B &o);
75 ~B();
76 int b;
77};
78
79extern "C" void catch_a_byval() {
80 try {
81 might_throw();
82 } catch (A e) {
83 handle_exception(&e);
84 }
85}
86
87// WIN64-LABEL: define void @catch_a_byval()
88// WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
Reid Kleckner10aa7702015-09-16 20:15:55 +000089// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000090// WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
91// WIN64: call void @handle_exception(i8* %[[e_i8]])
Reid Kleckner10aa7702015-09-16 20:15:55 +000092// WIN64: catchret
Reid Klecknerfff8e7f2015-03-03 19:21:04 +000093
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*
Reid Kleckner10aa7702015-09-16 20:15:55 +0000104// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
Reid Klecknerfff8e7f2015-03-03 19:21:04 +0000105// WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
106// WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
107// WIN64: call void @handle_exception(i8* %[[eptr_i8]])
Reid Kleckner10aa7702015-09-16 20:15:55 +0000108// WIN64: catchret
David Majnemer1f192e22015-04-01 04:45:52 +0000109
110extern "C" void fn_with_exc_spec() throw(int) {
111 might_throw();
112}
113
114// WIN64-LABEL: define void @fn_with_exc_spec()
115// WIN64: call void @might_throw()
116// WIN64-NEXT: ret void
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000117
118extern "C" void catch_nested() {
119 try {
120 might_throw();
121 } catch (int) {
122 try {
123 might_throw();
124 } catch (int) {
125 might_throw();
126 }
127 }
128}
129
130// WIN64-LABEL: define void @catch_nested()
131// WIN64: invoke void @might_throw()
Reid Kleckner10aa7702015-09-16 20:15:55 +0000132// WIN64-NEXT: to label %{{.*}} unwind label %[[lp1:[^ ]*]]
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000133//
134// WIN64: [[lp1]]
Reid Kleckner10aa7702015-09-16 20:15:55 +0000135// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
136// WIN64: to label %[[catchit:[^ ]*]] unwind label %{{.*}}
137//
138// WIN64: [[catchit]]
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000139// WIN64: invoke void @might_throw()
140// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]]
141//
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000142// WIN64: [[lp2]]
Reid Kleckner10aa7702015-09-16 20:15:55 +0000143// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
144// WIN64: to label %[[catchit2:[^ ]*]] unwind label %[[endcatch2:[^ ]*]]
Reid Kleckner7d4bc9c2015-04-22 23:39:15 +0000145//
Reid Kleckner10aa7702015-09-16 20:15:55 +0000146// WIN64: [[catchit2]]
147// WIN64-NEXT: invoke void @might_throw()
148// WIN64-NEXT: to label %[[catchret1:[^ ]*]] unwind label %[[endcatch2]]
149//
150// WIN64: [[catchret1]]
151// WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
152//
153// WIN64: [[catchret2]]
154// WIN64: catchret {{.*}} to label %[[mainret:[^ ]*]]
155//
156// WIN64: [[mainret]]
157// WIN64: ret void
158//
159// WIN64: [[endcatch2]]
160// WIN64: catchendpad unwind label %{{.*}}