// 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 // CHECK: define dso_local noundef i32 @"?bar@@YAHHVB1@@VB2@@@Z" // CHECK: %coerce.dive1 = getelementptr inbounds %class.B2 // CHECK: %coerce.dive2 = getelementptr inbounds %class.B1 // ----- scope begin of two passed-by-value temps // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B1@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B2@@QEAA@XZ" // CHECK: define linkonce_odr dso_local void @"??1B2@@QEAA@XZ" // CHECK: %this.addr = alloca ptr // ----- B1 scope begin without base ctor // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B1@@QEAA@XZ" // CHECK: define dso_local void @"?goo@@YA?AVB1@@H@Z" // CHECK: call noundef ptr @"??0B2@@QEAA@XZ"(ptr // CHECK: invoke void @llvm.seh.scope.begin() // check: call void @llvm.memcpy // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B2@@QEAA@XZ"(ptr // CHECK: define linkonce_odr dso_local noundef ptr @"??0B2@@QEAA@XZ" // CHECK: call noundef ptr @"??0B1@@QEAA@XZ"(ptr // ----- scope begin of base ctor // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.end() // ----- B1 scope end without base dtor // **************************************************************************** // Abstract: Test CPP Conditional-Expr & ABI Temps under SEH -EHa option void printf(...); int xxxx = 0; int* ptr; int foo(int a) { return xxxx + a; } class B1 { public: int data = 90; B1() { foo(data + 111); } ~B1() { printf("in B1 Dtor \n"); } }; class B2 : public B1 { public: B2() { foo(data + 222); } ~B2() { printf("in B2 Dtor \n");; } }; class B3 : public B2 { public: B3() { foo(data + 333); } ~B3() { printf("in B3 Dtor \n");; } }; int bar(int j, class B1 b1Bar, class B2 b2Bar) { int ww; if ( j > 0) ww = b1Bar.data; else ww = b2Bar.data; return ww + *ptr; } class B1 goo(int w) { class B2 b2ingoo; b2ingoo.data += w; return b2ingoo; } // CHECK: define dso_local noundef i32 @main() // CHECK: invoke void @llvm.seh.scope.begin() // --- beginning of conditional temp test // CHECK: invoke noundef ptr @"??0B2@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke noundef ptr @"??0B3@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B3@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.end() // CHECK: call void @"??1B2@@QEAA@XZ" // ----- end of conditional temp test // ----- testing caller's passed-by-value temps // setting scope in case exception occurs before the call // check: invoke ptr @"??0B2@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke noundef ptr @"??0B1@@QEAA@XZ" // CHECK: invoke void @llvm.seh.scope.begin() // ----- end of temps' scope right before callee // CHECK: invoke void @llvm.seh.scope.end() // CHECK: invoke void @llvm.seh.scope.end() // CHECK: invoke noundef i32 @"?bar@@YAHHVB1@@VB2@@@Z" // ----- testing caller's return-by-value temp // scope begins right after callee which is the ctor of return temp // CHECK: void @"?goo@@YA?AVB1@@H@Z" // CHECK: invoke void @llvm.seh.scope.begin() // CHECK: invoke void @llvm.seh.scope.end() int main() { class B3 b3inmain; // Test conditional ctor and dtor int m = (xxxx > 1) ? B2().data + foo(99) : B3().data + foo(88); // Test: passed-in by value // Per Windows ABI, ctored by caller, dtored by callee int i = bar(foo(0), B1(), B2()); // Test: returned by value // Per Windows ABI, caller allocate a temp in stack, then ctored by callee, // finally dtored in caller after consumed class B1 b1fromgoo = goo(i); return m + b1fromgoo.data + b3inmain.data; }