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