xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGenCXX/ctor-dtor-alias.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases | FileCheck --check-prefix=NOOPT %s
2f4a2713aSLionel Sambuc 
3*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-linux -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns > %t
4*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s
5*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s
6*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s
7*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s
8*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s
9*0a6a1f1dSLionel Sambuc // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t %s
10*0a6a1f1dSLionel Sambuc 
11*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck --check-prefix=COFF %s
12f4a2713aSLionel Sambuc 
13f4a2713aSLionel Sambuc namespace test1 {
14*0a6a1f1dSLionel Sambuc // Test that we produce the apropriate comdats when creating aliases to
15*0a6a1f1dSLionel Sambuc // weak_odr constructors and destructors.
16f4a2713aSLionel Sambuc 
17*0a6a1f1dSLionel Sambuc // CHECK1: @_ZN5test16foobarIvEC1Ev = weak_odr alias void {{.*}} @_ZN5test16foobarIvEC2Ev
18*0a6a1f1dSLionel Sambuc // CHECK1: @_ZN5test16foobarIvED1Ev = weak_odr alias void (%"struct.test1::foobar"*)* @_ZN5test16foobarIvED2Ev
19*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvEC2Ev({{.*}} comdat($_ZN5test16foobarIvEC5Ev)
20*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvED2Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
21*0a6a1f1dSLionel Sambuc // CHECK1: define weak_odr void @_ZN5test16foobarIvED0Ev({{.*}} comdat($_ZN5test16foobarIvED5Ev)
22*0a6a1f1dSLionel Sambuc // CHECK1-NOT: comdat
23f4a2713aSLionel Sambuc 
24*0a6a1f1dSLionel Sambuc // COFF doesn't support comdats with arbitrary names (C5/D5).
25*0a6a1f1dSLionel Sambuc // COFF-NOT: comdat
26*0a6a1f1dSLionel Sambuc 
27*0a6a1f1dSLionel Sambuc template <typename T>
28*0a6a1f1dSLionel Sambuc struct foobar {
foobartest1::foobar29f4a2713aSLionel Sambuc   foobar() {}
~foobartest1::foobar30*0a6a1f1dSLionel Sambuc   virtual ~foobar() {}
31f4a2713aSLionel Sambuc };
32f4a2713aSLionel Sambuc 
33f4a2713aSLionel Sambuc template struct foobar<void>;
34f4a2713aSLionel Sambuc }
35f4a2713aSLionel Sambuc 
36f4a2713aSLionel Sambuc namespace test2 {
37f4a2713aSLionel Sambuc // test that when the destrucor is linkonce_odr we just replace every use of
38f4a2713aSLionel Sambuc // C1 with C2.
39f4a2713aSLionel Sambuc 
40*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @__cxx_global_var_init()
41*0a6a1f1dSLionel Sambuc // CHECK1: call void @_ZN5test26foobarIvEC2Ev
42*0a6a1f1dSLionel Sambuc // CHECK1: define linkonce_odr void @_ZN5test26foobarIvEC2Ev(
43f4a2713aSLionel Sambuc void g();
44f4a2713aSLionel Sambuc template <typename T> struct foobar {
foobartest2::foobar45f4a2713aSLionel Sambuc   foobar() { g(); }
46f4a2713aSLionel Sambuc };
47f4a2713aSLionel Sambuc foobar<void> x;
48f4a2713aSLionel Sambuc }
49f4a2713aSLionel Sambuc 
50f4a2713aSLionel Sambuc namespace test3 {
51f4a2713aSLionel Sambuc // test that instead of an internal alias we just use the other destructor
52f4a2713aSLionel Sambuc // directly.
53f4a2713aSLionel Sambuc 
54*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @__cxx_global_var_init1()
55*0a6a1f1dSLionel Sambuc // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test312_GLOBAL__N_11AD2Ev
56*0a6a1f1dSLionel Sambuc // CHECK1: define internal void @_ZN5test312_GLOBAL__N_11AD2Ev(
57f4a2713aSLionel Sambuc namespace {
58f4a2713aSLionel Sambuc struct A {
~Atest3::__anon97c009620111::A59f4a2713aSLionel Sambuc   ~A() {}
60f4a2713aSLionel Sambuc };
61f4a2713aSLionel Sambuc 
62f4a2713aSLionel Sambuc struct B : public A {};
63f4a2713aSLionel Sambuc }
64f4a2713aSLionel Sambuc 
65f4a2713aSLionel Sambuc B x;
66f4a2713aSLionel Sambuc }
67f4a2713aSLionel Sambuc 
68f4a2713aSLionel Sambuc namespace test4 {
69f4a2713aSLionel Sambuc   // Test that we don't produce aliases from B to A. We cannot because we cannot
70f4a2713aSLionel Sambuc   // guarantee that they will be present in every TU. Instead, we just call
71f4a2713aSLionel Sambuc   // A's destructor directly.
72f4a2713aSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc   // CHECK1: define internal void @__cxx_global_var_init2()
74*0a6a1f1dSLionel Sambuc   // CHECK1: call i32 @__cxa_atexit{{.*}}_ZN5test41AD2Ev
75*0a6a1f1dSLionel Sambuc   // CHECK1: define linkonce_odr void @_ZN5test41AD2Ev(
76f4a2713aSLionel Sambuc 
77f4a2713aSLionel Sambuc   // test that we don't do this optimization at -O0 so that the debugger can
78f4a2713aSLionel Sambuc   // see both destructors.
79*0a6a1f1dSLionel Sambuc   // NOOPT: define internal void @__cxx_global_var_init2()
80*0a6a1f1dSLionel Sambuc   // NOOPT: call i32 @__cxa_atexit{{.*}}@_ZN5test41BD2Ev
81*0a6a1f1dSLionel Sambuc   // NOOPT: define linkonce_odr void @_ZN5test41BD2Ev
82f4a2713aSLionel Sambuc   struct A {
~Atest4::A83f4a2713aSLionel Sambuc     virtual ~A() {}
84f4a2713aSLionel Sambuc   };
85f4a2713aSLionel Sambuc   struct B : public A{
~Btest4::B86f4a2713aSLionel Sambuc     ~B() {}
87f4a2713aSLionel Sambuc   };
88f4a2713aSLionel Sambuc   B X;
89f4a2713aSLionel Sambuc }
90f4a2713aSLionel Sambuc 
91f4a2713aSLionel Sambuc namespace test5 {
92f4a2713aSLionel Sambuc   // similar to test4, but with an internal B.
93f4a2713aSLionel Sambuc 
94*0a6a1f1dSLionel Sambuc   // CHECK2: define internal void @__cxx_global_var_init3()
95*0a6a1f1dSLionel Sambuc   // CHECK2: call i32 @__cxa_atexit{{.*}}_ZN5test51AD2Ev
96*0a6a1f1dSLionel Sambuc   // CHECK2: define linkonce_odr void @_ZN5test51AD2Ev(
97f4a2713aSLionel Sambuc   struct A {
~Atest5::A98f4a2713aSLionel Sambuc     virtual ~A() {}
99f4a2713aSLionel Sambuc   };
100f4a2713aSLionel Sambuc   namespace {
101f4a2713aSLionel Sambuc   struct B : public A{
~Btest5::__anon97c009620211::B102f4a2713aSLionel Sambuc     ~B() {}
103f4a2713aSLionel Sambuc   };
104f4a2713aSLionel Sambuc   }
105f4a2713aSLionel Sambuc   B X;
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc namespace test6 {
109f4a2713aSLionel Sambuc   // Test that we use ~A directly, even when ~A is not defined. The symbol for
110f4a2713aSLionel Sambuc   // ~B would have been internal and still contain a reference to ~A.
111f4a2713aSLionel Sambuc   struct A {
112f4a2713aSLionel Sambuc     virtual ~A();
113f4a2713aSLionel Sambuc   };
114f4a2713aSLionel Sambuc   namespace {
115f4a2713aSLionel Sambuc   struct B : public A {
~Btest6::__anon97c009620311::B116f4a2713aSLionel Sambuc     ~B() {}
117f4a2713aSLionel Sambuc   };
118f4a2713aSLionel Sambuc   }
119f4a2713aSLionel Sambuc   B X;
120*0a6a1f1dSLionel Sambuc   // CHECK3: define internal void @__cxx_global_var_init4()
121*0a6a1f1dSLionel Sambuc   // CHECK3: call i32 @__cxa_atexit({{.*}}@_ZN5test61AD2Ev
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc 
124f4a2713aSLionel Sambuc namespace test7 {
125f4a2713aSLionel Sambuc   // Test that we don't produce an alias from ~B to ~A<int> (or crash figuring
126f4a2713aSLionel Sambuc   // out if we should).
127f4a2713aSLionel Sambuc   // pr17875.
128*0a6a1f1dSLionel Sambuc   // CHECK3: define void @_ZN5test71BD2Ev
129f4a2713aSLionel Sambuc   template <typename> struct A {
~Atest7::A130f4a2713aSLionel Sambuc     ~A() {}
131f4a2713aSLionel Sambuc   };
132f4a2713aSLionel Sambuc   class B : A<int> {
133f4a2713aSLionel Sambuc     ~B();
134f4a2713aSLionel Sambuc   };
135f4a2713aSLionel Sambuc   template class A<int>;
~B()136f4a2713aSLionel Sambuc   B::~B() {}
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc namespace test8 {
140f4a2713aSLionel Sambuc   // Test that we replace ~zed with ~bar which is an alias to ~foo.
141*0a6a1f1dSLionel Sambuc   // CHECK4: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
142*0a6a1f1dSLionel Sambuc   // CHECK4: define internal void @__cxx_global_var_init5()
143*0a6a1f1dSLionel Sambuc   // CHECK4: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
144f4a2713aSLionel Sambuc   struct foo {
145f4a2713aSLionel Sambuc     ~foo();
146f4a2713aSLionel Sambuc   };
~foo()147f4a2713aSLionel Sambuc   foo::~foo() {}
148f4a2713aSLionel Sambuc   struct bar : public foo {
149f4a2713aSLionel Sambuc     ~bar();
150f4a2713aSLionel Sambuc   };
~bar()151f4a2713aSLionel Sambuc   bar::~bar() {}
152f4a2713aSLionel Sambuc   struct zed : public bar {};
153f4a2713aSLionel Sambuc   zed foo;
154f4a2713aSLionel Sambuc }
155f4a2713aSLionel Sambuc 
156*0a6a1f1dSLionel Sambuc namespace test9 {
157*0a6a1f1dSLionel Sambuc struct foo {
~footest9::foo158*0a6a1f1dSLionel Sambuc   __attribute__((stdcall)) ~foo() {
159*0a6a1f1dSLionel Sambuc   }
160*0a6a1f1dSLionel Sambuc };
161*0a6a1f1dSLionel Sambuc 
162*0a6a1f1dSLionel Sambuc struct bar : public foo {};
163*0a6a1f1dSLionel Sambuc 
zed()164*0a6a1f1dSLionel Sambuc void zed() {
165*0a6a1f1dSLionel Sambuc   // Test that we produce a call to bar's destructor. We used to call foo's, but
166*0a6a1f1dSLionel Sambuc   // it has a different calling conversion.
167*0a6a1f1dSLionel Sambuc   // CHECK4: call void @_ZN5test93barD2Ev
168*0a6a1f1dSLionel Sambuc   bar ptr;
169*0a6a1f1dSLionel Sambuc }
170*0a6a1f1dSLionel Sambuc }
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc // CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
173f4a2713aSLionel Sambuc // r194296 replaced C::~C with B::~B without emitting the later.
174f4a2713aSLionel Sambuc 
175f4a2713aSLionel Sambuc class A {
176f4a2713aSLionel Sambuc public:
177f4a2713aSLionel Sambuc   A(int);
178f4a2713aSLionel Sambuc   virtual ~A();
179f4a2713aSLionel Sambuc };
180f4a2713aSLionel Sambuc 
181f4a2713aSLionel Sambuc template <class>
182f4a2713aSLionel Sambuc class B : A {
183f4a2713aSLionel Sambuc public:
B()184f4a2713aSLionel Sambuc   B()
185f4a2713aSLionel Sambuc       : A(0) {
186f4a2713aSLionel Sambuc   }
~B()187f4a2713aSLionel Sambuc   __attribute__((always_inline)) ~B() {
188f4a2713aSLionel Sambuc   }
189f4a2713aSLionel Sambuc };
190f4a2713aSLionel Sambuc 
191f4a2713aSLionel Sambuc extern template class B<char>;
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc class C : B<char> {
194f4a2713aSLionel Sambuc };
195f4a2713aSLionel Sambuc 
196f4a2713aSLionel Sambuc void
fn1()197f4a2713aSLionel Sambuc fn1() {
198f4a2713aSLionel Sambuc   new C;
199f4a2713aSLionel Sambuc }
200*0a6a1f1dSLionel Sambuc 
201*0a6a1f1dSLionel Sambuc namespace test10 {
202*0a6a1f1dSLionel Sambuc // Test that if a destructor is in a comdat, we don't try to emit is as an
203*0a6a1f1dSLionel Sambuc // alias to a base class destructor.
204*0a6a1f1dSLionel Sambuc struct bar {
205*0a6a1f1dSLionel Sambuc   ~bar();
206*0a6a1f1dSLionel Sambuc };
~bar()207*0a6a1f1dSLionel Sambuc bar::~bar() {
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc } // closing the namespace causes ~bar to be sent to CodeGen
210*0a6a1f1dSLionel Sambuc namespace test10 {
211*0a6a1f1dSLionel Sambuc template <typename T>
212*0a6a1f1dSLionel Sambuc struct foo : public bar {
213*0a6a1f1dSLionel Sambuc   ~foo();
214*0a6a1f1dSLionel Sambuc };
215*0a6a1f1dSLionel Sambuc template <typename T>
~foo()216*0a6a1f1dSLionel Sambuc foo<T>::~foo() {}
217*0a6a1f1dSLionel Sambuc template class foo<int>;
218*0a6a1f1dSLionel Sambuc // CHECK5: define weak_odr void @_ZN6test103fooIiED2Ev({{.*}} comdat($_ZN6test103fooIiED5Ev)
219*0a6a1f1dSLionel Sambuc }
220*0a6a1f1dSLionel Sambuc 
221*0a6a1f1dSLionel Sambuc namespace test11 {
222*0a6a1f1dSLionel Sambuc // Test that when we don't have to worry about COMDATs we produce an alias
223*0a6a1f1dSLionel Sambuc // from complate to base and from base to base class base.
224*0a6a1f1dSLionel Sambuc struct bar {
225*0a6a1f1dSLionel Sambuc   ~bar();
226*0a6a1f1dSLionel Sambuc };
~bar()227*0a6a1f1dSLionel Sambuc bar::~bar() {}
228*0a6a1f1dSLionel Sambuc struct foo : public bar {
229*0a6a1f1dSLionel Sambuc   ~foo();
230*0a6a1f1dSLionel Sambuc };
~foo()231*0a6a1f1dSLionel Sambuc foo::~foo() {}
232*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test113fooD2Ev = alias {{.*}} @_ZN6test113barD2Ev
233*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test113fooD1Ev = alias {{.*}} @_ZN6test113fooD2Ev
234*0a6a1f1dSLionel Sambuc }
235*0a6a1f1dSLionel Sambuc 
236*0a6a1f1dSLionel Sambuc namespace test12 {
237*0a6a1f1dSLionel Sambuc template <int>
238*0a6a1f1dSLionel Sambuc struct foo {
~footest12::foo239*0a6a1f1dSLionel Sambuc   ~foo() { delete this; }
240*0a6a1f1dSLionel Sambuc };
241*0a6a1f1dSLionel Sambuc 
242*0a6a1f1dSLionel Sambuc template class foo<1>;
243*0a6a1f1dSLionel Sambuc // CHECK6: @_ZN6test123fooILi1EED1Ev = weak_odr alias {{.*}} @_ZN6test123fooILi1EED2Ev
244*0a6a1f1dSLionel Sambuc // CHECK6: define weak_odr void @_ZN6test123fooILi1EED2Ev({{.*}}) {{.*}} comdat($_ZN6test123fooILi1EED5Ev)
245*0a6a1f1dSLionel Sambuc }
246