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