| 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 | \ |
| 3 | // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH |
| 4 | |
| 5 | extern "C" int basic_filter(int v, ...); |
| 6 | extern "C" void might_crash(); |
| 7 | |
| 8 | extern "C" void test_freefunc(int p1) { |
| 9 | int l1 = 13; |
| 10 | static int s1 = 42; |
| 11 | __try { |
| 12 | might_crash(); |
| 13 | } __except(basic_filter(p1, l1, s1)) { |
| 14 | } |
| 15 | } |
| 16 | |
| 17 | // CHECK-LABEL: define dso_local void @test_freefunc(i32 %p1) |
| 18 | // CHECK: @llvm.localescape(i32* %[[p1_ptr:[^, ]*]], i32* %[[l1_ptr:[^, ]*]]) |
| 19 | // CHECK: store i32 %p1, i32* %[[p1_ptr]], align 4 |
| 20 | // CHECK: store i32 13, i32* %[[l1_ptr]], align 4 |
| 21 | // CHECK: invoke void @might_crash() |
| 22 | |
| 23 | // CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer) |
| 24 | // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer) |
| 25 | // CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0) |
| 26 | // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32* |
| 27 | // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1) |
| 28 | // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* |
| 29 | // CHECK: %[[s1:[^ ]*]] = load i32, i32* @"?s1@?1??test_freefunc@@9@4HA", align 4 |
| 30 | // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] |
| 31 | // CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]] |
| 32 | // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[p1]], i32 %[[l1]], i32 %[[s1]]) |
| 33 | |
| 34 | struct S { |
| 35 | int m1; |
| 36 | void test_method(void); |
| 37 | }; |
| 38 | |
| 39 | void S::test_method() { |
| 40 | int l1 = 13; |
| 41 | __try { |
| 42 | might_crash(); |
| 43 | } __except(basic_filter(l1)) { |
| 44 | // FIXME: Test capturing 'this' and 'm1'. |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(%struct.S* %this) |
| 49 | // CHECK: @llvm.localescape(i32* %[[l1_addr:[^, ]*]]) |
| 50 | // CHECK: store i32 13, i32* %[[l1_addr]], align 4 |
| 51 | // CHECK: invoke void @might_crash() |
| 52 | |
| 53 | // CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* %exception_pointers, i8* %frame_pointer) |
| 54 | // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer) |
| 55 | // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void (%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0) |
| 56 | // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32* |
| 57 | // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]] |
| 58 | // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l1]]) |
| 59 | |
| 60 | void test_lambda() { |
| 61 | int l1 = 13; |
| 62 | auto lambda = [&]() { |
| 63 | int l2 = 42; |
| 64 | __try { |
| 65 | might_crash(); |
| 66 | } __except(basic_filter(l2)) { |
| 67 | // FIXME: Test 'l1' when we can capture the lambda's 'this' decl. |
| 68 | } |
| 69 | }; |
| 70 | lambda(); |
| 71 | } |
| 72 | |
| 73 | // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(%class.anon* %this) |
| 74 | // CHECK: @llvm.localescape(i32* %[[l2_addr:[^, ]*]]) |
| 75 | // CHECK: store i32 42, i32* %[[l2_addr]], align 4 |
| 76 | // CHECK: invoke void @might_crash() |
| 77 | |
| 78 | // CHECK-LABEL: define internal i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer) |
| 79 | // 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) |
| 80 | // 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) |
| 81 | // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32* |
| 82 | // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]] |
| 83 | // CHECK: call i32 (i32, ...) @basic_filter(i32 %[[l2]]) |
| 84 | |