1 // RUN: %clang_cc1 -no-opaque-pointers -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 
foo(int a)43 int foo(int a)
44 {
45   return xxxx + a;
46 }
47 
48 class B1      {
49 public:
50    int data = 90;
B1()51    B1() { foo(data + 111); }
~B1()52     ~B1() { printf("in B1 Dtor \n"); }
53 };
54 class B2 : public B1 {
55 public:
B2()56   B2() { foo(data + 222); }
~B2()57   ~B2() { printf("in B2 Dtor \n");; }
58 };
59 class B3 : public B2 {
60 public:
B3()61   B3() { foo(data + 333); }
~B3()62   ~B3() { printf("in B3 Dtor \n");; }
63 };
64 
bar(int j,class B1 b1Bar,class B2 b2Bar)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 
goo(int w)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 
main()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 }