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 noundef %p1) 17 // CHECK: @llvm.localescape(ptr %[[p1_ptr:[^, ]*]], ptr %[[l1_ptr:[^, ]*]]) 18 // CHECK: store i32 %p1, ptr %[[p1_ptr]], align 4 19 // CHECK: store i32 13, ptr %[[l1_ptr]], align 4 20 // CHECK: invoke void @might_crash() 21 22 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_freefunc@@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer) 23 // CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @test_freefunc, ptr %frame_pointer) 24 // CHECK: %[[p1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @test_freefunc, ptr %[[fp]], i32 0) 25 // CHECK: %[[l1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @test_freefunc, ptr %[[fp]], i32 1) 26 // CHECK: %[[s1:[^ ]*]] = load i32, ptr @"?s1@?1??test_freefunc@@9@4HA", align 4 27 // CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_i8]] 28 // CHECK: %[[p1:[^ ]*]] = load i32, ptr %[[p1_i8]] 29 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[p1]], i32 noundef %[[l1]], i32 noundef %[[s1]]) 30 31 struct S { 32 int m1; 33 void test_method(void); 34 }; 35 36 void S::test_method() { 37 int l1 = 13; 38 __try { 39 might_crash(); 40 } __except (basic_filter(l1, m1)) { 41 } 42 } 43 44 // CHECK-LABEL: define dso_local void @"?test_method@S@@QEAAXXZ"(ptr {{[^,]*}} %this) 45 // CHECK: @llvm.localescape(ptr %[[l1_addr:[^, ]*]], ptr %[[this_addr:[^, ]*]]) 46 // CHECK: store ptr %this, ptr %[[this_addr]], align 8 47 // CHECK: store i32 13, ptr %[[l1_addr]], align 4 48 // CHECK: invoke void @might_crash() 49 50 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@test_method@S@@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer) 51 // CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @"?test_method@S@@QEAAXXZ", ptr %frame_pointer) 52 // CHECK: %[[l1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_method@S@@QEAAXXZ", ptr %[[fp]], i32 0) 53 // CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_method@S@@QEAAXXZ", ptr %[[fp]], i32 1) 54 // CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8 55 // CHECK: %[[m1_ptr:[^ ]*]] = getelementptr inbounds nuw %struct.S, ptr %[[this]], i32 0, i32 0 56 // CHECK: %[[m1:[^ ]*]] = load i32, ptr %[[m1_ptr]] 57 // CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_i8]] 58 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[m1]]) 59 60 struct V { 61 void test_virtual(int p1); 62 virtual void virt(int p1); 63 }; 64 65 void V::test_virtual(int p1) { 66 __try { 67 might_crash(); 68 } __finally { 69 virt(p1); 70 } 71 } 72 73 // CHECK-LABEL: define dso_local void @"?test_virtual@V@@QEAAXH@Z"(ptr {{[^,]*}} %this, i32 noundef %p1) 74 // CHECK: @llvm.localescape(ptr %[[this_addr:[^, ]*]], ptr %[[p1_addr:[^, ]*]]) 75 // CHECK: store i32 %p1, ptr %[[p1_addr]], align 4 76 // CHECK: store ptr %this, ptr %[[this_addr]], align 8 77 // CHECK: invoke void @might_crash() 78 79 // CHECK-LABEL: define internal void @"?fin$0@0@test_virtual@V@@"(i8 noundef %abnormal_termination, ptr noundef %frame_pointer) 80 // CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_virtual@V@@QEAAXH@Z", ptr %frame_pointer, i32 0) 81 // CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8 82 // CHECK: %[[p1_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"?test_virtual@V@@QEAAXH@Z", ptr %frame_pointer, i32 1) 83 // CHECK: %[[p1:[^ ]*]] = load i32, ptr %[[p1_i8]] 84 // CHECK: %[[vtable:[^ ]*]] = load ptr, ptr %[[this]], align 8 85 // CHECK: %[[vfn:[^ ]*]] = getelementptr inbounds ptr, ptr %[[vtable]], i64 0 86 // CHECK: %[[virt:[^ ]*]] = load ptr, ptr %[[vfn]], align 8 87 // CHECK: call void %[[virt]](ptr {{[^,]*}} %[[this]], i32 noundef %[[p1]]) 88 89 void test_lambda() { 90 int l1 = 13; 91 auto lambda = [&]() { 92 int l2 = 42; 93 __try { 94 might_crash(); 95 } __except (basic_filter(l1, l2)) { 96 } 97 }; 98 lambda(); 99 } 100 101 // CHECK-LABEL: define internal void @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ"(ptr {{[^,]*}} %this) 102 // CHECK: @llvm.localescape(ptr %[[this_addr:[^, ]*]], ptr %[[l2_addr:[^, ]*]]) 103 // CHECK: store ptr %this, ptr %[[this_addr]], align 8 104 // CHECK: store i32 42, ptr %[[l2_addr]], align 4 105 // CHECK: invoke void @might_crash() 106 107 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_0>@?0??test_lambda@@YAXXZ@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer) 108 // CHECK: %[[fp:[^ ]*]] = call ptr @llvm.eh.recoverfp(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %frame_pointer) 109 // CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %[[fp]], i32 0) 110 // CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8 111 // CHECK: %[[l2_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_0>@?0??test_lambda@@YAXXZ@QEBA@XZ", ptr %[[fp]], i32 1) 112 // CHECK: %[[l2:[^ ]*]] = load i32, ptr %[[l2_i8]] 113 // CHECK: %[[l1_ref_ptr:[^ ]*]] = getelementptr inbounds nuw %class.anon, ptr %[[this]], i32 0, i32 0 114 // CHECK: %[[l1_ref:[^ ]*]] = load ptr, ptr %[[l1_ref_ptr]] 115 // CHECK: %[[l1:[^ ]*]] = load i32, ptr %[[l1_ref]] 116 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef %[[l1]], i32 noundef %[[l2]]) 117 118 struct U { 119 void this_in_lambda(); 120 }; 121 122 void U::this_in_lambda() { 123 auto lambda = [=]() { 124 __try { 125 might_crash(); 126 } __except (basic_filter(0, this)) { 127 } 128 }; 129 lambda(); 130 } 131 132 // CHECK-LABEL: define internal noundef i32 @"?filt$0@0@?R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@"(ptr noundef %exception_pointers, ptr noundef %frame_pointer) 133 // CHECK: %[[this_i8:[^ ]*]] = call ptr @llvm.localrecover(ptr @"??R<lambda_1>@?0??this_in_lambda@U@@QEAAXXZ@QEBA@XZ", ptr %[[fp:[^ ]*]], i32 0) 134 // CHECK: %[[this:[^ ]*]] = load ptr, ptr %[[this_i8]], align 8 135 // CHECK: %[[actual_this_ptr:[^ ]*]] = getelementptr inbounds nuw %class.anon.0, ptr %[[this]], i32 0, i32 0 136 // CHECK: %[[actual_this:[^ ]*]] = load ptr, ptr %[[actual_this_ptr]], align 8 137 // CHECK: call i32 (i32, ...) @basic_filter(i32 noundef 0, ptr noundef %[[actual_this]]) 138