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