| // 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 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 %class.B2* |
| // ----- 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 %class.B2* @"??0B2@@QEAA@XZ"(%class.B2* |
| // 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"(%class.B2* |
| |
| // CHECK: define linkonce_odr dso_local %class.B2* @"??0B2@@QEAA@XZ" |
| // CHECK: call %class.B1* @"??0B1@@QEAA@XZ"(%class.B1* |
| // ----- 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 i32 @main() |
| // CHECK: invoke void @llvm.seh.scope.begin() |
| // --- beginning of conditional temp test |
| // CHECK: invoke %class.B2* @"??0B2@@QEAA@XZ" |
| // CHECK: invoke void @llvm.seh.scope.begin() |
| // CHECK: invoke %class.B3* @"??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 %class.B2* @"??0B2@@QEAA@XZ" |
| // CHECK: invoke void @llvm.seh.scope.begin() |
| // CHECK: invoke %class.B1* @"??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 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; |
| } |