// RUN: %clang_cc1 %s -O1 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK: @_ZN7PR100011xE = global // CHECK-NOT: @_ZN7PR100014kBarE = external global i32 // // CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant // CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE // CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant // CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32] // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A // CHECK-NOT: _ZTVN5test31SIiEE // CHECK-NOT: _ZTSN5test31SIiEE // CHECK: define linkonce_odr void @_ZN5test21CIiEC1Ev(%"class.test2::C"* nocapture %this) unnamed_addr // CHECK: define linkonce_odr void @_ZN5test21CIiE6foobarIdEEvT_( // CHECK: define available_externally void @_ZN5test21CIiE6zedbarEd( // CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi1EEE() // CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi2EEE() // CHECK: define linkonce_odr void @_ZN7PR106662g1ENS_1SILi3EEE() // CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi1EEE() // CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi2EEE() // CHECK: define linkonce_odr void @_ZN7PR106662g2ENS_1SILi3EEE() // CHECK: declare void @_ZN7PR106662h1ENS_1SILi1EEE() // CHECK: declare void @_ZN7PR106662h1ENS_1SILi2EEE() // CHECK: declare void @_ZN7PR106662h1ENS_1SILi3EEE() // CHECK: declare void @_ZN7PR106662h2ENS_1SILi1EEE() // CHECK: declare void @_ZN7PR106662h2ENS_1SILi2EEE() // CHECK: declare void @_ZN7PR106662h2ENS_1SILi3EEE() namespace test0 { struct basic_streambuf { virtual ~basic_streambuf(); }; template struct stdio_sync_filebuf : public basic_streambuf { virtual void xsgetn(); }; // This specialization should cause the vtable to be emitted, even with // the following extern template declaration. template<> void stdio_sync_filebuf::xsgetn() { } extern template class stdio_sync_filebuf; } namespace test1 { struct basic_streambuf { virtual ~basic_streambuf(); }; template struct stdio_sync_filebuf : public basic_streambuf { virtual void xsgetn(); }; // Just a declaration should not force the vtable to be emitted. template<> void stdio_sync_filebuf::xsgetn(); } namespace test2 { template class C { public: virtual ~C(); void zedbar(double) { } template void foobar(T2 foo) { } }; extern template class C; void g() { // The extern template declaration should not prevent us from producing // the implicit constructor (test at the top). C a; // or foobar(test at the top). a.foobar(0.0); // But it should prevent zebbar // (test at the top). a.zedbar(0.0); } } namespace test3 { template class basic_fstreamXX { virtual void foo(){} virtual void is_open() const { } }; extern template class basic_fstreamXX; // This template instantiation should not cause us to produce a vtable. // (test at the top). template void basic_fstreamXX::is_open() const; } namespace test3 { template struct S { virtual void m(); }; template void S::m() { } // Should not cause us to produce vtable because template instantiations // don't have key functions. template void S::m(); } namespace test4 { template struct A { static void foo(); }; class B { template friend void A::foo(); B(); }; template void A::foo() { B b; } unsigned test() { A::foo(); } } namespace PR8505 { // Hits an assertion due to bogus instantiation of class B. template class A { class B* g; }; class B { void f () {} }; // Should not instantiate class B since it is introduced in namespace scope. // CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv template class A<0>; } // Ensure that when instantiating initializers for static data members to // complete their type in an unevaluated context, we *do* emit initializers with // side-effects, but *don't* emit initializers and variables which are otherwise // unused in the program. namespace PR10001 { template struct S { static const int arr[]; static const int arr2[]; static const int x, y; static int f(); }; extern int foo(); extern int kBar; template const int S::arr[] = { 1, 2, foo() }; // possible side effects template const int S::arr2[] = { 1, 2, kBar }; // no side effects template const int S::x = sizeof(arr) / sizeof(arr[0]); template const int S::y = sizeof(arr2) / sizeof(arr2[0]); template int S::f() { return x + y; } int x = S::f(); } // Ensure that definitions are emitted for all friend functions defined within // class templates. Order of declaration is extremely important here. Different // instantiations of the class happen at different points during the deferred // method body parsing and afterward. Those different points of instantiation // change the exact form the class template appears to have. namespace PR10666 { template struct S { void f1() { S<1> s; } friend void g1(S s) {} friend void h1(S s); void f2() { S<2> s; } friend void g2(S s) {} friend void h2(S s); void f3() { S<3> s; } }; void test(S<1> s1, S<2> s2, S<3> s3) { g1(s1); g1(s2); g1(s3); g2(s1); g2(s2); g2(s3); h1(s1); h1(s2); h1(s3); h2(s1); h2(s2); h2(s3); } }