xref: /aosp_15_r20/external/clang/test/CodeGenCXX/template-instantiation.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li // CHECK: @_ZN7PR100011xE = global
4*67e74705SXin Li // CHECK-NOT: @_ZN7PR100014kBarE = external global i32
5*67e74705SXin Li //
6*67e74705SXin Li // CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant
7*67e74705SXin Li // CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE
8*67e74705SXin Li // CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA1_iEE
9*67e74705SXin Li // CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE
10*67e74705SXin Li // CHECK:     @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant
11*67e74705SXin Li 
12*67e74705SXin Li // CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
13*67e74705SXin Li // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
14*67e74705SXin Li 
15*67e74705SXin Li // CHECK:     @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
16*67e74705SXin Li 
17*67e74705SXin Li // CHECK-NOT: _ZTVN5test31SIiEE
18*67e74705SXin Li // CHECK-NOT: _ZTSN5test31SIiEE
19*67e74705SXin Li 
20*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* %this) unnamed_addr
21*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_(
22*67e74705SXin Li // CHECK-LABEL: define available_externally void @_ZN5test21CIiE6zedbarEd(
23*67e74705SXin Li 
24*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi1EEE()
25*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi2EEE()
26*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi3EEE()
27*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi1EEE()
28*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi2EEE()
29*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi3EEE()
30*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h1ENS_1SILi1EEE()
31*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h1ENS_1SILi2EEE()
32*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h1ENS_1SILi3EEE()
33*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h2ENS_1SILi1EEE()
34*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h2ENS_1SILi2EEE()
35*67e74705SXin Li // CHECK: declare void @_ZN7PR106662h2ENS_1SILi3EEE()
36*67e74705SXin Li 
37*67e74705SXin Li namespace test0 {
38*67e74705SXin Li   struct  basic_streambuf   {
39*67e74705SXin Li     virtual       ~basic_streambuf();
40*67e74705SXin Li   };
41*67e74705SXin Li   template<typename _CharT >
42*67e74705SXin Li   struct stdio_sync_filebuf : public basic_streambuf {
43*67e74705SXin Li     virtual void      xsgetn();
44*67e74705SXin Li   };
45*67e74705SXin Li 
46*67e74705SXin Li   // This specialization is not a key function, so doesn't cause the vtable to
47*67e74705SXin Li   // be instantiated unless we're instantiating a class definition anyway.
xsgetn()48*67e74705SXin Li   template<> void stdio_sync_filebuf<int[1]>::xsgetn()  {
49*67e74705SXin Li   }
xsgetn()50*67e74705SXin Li   template<> void stdio_sync_filebuf<int[2]>::xsgetn()  {
51*67e74705SXin Li   }
xsgetn()52*67e74705SXin Li   template<> void stdio_sync_filebuf<int[3]>::xsgetn()  {
53*67e74705SXin Li   }
xsgetn()54*67e74705SXin Li   template<> void stdio_sync_filebuf<int[4]>::xsgetn()  {
55*67e74705SXin Li   }
56*67e74705SXin Li   extern template class stdio_sync_filebuf<int[2]>;
57*67e74705SXin Li 
58*67e74705SXin Li   // These two both cause vtables to be emitted.
59*67e74705SXin Li   template class stdio_sync_filebuf<int[3]>;
60*67e74705SXin Li   stdio_sync_filebuf<int[4]> implicit_instantiation;
61*67e74705SXin Li }
62*67e74705SXin Li 
63*67e74705SXin Li namespace test1 {
64*67e74705SXin Li   struct  basic_streambuf   {
65*67e74705SXin Li     virtual       ~basic_streambuf();
66*67e74705SXin Li   };
67*67e74705SXin Li   template<typename _CharT >
68*67e74705SXin Li   struct stdio_sync_filebuf : public basic_streambuf {
69*67e74705SXin Li     virtual void      xsgetn();
70*67e74705SXin Li   };
71*67e74705SXin Li 
72*67e74705SXin Li   // Just a declaration should not force the vtable to be emitted.
73*67e74705SXin Li   template<> void stdio_sync_filebuf<wchar_t>::xsgetn();
74*67e74705SXin Li }
75*67e74705SXin Li 
76*67e74705SXin Li namespace test2 {
77*67e74705SXin Li   template<typename T1>
78*67e74705SXin Li   class C {
79*67e74705SXin Li   public:
80*67e74705SXin Li     virtual ~C();
zedbar(double)81*67e74705SXin Li     void zedbar(double) {
82*67e74705SXin Li     }
83*67e74705SXin Li     template<typename T2>
foobar(T2 foo)84*67e74705SXin Li     void foobar(T2 foo) {
85*67e74705SXin Li     }
86*67e74705SXin Li   };
87*67e74705SXin Li   extern template class C<int>;
g()88*67e74705SXin Li   void g() {
89*67e74705SXin Li     // The extern template declaration should not prevent us from producing
90*67e74705SXin Li     // the implicit constructor (test at the top).
91*67e74705SXin Li     C<int> a;
92*67e74705SXin Li 
93*67e74705SXin Li     // or foobar(test at the top).
94*67e74705SXin Li     a.foobar(0.0);
95*67e74705SXin Li 
96*67e74705SXin Li     // But it should prevent zebbar
97*67e74705SXin Li     // (test at the top).
98*67e74705SXin Li     a.zedbar(0.0);
99*67e74705SXin Li   }
100*67e74705SXin Li }
101*67e74705SXin Li 
102*67e74705SXin Li namespace test3 {
103*67e74705SXin Li   template<typename T>
104*67e74705SXin Li   class basic_fstreamXX  {
foo()105*67e74705SXin Li     virtual void foo(){}
is_open() const106*67e74705SXin Li     virtual void is_open() const  { }
107*67e74705SXin Li   };
108*67e74705SXin Li 
109*67e74705SXin Li   extern template class basic_fstreamXX<char>;
110*67e74705SXin Li   // This template instantiation should not cause us to produce a vtable.
111*67e74705SXin Li   // (test at the top).
112*67e74705SXin Li   template void basic_fstreamXX<char>::is_open() const;
113*67e74705SXin Li }
114*67e74705SXin Li 
115*67e74705SXin Li namespace test3 {
116*67e74705SXin Li   template <typename T>
117*67e74705SXin Li   struct S  {
118*67e74705SXin Li       virtual void m();
119*67e74705SXin Li   };
120*67e74705SXin Li 
121*67e74705SXin Li   template<typename T>
m()122*67e74705SXin Li   void S<T>::m() { }
123*67e74705SXin Li 
124*67e74705SXin Li   // Should not cause us to produce vtable because template instantiations
125*67e74705SXin Li   // don't have key functions.
126*67e74705SXin Li   template void S<int>::m();
127*67e74705SXin Li }
128*67e74705SXin Li 
129*67e74705SXin Li namespace test4 {
130*67e74705SXin Li   template <class T> struct A { static void foo(); };
131*67e74705SXin Li 
132*67e74705SXin Li   class B {
133*67e74705SXin Li     template <class T> friend void A<T>::foo();
134*67e74705SXin Li     B();
135*67e74705SXin Li   };
136*67e74705SXin Li 
foo()137*67e74705SXin Li   template <class T> void A<T>::foo() {
138*67e74705SXin Li     B b;
139*67e74705SXin Li   }
140*67e74705SXin Li 
test()141*67e74705SXin Li   unsigned test() {
142*67e74705SXin Li     A<int>::foo();
143*67e74705SXin Li   }
144*67e74705SXin Li }
145*67e74705SXin Li 
146*67e74705SXin Li namespace PR8505 {
147*67e74705SXin Li // Hits an assertion due to bogus instantiation of class B.
148*67e74705SXin Li template <int i> class A {
149*67e74705SXin Li   class B* g;
150*67e74705SXin Li };
151*67e74705SXin Li class B {
f()152*67e74705SXin Li   void f () {}
153*67e74705SXin Li };
154*67e74705SXin Li // Should not instantiate class B since it is introduced in namespace scope.
155*67e74705SXin Li // CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv
156*67e74705SXin Li template class A<0>;
157*67e74705SXin Li }
158*67e74705SXin Li 
159*67e74705SXin Li // Ensure that when instantiating initializers for static data members to
160*67e74705SXin Li // complete their type in an unevaluated context, we *do* emit initializers with
161*67e74705SXin Li // side-effects, but *don't* emit initializers and variables which are otherwise
162*67e74705SXin Li // unused in the program.
163*67e74705SXin Li namespace PR10001 {
164*67e74705SXin Li   template <typename T> struct S {
165*67e74705SXin Li     static const int arr[];
166*67e74705SXin Li     static const int arr2[];
167*67e74705SXin Li     static const int x, y;
168*67e74705SXin Li     static int f();
169*67e74705SXin Li   };
170*67e74705SXin Li 
171*67e74705SXin Li   extern int foo();
172*67e74705SXin Li   extern int kBar;
173*67e74705SXin Li 
174*67e74705SXin Li   template <typename T> const int S<T>::arr[] = { 1, 2, foo() }; // possible side effects
175*67e74705SXin Li   template <typename T> const int S<T>::arr2[] = { 1, 2, kBar }; // no side effects
176*67e74705SXin Li   template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
177*67e74705SXin Li   template <typename T> const int S<T>::y = sizeof(arr2) / sizeof(arr2[0]);
f()178*67e74705SXin Li   template <typename T> int S<T>::f() { return x + y; }
179*67e74705SXin Li 
180*67e74705SXin Li   int x = S<int>::f();
181*67e74705SXin Li }
182*67e74705SXin Li 
183*67e74705SXin Li // Ensure that definitions are emitted for all friend functions defined within
184*67e74705SXin Li // class templates. Order of declaration is extremely important here. Different
185*67e74705SXin Li // instantiations of the class happen at different points during the deferred
186*67e74705SXin Li // method body parsing and afterward. Those different points of instantiation
187*67e74705SXin Li // change the exact form the class template appears to have.
188*67e74705SXin Li namespace PR10666 {
189*67e74705SXin Li   template <int N> struct S {
f1PR10666::S190*67e74705SXin Li     void f1() { S<1> s; }
g1(S s)191*67e74705SXin Li     friend void g1(S s) {}
192*67e74705SXin Li     friend void h1(S s);
f2PR10666::S193*67e74705SXin Li     void f2() { S<2> s; }
g2(S s)194*67e74705SXin Li     friend void g2(S s) {}
195*67e74705SXin Li     friend void h2(S s);
f3PR10666::S196*67e74705SXin Li     void f3() { S<3> s; }
197*67e74705SXin Li   };
test(S<1> s1,S<2> s2,S<3> s3)198*67e74705SXin Li   void test(S<1> s1, S<2> s2, S<3> s3) {
199*67e74705SXin Li     g1(s1); g1(s2); g1(s3);
200*67e74705SXin Li     g2(s1); g2(s2); g2(s3);
201*67e74705SXin Li     h1(s1); h1(s2); h1(s3);
202*67e74705SXin Li     h2(s1); h2(s2); h2(s3);
203*67e74705SXin Li   }
204*67e74705SXin Li }
205