Clang Project

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