1*67e74705SXin Li // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li // The trickery with optimization in the run line is to get IR 4*67e74705SXin Li // generation to emit available_externally function bodies, but not 5*67e74705SXin Li // actually inline them (and thus remove the emitted bodies). 6*67e74705SXin Li 7*67e74705SXin Li struct X0 { f1X08*67e74705SXin Li void __attribute__((visibility("default"))) f1() { } f2X09*67e74705SXin Li void f2() { } 10*67e74705SXin Li void f3(); f5X011*67e74705SXin Li static void f5() { } f6X012*67e74705SXin Li virtual void f6() { } 13*67e74705SXin Li }; 14*67e74705SXin Li f3()15*67e74705SXin Liinline void X0::f3() { } 16*67e74705SXin Li 17*67e74705SXin Li template<typename T> 18*67e74705SXin Li struct X1 { f1X119*67e74705SXin Li void __attribute__((visibility("default"))) f1() { } f2X120*67e74705SXin Li void f2() { } 21*67e74705SXin Li void f3(); 22*67e74705SXin Li void f4(); f5X123*67e74705SXin Li static void f5() { } f6X124*67e74705SXin Li virtual void f6() { } 25*67e74705SXin Li }; 26*67e74705SXin Li 27*67e74705SXin Li template<typename T> f3()28*67e74705SXin Liinline void X1<T>::f3() { } 29*67e74705SXin Li 30*67e74705SXin Li template<> f4()31*67e74705SXin Liinline void X1<int>::f4() { } 32*67e74705SXin Li 33*67e74705SXin Li struct __attribute__((visibility("default"))) X2 { f2X234*67e74705SXin Li void f2() { } 35*67e74705SXin Li }; 36*67e74705SXin Li 37*67e74705SXin Li extern template struct X1<float>; 38*67e74705SXin Li use(X0 * x0,X1<int> * x1,X2 * x2,X1<float> * x3)39*67e74705SXin Livoid use(X0 *x0, X1<int> *x1, X2 *x2, X1<float> *x3) { 40*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN2X02f1Ev 41*67e74705SXin Li x0->f1(); 42*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f2Ev 43*67e74705SXin Li x0->f2(); 44*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f3Ev 45*67e74705SXin Li x0->f3(); 46*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f5Ev 47*67e74705SXin Li X0::f5(); 48*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f6Ev 49*67e74705SXin Li x0->X0::f6(); 50*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @_ZN2X1IiE2f1Ev 51*67e74705SXin Li x1->f1(); 52*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev 53*67e74705SXin Li x1->f2(); 54*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev 55*67e74705SXin Li x1->f3(); 56*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev 57*67e74705SXin Li x1->f4(); 58*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev 59*67e74705SXin Li X1<int>::f5(); 60*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev 61*67e74705SXin Li x1->X1::f6(); 62*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X22f2Ev 63*67e74705SXin Li x2->f2(); 64*67e74705SXin Li // CHECK-LABEL: define available_externally void @_ZN2X1IfE2f2Ev 65*67e74705SXin Li x3->f2(); 66*67e74705SXin Li } 67*67e74705SXin Li 68*67e74705SXin Li // rdar://problem/8614470 69*67e74705SXin Li namespace test1 { 70*67e74705SXin Li struct __attribute__((visibility("default"))) A { 71*67e74705SXin Li inline void foo(); 72*67e74705SXin Li ~A(); 73*67e74705SXin Li }; 74*67e74705SXin Li test()75*67e74705SXin Li void test() { 76*67e74705SXin Li A a; 77*67e74705SXin Li a.foo(); 78*67e74705SXin Li } 79*67e74705SXin Li // CHECK: declare void @_ZN5test11A3fooEv 80*67e74705SXin Li // CHECK: declare {{.*}} @_ZN5test11AD1Ev 81*67e74705SXin Li } 82*67e74705SXin Li 83*67e74705SXin Li // PR8713 84*67e74705SXin Li namespace test2 { 85*67e74705SXin Li struct A {}; 86*67e74705SXin Li template <class T> class B {}; 87*67e74705SXin Li typedef B<A> arg; 88*67e74705SXin Li 89*67e74705SXin Li namespace ns __attribute__((visibility("default"))) { foo()90*67e74705SXin Li template <class T> inline void foo() {} 91*67e74705SXin Li extern template void foo<arg>(); 92*67e74705SXin Li } 93*67e74705SXin Li test()94*67e74705SXin Li void test() { 95*67e74705SXin Li ns::foo<arg>(); 96*67e74705SXin Li } 97*67e74705SXin Li 98*67e74705SXin Li // CHECK-LABEL: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv() 99*67e74705SXin Li } 100*67e74705SXin Li 101*67e74705SXin Li namespace PR11642 { 102*67e74705SXin Li template <typename T> 103*67e74705SXin Li class Foo { 104*67e74705SXin Li public: foo(T x)105*67e74705SXin Li T foo(T x) { return x; } 106*67e74705SXin Li }; 107*67e74705SXin Li extern template class Foo<int>; 108*67e74705SXin Li template class Foo<int>; 109*67e74705SXin Li // CHECK-LABEL: define weak_odr i32 @_ZN7PR116423FooIiE3fooEi 110*67e74705SXin Li } 111*67e74705SXin Li 112*67e74705SXin Li // Test that clang implements the new gcc behaviour for inline functions. 113*67e74705SXin Li // GCC PR30066. 114*67e74705SXin Li namespace test3 { foo(void)115*67e74705SXin Li inline void foo(void) { 116*67e74705SXin Li } 117*67e74705SXin Li template<typename T> zed()118*67e74705SXin Li inline void zed() { 119*67e74705SXin Li } 120*67e74705SXin Li template void zed<float>(); bar(void)121*67e74705SXin Li void bar(void) { 122*67e74705SXin Li foo(); 123*67e74705SXin Li zed<int>(); 124*67e74705SXin Li } 125*67e74705SXin Li // CHECK-LABEL: define weak_odr void @_ZN5test33zedIfEEvv 126*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33fooEv 127*67e74705SXin Li // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33zedIiEEvv 128*67e74705SXin Li } 129*67e74705SXin Li 130*67e74705SXin Li namespace test4 { 131*67e74705SXin Li extern inline __attribute__ ((__gnu_inline__)) foo()132*67e74705SXin Li void foo() {} bar()133*67e74705SXin Li void bar() { 134*67e74705SXin Li foo(); 135*67e74705SXin Li } 136*67e74705SXin Li // CHECK-LABEL: define available_externally void @_ZN5test43fooE 137*67e74705SXin Li } 138*67e74705SXin Li 139*67e74705SXin Li namespace test5 { 140*67e74705SXin Li // just don't crash. 141*67e74705SXin Li template <int> inline void Op(); 142*67e74705SXin Li class UnaryInstruction { UnaryInstruction()143*67e74705SXin Li UnaryInstruction() { 144*67e74705SXin Li Op<0>(); 145*67e74705SXin Li } 146*67e74705SXin Li }; Op()147*67e74705SXin Li template <int Idx_nocapture> void Op() { 148*67e74705SXin Li } 149*67e74705SXin Li } 150*67e74705SXin Li 151*67e74705SXin Li namespace test6 { 152*67e74705SXin Li // just don't crash. 153*67e74705SXin Li template <typename T> f(T x)154*67e74705SXin Li void f(T x) { 155*67e74705SXin Li } 156*67e74705SXin Li struct C { gtest6::C157*67e74705SXin Li static void g() { 158*67e74705SXin Li f([](){}); 159*67e74705SXin Li } 160*67e74705SXin Li }; g()161*67e74705SXin Li void g() { 162*67e74705SXin Li C::g(); 163*67e74705SXin Li } 164*67e74705SXin Li } 165