1 // RUN: %clang_cc1 -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 
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 %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 i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %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 %[[p1]], i32 %[[l1]], i32 %[[s1]])
32 
33 struct S {
34   int m1;
35   void test_method(void);
36 };
37 
38 void S::test_method() {
39   int l1 = 13;
40   __try {
41     might_crash();
42   } __except(basic_filter(l1)) {
43     // FIXME: Test capturing 'this' and 'm1'.
44   }
45 }
46 
47 // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* {{[^,]*}} %this)
48 // CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]])
49 // CHECK: store i32 13, i32* %[[l1_addr]], align 4
50 // CHECK: invoke void @might_crash()
51 
52 // CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %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: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
57 // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]])
58 
59 void test_lambda() {
60   int l1 = 13;
61   auto lambda = [&]() {
62     int l2 = 42;
63     __try {
64       might_crash();
65     } __except(basic_filter(l2)) {
66       // FIXME: Test 'l1' when we can capture the lambda's 'this' decl.
67     }
68   };
69   lambda();
70 }
71 
72 // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* {{[^,]*}} %this)
73 // CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]])
74 // CHECK: store i32 42, i32* %[[l2_addr]], align 4
75 // CHECK: invoke void @might_crash()
76 
77 // CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
78 // 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)
80 // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
81 // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
82 // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]])
83