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