1 // RUN: %clang_cc1 -triple x86_64-windows -fasync-exceptions -fcxx-exceptions -fexceptions -fms-extensions -x c++ -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s 2 3 // CHECK: define dso_local noundef i32 @"?bar@@YAHHVB1@@VB2@@@Z" 4 // CHECK: %coerce.dive1 = getelementptr inbounds %class.B2 5 // CHECK: %coerce.dive2 = getelementptr inbounds %class.B1 6 // ----- scope begin of two passed-by-value temps 7 // CHECK: invoke void @llvm.seh.scope.begin() 8 // CHECK: invoke void @llvm.seh.scope.begin() 9 // CHECK: invoke void @llvm.seh.scope.end() 10 // CHECK: call void @"??1B1@@QEAA@XZ" 11 // CHECK: invoke void @llvm.seh.scope.end() 12 // CHECK: call void @"??1B2@@QEAA@XZ" 13 14 // CHECK: define linkonce_odr dso_local void @"??1B2@@QEAA@XZ" 15 // CHECK: %this.addr = alloca %class.B2* 16 // ----- B1 scope begin without base ctor 17 // CHECK: invoke void @llvm.seh.scope.begin() 18 // CHECK: invoke void @llvm.seh.scope.end() 19 // CHECK: call void @"??1B1@@QEAA@XZ" 20 21 // CHECK: define dso_local void @"?goo@@YA?AVB1@@H@Z" 22 // CHECK: call noundef %class.B2* @"??0B2@@QEAA@XZ"(%class.B2* 23 // CHECK: invoke void @llvm.seh.scope.begin() 24 // check: call void @llvm.memcpy 25 // CHECK: invoke void @llvm.seh.scope.end() 26 // CHECK: call void @"??1B2@@QEAA@XZ"(%class.B2* 27 28 // CHECK: define linkonce_odr dso_local noundef %class.B2* @"??0B2@@QEAA@XZ" 29 // CHECK: call noundef %class.B1* @"??0B1@@QEAA@XZ"(%class.B1* 30 // ----- scope begin of base ctor 31 // CHECK: invoke void @llvm.seh.scope.begin() 32 // CHECK: invoke void @llvm.seh.scope.end() 33 // ----- B1 scope end without base dtor 34 35 // **************************************************************************** 36 // Abstract: Test CPP Conditional-Expr & ABI Temps under SEH -EHa option 37 38 void printf(...); 39 40 int xxxx = 0; 41 int* ptr; 42 43 int foo(int a) 44 { 45 return xxxx + a; 46 } 47 48 class B1 { 49 public: 50 int data = 90; 51 B1() { foo(data + 111); } 52 ~B1() { printf("in B1 Dtor \n"); } 53 }; 54 class B2 : public B1 { 55 public: 56 B2() { foo(data + 222); } 57 ~B2() { printf("in B2 Dtor \n");; } 58 }; 59 class B3 : public B2 { 60 public: 61 B3() { foo(data + 333); } 62 ~B3() { printf("in B3 Dtor \n");; } 63 }; 64 65 int bar(int j, class B1 b1Bar, class B2 b2Bar) 66 { 67 int ww; 68 if ( j > 0) 69 ww = b1Bar.data; 70 else 71 ww = b2Bar.data; 72 return ww + *ptr; 73 } 74 75 class B1 goo(int w) 76 { 77 class B2 b2ingoo; 78 b2ingoo.data += w; 79 return b2ingoo; 80 } 81 82 // CHECK: define dso_local noundef i32 @main() 83 // CHECK: invoke void @llvm.seh.scope.begin() 84 // --- beginning of conditional temp test 85 // CHECK: invoke noundef %class.B2* @"??0B2@@QEAA@XZ" 86 // CHECK: invoke void @llvm.seh.scope.begin() 87 // CHECK: invoke noundef %class.B3* @"??0B3@@QEAA@XZ" 88 // CHECK: invoke void @llvm.seh.scope.begin() 89 // CHECK: invoke void @llvm.seh.scope.end() 90 // CHECK: call void @"??1B3@@QEAA@XZ" 91 // CHECK: invoke void @llvm.seh.scope.end() 92 // CHECK: call void @"??1B2@@QEAA@XZ" 93 // ----- end of conditional temp test 94 95 // ----- testing caller's passed-by-value temps 96 // setting scope in case exception occurs before the call 97 // check: invoke %class.B2* @"??0B2@@QEAA@XZ" 98 // CHECK: invoke void @llvm.seh.scope.begin() 99 // CHECK: invoke noundef %class.B1* @"??0B1@@QEAA@XZ" 100 // CHECK: invoke void @llvm.seh.scope.begin() 101 // ----- end of temps' scope right before callee 102 // CHECK: invoke void @llvm.seh.scope.end() 103 // CHECK: invoke void @llvm.seh.scope.end() 104 // CHECK: invoke noundef i32 @"?bar@@YAHHVB1@@VB2@@@Z" 105 106 // ----- testing caller's return-by-value temp 107 // scope begins right after callee which is the ctor of return temp 108 // CHECK: void @"?goo@@YA?AVB1@@H@Z" 109 // CHECK: invoke void @llvm.seh.scope.begin() 110 // CHECK: invoke void @llvm.seh.scope.end() 111 112 int main() { 113 class B3 b3inmain; 114 115 // Test conditional ctor and dtor 116 int m = (xxxx > 1) ? B2().data + foo(99) : 117 B3().data + foo(88); 118 119 // Test: passed-in by value 120 // Per Windows ABI, ctored by caller, dtored by callee 121 int i = bar(foo(0), B1(), B2()); 122 123 // Test: returned by value 124 // Per Windows ABI, caller allocate a temp in stack, then ctored by callee, 125 // finally dtored in caller after consumed 126 class B1 b1fromgoo = goo(i); 127 128 return m + b1fromgoo.data + b3inmain.data; 129 }