@@ -39,44 +39,87 @@ void S::test_method() {
39
39
int l1 = 13 ;
40
40
__try {
41
41
might_crash ();
42
- } __except (basic_filter (l1)) {
43
- // FIXME: Test capturing 'this' and 'm1'.
42
+ } __except (basic_filter (l1, m1)) {
44
43
}
45
44
}
46
45
47
46
// CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* {{[^,]*}} %this)
48
- // CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]])
47
+ // CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]], %struct.S** %[[this_addr:[^, ]*]])
48
+ // CHECK: store %struct.S* %this, %struct.S** %[[this_addr]], align 8
49
49
// CHECK: store i32 13, i32* %[[l1_addr]], align 4
50
50
// CHECK: invoke void @might_crash()
51
51
52
52
// CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer)
53
53
// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
54
54
// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
55
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]]
56
61
// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
57
- // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
62
+ // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]], i32 %[[m1]])
63
+
64
+ struct V {
65
+ void test_virtual (int p1);
66
+ virtual void virt (int p1);
67
+ };
68
+
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 %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 %abnormal_termination, i8* %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 %[[p1]])
58
95
59
96
void test_lambda () {
60
97
int l1 = 13 ;
61
98
auto lambda = [&]() {
62
99
int l2 = 42 ;
63
100
__try {
64
101
might_crash ();
65
- } __except (basic_filter (l2)) {
66
- // FIXME: Test 'l1' when we can capture the lambda's 'this' decl.
102
+ } __except (basic_filter (l1, l2)) {
67
103
}
68
104
};
69
105
lambda ();
70
106
}
71
107
72
108
// CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* {{[^,]*}} %this)
73
- // CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]])
109
+ // CHECK: @llvm.localescape(%class.anon** %[[this_addr:[^, ]*]], i32* %[[l2_addr:[^, ]*]])
110
+ // CHECK: store %class.anon* %this, %class.anon** %[[this_addr]], align 8
74
111
// CHECK: store i32 42, i32* %[[l2_addr]], align 4
75
112
// CHECK: invoke void @might_crash()
76
113
77
114
// CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
78
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)
79
- // 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 0)
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)
80
120
// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
81
121
// CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
82
- // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]])
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 %[[l1]], i32 %[[l2]])
0 commit comments