1 // RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
2 // RUN:         -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | FileCheck %s
3 
4 extern "C" int basic_filter(int v, ...);
5 extern "C" void might_crash();
6 
test_freefunc(int p1)7 extern "C" void test_freefunc(int p1) {
8   int l1 = 13;
9   static int s1 = 42;
10   __try {
11     might_crash();
12   } __except(basic_filter(p1, l1, s1)) {
13   }
14 }
15 
16 // CHECK-LABEL: define dso_local void @test_freefunc(i32 noundef %p1)
17 // CHECK: @llvm.localescape(i32* %[[p1_ptr:[^, ]*]], i32* %[[l1_ptr:[^, ]*]])
18 // CHECK: store i32 %p1, i32* %[[p1_ptr]], align 4
19 // CHECK: store i32 13, i32* %[[l1_ptr]], align 4
20 // CHECK: invoke void @might_crash()
21 
22 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_freefunc@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
23 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer)
24 // CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
25 // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
26 // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
27 // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
28 // CHECK: %[[s1:[^ ]*]] = load i32, i32* @"?s1@?1??test_freefunc@@9@4HA", align 4
29 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
30 // CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
31 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[p1]], i32 noundef %[[l1]], i32 noundef %[[s1]])
32 
33 struct S {
34   int m1;
35   void test_method(void);
36 };
37 
test_method()38 void S::test_method() {
39   int l1 = 13;
40   __try {
41     might_crash();
42   } __except (basic_filter(l1, m1)) {
43   }
44 }
45 
46 // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* {{[^,]*}} %this)
47 // CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]], %struct.S** %[[this_addr:[^, ]*]])
48 // CHECK: store %struct.S* %this, %struct.S** %[[this_addr]], align 8
49 // CHECK: store i32 13, i32* %[[l1_addr]], align 4
50 // CHECK: invoke void @might_crash()
51 
52 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_method@S@@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
53 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
54 // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
55 // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
56 // CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 1)
57 // CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.S**
58 // CHECK: %[[this:[^ ]*]] = load %struct.S*, %struct.S** %[[this_ptr]], align 8
59 // CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds %struct.S, %struct.S* %[[this]], i32 0, i32 0
60 // CHECK: %[[m1:[^ ]*]] = load i32, i32* %[[m1_ptr]]
61 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
62 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[m1]])
63 
64 struct V {
65   void test_virtual(int p1);
66   virtual void virt(int p1);
67 };
68 
test_virtual(int p1)69 void V::test_virtual(int p1) {
70   __try {
71     might_crash();
72   } __finally {
73     virt(p1);
74   }
75 }
76 
77 // CHECK-LABEL: define dso_local void @"?test_virtual@V@@QEAAXH@Z"(%struct.V* {{[^,]*}} %this, i32 noundef %p1)
78 // CHECK: @llvm.localescape(%struct.V** %[[this_addr:[^, ]*]], i32* %[[p1_addr:[^, ]*]])
79 // CHECK: store i32 %p1, i32* %[[p1_addr]], align 4
80 // CHECK: store %struct.V* %this, %struct.V** %[[this_addr]], align 8
81 // CHECK: invoke void @might_crash()
82 
83 // CHECK-LABEL: define internal void @"?fin$0@0@test_virtual@V@@"(i8 noundef %abnormal_termination, i8* noundef %frame_pointer)
84 // CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.V*, i32)* @"?test_virtual@V@@QEAAXH@Z" to i8*), i8* %frame_pointer, i32 0)
85 // CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %struct.V**
86 // CHECK: %[[this:[^ ]*]] = load %struct.V*, %struct.V** %[[this_ptr]], align 8
87 // CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.V*, i32)* @"?test_virtual@V@@QEAAXH@Z" to i8*), i8* %frame_pointer, i32 1)
88 // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
89 // CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
90 // CHECK: %[[this_2:[^ ]*]] = bitcast %struct.V* %[[this]] to void (%struct.V*, i32)***
91 // CHECK: %[[vtable:[^ ]*]] = load void (%struct.V*, i32)**, void (%struct.V*, i32)*** %[[this_2]], align 8
92 // CHECK: %[[vfn:[^ ]*]] = getelementptr inbounds void (%struct.V*, i32)*, void (%struct.V*, i32)** %[[vtable]], i64 0
93 // CHECK: %[[virt:[^ ]*]] = load void (%struct.V*, i32)*, void (%struct.V*, i32)** %[[vfn]], align 8
94 // CHECK: call void %[[virt]](%struct.V* {{[^,]*}} %[[this]], i32 noundef %[[p1]])
95 
test_lambda()96 void test_lambda() {
97   int l1 = 13;
98   auto lambda = [&]() {
99     int l2 = 42;
100     __try {
101       might_crash();
102     } __except (basic_filter(l1, l2)) {
103     }
104   };
105   lambda();
106 }
107 
108 // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* {{[^,]*}} %this)
109 // CHECK: @llvm.localescape(%class.anon** %[[this_addr:[^, ]*]], i32* %[[l2_addr:[^, ]*]])
110 // CHECK: store %class.anon* %this, %class.anon** %[[this_addr]], align 8
111 // CHECK: store i32 42, i32* %[[l2_addr]], align 4
112 // CHECK: invoke void @might_crash()
113 
114 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
115 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %frame_pointer)
116 // CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 0)
117 // CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon**
118 // CHECK: %[[this:[^ ]*]] = load %class.anon*, %class.anon** %[[this_ptr]], align 8
119 // CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon*)* @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* %[[fp]], i32 1)
120 // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
121 // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
122 // CHECK: %[[l1_ref_ptr:[^ ]*]] = getelementptr inbounds %class.anon, %class.anon* %[[this]], i32 0, i32 0
123 // CHECK: %[[l1_ref:[^ ]*]] = load i32*, i32** %[[l1_ref_ptr]]
124 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ref]]
125 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[l2]])
126 
127 struct U {
128   void this_in_lambda();
129 };
130 
this_in_lambda()131 void U::this_in_lambda() {
132   auto lambda = [=]() {
133     __try {
134       might_crash();
135     } __except (basic_filter(0, this)) {
136     }
137   };
138   lambda();
139 }
140 
141 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@"(i8* noundef %exception_pointers, i8* noundef %frame_pointer)
142 // CHECK: %[[this_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%class.anon.0*)* @"??R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ" to i8*), i8* %[[fp:[^ ]*]], i32 0)
143 // CHECK: %[[this_ptr:[^ ]*]] = bitcast i8* %[[this_i8]] to %class.anon.0**
144 // CHECK: %[[this:[^ ]*]] = load %class.anon.0*, %class.anon.0** %[[this_ptr]], align 8
145 // CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds %class.anon.0, %class.anon.0* %[[this]], i32 0, i32 0
146 // CHECK: %[[actual_this:[^ ]*]] = load %struct.U*, %struct.U** %[[actual_this_ptr]], align 8
147 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef 0, %struct.U* noundef %[[actual_this]])
148