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 
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 
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 
51 struct A {
52   A();
53   A(const A &o);
54   ~A();
55   int a;
56 };
57 
58 struct B : A {
59   B();
60   B(const B &o);
61   ~B();
62   int b;
63 };
64 
65 extern "C" void catch_a_byval() {
66   try {
67     might_throw();
68   } catch (A e) {
69     handle_exception(&e);
70   }
71 }
72 
73 // WIN64-LABEL: define void @catch_a_byval()
74 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
75 // WIN64: landingpad { i8*, i32 }
76 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
77 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
78 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
79 // WIN64: call void @handle_exception(i8* %[[e_i8]])
80 // WIN64: call void @llvm.eh.endcatch()
81 
82 extern "C" void catch_a_ref() {
83   try {
84     might_throw();
85   } catch (A &e) {
86     handle_exception(&e);
87   }
88 }
89 
90 // WIN64-LABEL: define void @catch_a_ref()
91 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
92 // WIN64: landingpad { i8*, i32 }
93 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A** %[[e_addr]] to i8*
94 // WIN64: call void @llvm.eh.begincatch(i8* %{{.*}}, i8* %[[e_i8]])
95 // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
96 // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
97 // WIN64: call void @handle_exception(i8* %[[eptr_i8]])
98 // WIN64: call void @llvm.eh.endcatch()
99