xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/microsoft-abi-exceptions.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc struct A {
4*f4a2713aSLionel Sambuc   A();
5*f4a2713aSLionel Sambuc   ~A();
6*f4a2713aSLionel Sambuc   int a;
7*f4a2713aSLionel Sambuc };
8*f4a2713aSLionel Sambuc 
9*f4a2713aSLionel Sambuc A getA();
10*f4a2713aSLionel Sambuc 
11*f4a2713aSLionel Sambuc int TakesTwo(A a, A b);
12*f4a2713aSLionel Sambuc void HasEHCleanup() {
13*f4a2713aSLionel Sambuc   TakesTwo(getA(), getA());
14*f4a2713aSLionel Sambuc }
15*f4a2713aSLionel Sambuc 
16*f4a2713aSLionel Sambuc // With exceptions, we need to clean up at least one of these temporaries.
17*f4a2713aSLionel Sambuc // WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} {
18*f4a2713aSLionel Sambuc //    First one doesn't have any cleanups, no need for invoke.
19*f4a2713aSLionel Sambuc // WIN32:   call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
20*f4a2713aSLionel Sambuc //    If this call throws, we have to cleanup the first temporary.
21*f4a2713aSLionel Sambuc // WIN32:   invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}})
22*f4a2713aSLionel Sambuc //    If this call throws, we already popped our cleanups
23*f4a2713aSLionel Sambuc // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
24*f4a2713aSLionel Sambuc // WIN32:   ret void
25*f4a2713aSLionel Sambuc //
26*f4a2713aSLionel Sambuc //    There should be one dtor call for unwinding from the second getA.
27*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
28*f4a2713aSLionel Sambuc // WIN32: }
29*f4a2713aSLionel Sambuc 
30*f4a2713aSLionel Sambuc void TakeRef(const A &a);
31*f4a2713aSLionel Sambuc int HasDeactivatedCleanups() {
32*f4a2713aSLionel Sambuc   return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
33*f4a2713aSLionel Sambuc }
34*f4a2713aSLionel Sambuc 
35*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} {
36*f4a2713aSLionel Sambuc // WIN32:   %[[isactive:.*]] = alloca i1
37*f4a2713aSLionel Sambuc // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
38*f4a2713aSLionel Sambuc // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
39*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
40*f4a2713aSLionel Sambuc // WIN32:   store i1 true, i1* %[[isactive]]
41*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
42*f4a2713aSLionel Sambuc // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
43*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
44*f4a2713aSLionel Sambuc // WIN32:   store i1 false, i1* %[[isactive]]
45*f4a2713aSLionel Sambuc // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
46*f4a2713aSLionel Sambuc //        Destroy the two const ref temporaries.
47*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
48*f4a2713aSLionel Sambuc // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
49*f4a2713aSLionel Sambuc // WIN32:   ret i32
50*f4a2713aSLionel Sambuc //
51*f4a2713aSLionel Sambuc //        Conditionally destroy arg1.
52*f4a2713aSLionel Sambuc // WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
53*f4a2713aSLionel Sambuc // WIN32:   br i1 %[[cond]]
54*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
55*f4a2713aSLionel Sambuc // WIN32: }
56*f4a2713aSLionel Sambuc 
57*f4a2713aSLionel Sambuc // Test putting the cleanups inside a conditional.
58*f4a2713aSLionel Sambuc int CouldThrow();
59*f4a2713aSLionel Sambuc int HasConditionalCleanup(bool cond) {
60*f4a2713aSLionel Sambuc   return (cond ? TakesTwo(A(), A()) : CouldThrow());
61*f4a2713aSLionel Sambuc }
62*f4a2713aSLionel Sambuc 
63*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} {
64*f4a2713aSLionel Sambuc // WIN32:   store i1 false
65*f4a2713aSLionel Sambuc // WIN32:   br i1
66*f4a2713aSLionel Sambuc //        No cleanups, so we call and then activate a cleanup if it succeeds.
67*f4a2713aSLionel Sambuc // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]])
68*f4a2713aSLionel Sambuc // WIN32:   store i1 true
69*f4a2713aSLionel Sambuc //        Now we have a cleanup for the first aggregate, so we invoke.
70*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}})
71*f4a2713aSLionel Sambuc //        Now we have no cleanups because TakeTwo will destruct both args.
72*f4a2713aSLionel Sambuc // WIN32:   call i32 @"\01?TakesTwo@@YAHUA@@0@Z"
73*f4a2713aSLionel Sambuc //        Still no cleanups, so call.
74*f4a2713aSLionel Sambuc // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
75*f4a2713aSLionel Sambuc //        Somewhere in the landing pad for our single invoke, call the dtor.
76*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
77*f4a2713aSLionel Sambuc // WIN32: }
78*f4a2713aSLionel Sambuc 
79*f4a2713aSLionel Sambuc // Now test both.
80*f4a2713aSLionel Sambuc int HasConditionalDeactivatedCleanups(bool cond) {
81*f4a2713aSLionel Sambuc   return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
82*f4a2713aSLionel Sambuc }
83*f4a2713aSLionel Sambuc 
84*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} {
85*f4a2713aSLionel Sambuc // WIN32:   %[[arg1:.*]] = alloca %struct.A, align 4
86*f4a2713aSLionel Sambuc // WIN32:   alloca i1
87*f4a2713aSLionel Sambuc // WIN32:   %[[arg1_cond:.*]] = alloca i1
88*f4a2713aSLionel Sambuc //        Start all four cleanups as deactivated.
89*f4a2713aSLionel Sambuc // WIN32:   store i1 false
90*f4a2713aSLionel Sambuc // WIN32:   store i1 false
91*f4a2713aSLionel Sambuc // WIN32:   store i1 false
92*f4a2713aSLionel Sambuc // WIN32:   store i1 false
93*f4a2713aSLionel Sambuc // WIN32:   br i1
94*f4a2713aSLionel Sambuc //        True condition.
95*f4a2713aSLionel Sambuc // WIN32:   call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
96*f4a2713aSLionel Sambuc // WIN32:   store i1 true
97*f4a2713aSLionel Sambuc // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
98*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]])
99*f4a2713aSLionel Sambuc // WIN32:   store i1 true, i1* %[[arg1_cond]]
100*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
101*f4a2713aSLionel Sambuc // WIN32:   store i1 true
102*f4a2713aSLionel Sambuc // WIN32:   invoke void @"\01?TakeRef@@YAXABUA@@@Z"
103*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"
104*f4a2713aSLionel Sambuc // WIN32:   store i1 true
105*f4a2713aSLionel Sambuc // WIN32:   store i1 false, i1* %[[arg1_cond]]
106*f4a2713aSLionel Sambuc // WIN32:   invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"
107*f4a2713aSLionel Sambuc //        False condition.
108*f4a2713aSLionel Sambuc // WIN32:   invoke i32 @"\01?CouldThrow@@YAHXZ"()
109*f4a2713aSLionel Sambuc //        Two normal cleanups for TakeRef args.
110*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
111*f4a2713aSLionel Sambuc // WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"
112*f4a2713aSLionel Sambuc // WIN32:   ret i32
113*f4a2713aSLionel Sambuc //
114*f4a2713aSLionel Sambuc //        Somewhere in the landing pad soup, we conditionally destroy arg1.
115*f4a2713aSLionel Sambuc // WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
116*f4a2713aSLionel Sambuc // WIN32:   br i1 %[[isactive]]
117*f4a2713aSLionel Sambuc // WIN32:   invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
118*f4a2713aSLionel Sambuc // WIN32: }
119*f4a2713aSLionel Sambuc 
120*f4a2713aSLionel Sambuc namespace crash_on_partial_destroy {
121*f4a2713aSLionel Sambuc struct A {
122*f4a2713aSLionel Sambuc   virtual ~A();
123*f4a2713aSLionel Sambuc };
124*f4a2713aSLionel Sambuc 
125*f4a2713aSLionel Sambuc struct B : virtual A {
126*f4a2713aSLionel Sambuc   // Has an implicit destructor.
127*f4a2713aSLionel Sambuc };
128*f4a2713aSLionel Sambuc 
129*f4a2713aSLionel Sambuc struct C : B {
130*f4a2713aSLionel Sambuc   C();
131*f4a2713aSLionel Sambuc };
132*f4a2713aSLionel Sambuc 
133*f4a2713aSLionel Sambuc void foo();
134*f4a2713aSLionel Sambuc // We used to crash when emitting this.
135*f4a2713aSLionel Sambuc C::C() { foo(); }
136*f4a2713aSLionel Sambuc 
137*f4a2713aSLionel Sambuc // Verify that we don't bother with a vbtable lookup when adjusting the this
138*f4a2713aSLionel Sambuc // pointer to call a base destructor from a constructor while unwinding.
139*f4a2713aSLionel Sambuc // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} {
140*f4a2713aSLionel Sambuc // WIN32:      landingpad
141*f4a2713aSLionel Sambuc //
142*f4a2713aSLionel Sambuc //        We shouldn't do any vbptr loads, just constant GEPs.
143*f4a2713aSLionel Sambuc // WIN32-NOT:  load
144*f4a2713aSLionel Sambuc // WIN32:      getelementptr i8* %{{.*}}, i32 4
145*f4a2713aSLionel Sambuc // WIN32-NOT:  load
146*f4a2713aSLionel Sambuc // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
147*f4a2713aSLionel Sambuc // WIN32:      invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ"
148*f4a2713aSLionel Sambuc //
149*f4a2713aSLionel Sambuc // WIN32-NOT:  load
150*f4a2713aSLionel Sambuc // WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
151*f4a2713aSLionel Sambuc // WIN32-NOT:  load
152*f4a2713aSLionel Sambuc // WIN32:      getelementptr inbounds i8* %{{.*}}, i64 4
153*f4a2713aSLionel Sambuc // WIN32-NOT:  load
154*f4a2713aSLionel Sambuc // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
155*f4a2713aSLionel Sambuc // WIN32:      invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"
156*f4a2713aSLionel Sambuc // WIN32: }
157*f4a2713aSLionel Sambuc }
158