template-instantiation.cpp revision e4d645cbe073042d8abc1a4eb600af4ff7a8dffb
1// RUN: %clang_cc1 %s -O1 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
2
3// CHECK: @_ZN7PR100011xE = global
4// CHECK-NOT: @_ZN7PR100014kBarE = external global i32
5//
6// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant
7// CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE
8// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant
9
10// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32]
11// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A
12
13// CHECK-NOT: _ZTVN5test31SIiEE
14// CHECK-NOT: _ZTSN5test31SIiEE
15
16// CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* nocapture %this) unnamed_addr
17// CHECK: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_(
18// CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd(
19
20namespace test0 {
21  struct  basic_streambuf   {
22    virtual       ~basic_streambuf();
23  };
24  template<typename _CharT >
25  struct stdio_sync_filebuf : public basic_streambuf {
26    virtual void      xsgetn();
27  };
28
29  // This specialization should cause the vtable to be emitted, even with
30  // the following extern template declaration.
31  template<> void stdio_sync_filebuf<wchar_t>::xsgetn()  {
32  }
33  extern template class stdio_sync_filebuf<wchar_t>;
34}
35
36namespace test1 {
37  struct  basic_streambuf   {
38    virtual       ~basic_streambuf();
39  };
40  template<typename _CharT >
41  struct stdio_sync_filebuf : public basic_streambuf {
42    virtual void      xsgetn();
43  };
44
45  // Just a declaration should not force the vtable to be emitted.
46  template<> void stdio_sync_filebuf<wchar_t>::xsgetn();
47}
48
49namespace test2 {
50  template<typename T1>
51  class C {
52  public:
53    virtual ~C();
54    void zedbar(double) {
55    }
56    template<typename T2>
57    void foobar(T2 foo) {
58    }
59  };
60  extern template class C<int>;
61  void g() {
62    // The extern template declaration should not prevent us from producing
63    // the implicit constructor (test at the top).
64    C<int> a;
65
66    // or foobar(test at the top).
67    a.foobar(0.0);
68
69    // But it should prevent zebbar
70    // (test at the top).
71    a.zedbar(0.0);
72  }
73}
74
75namespace test3 {
76  template<typename T>
77  class basic_fstreamXX  {
78    virtual void foo(){}
79    virtual void is_open() const  { }
80  };
81
82  extern template class basic_fstreamXX<char>;
83  // This template instantiation should not cause us to produce a vtable.
84  // (test at the top).
85  template void basic_fstreamXX<char>::is_open() const;
86}
87
88namespace test3 {
89  template <typename T>
90  struct S  {
91      virtual void m();
92  };
93
94  template<typename T>
95  void S<T>::m() { }
96
97  // Should not cause us to produce vtable because template instantiations
98  // don't have key functions.
99  template void S<int>::m();
100}
101
102namespace test4 {
103  template <class T> struct A { static void foo(); };
104
105  class B {
106    template <class T> friend void A<T>::foo();
107    B();
108  };
109
110  template <class T> void A<T>::foo() {
111    B b;
112  }
113
114  unsigned test() {
115    A<int>::foo();
116  }
117}
118
119namespace PR8505 {
120// Hits an assertion due to bogus instantiation of class B.
121template <int i> class A {
122  class B* g;
123};
124class B {
125  void f () {}
126};
127// Should not instantiate class B since it is introduced in namespace scope.
128// CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv
129template class A<0>;
130}
131
132// Ensure that when instantiating initializers for static data members to
133// complete their type in an unevaluated context, we *do* emit initializers with
134// side-effects, but *don't* emit initializers and variables which are otherwise
135// unused in the program.
136namespace PR10001 {
137  template <typename T> struct S {
138    static const int arr[];
139    static const int arr2[];
140    static const int x, y;
141    static int f();
142  };
143
144  extern int foo();
145  extern int kBar;
146
147  template <typename T> const int S<T>::arr[] = { 1, 2, foo() }; // possible side effects
148  template <typename T> const int S<T>::arr2[] = { 1, 2, kBar }; // no side effects
149  template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
150  template <typename T> const int S<T>::y = sizeof(arr2) / sizeof(arr2[0]);
151  template <typename T> int S<T>::f() { return x + y; }
152
153  int x = S<int>::f();
154}
155