1 // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | 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 {
f1X08 void __attribute__((visibility("default"))) f1() { }
f2X09 void f2() { }
10 void f3();
f5X011 static void f5() { }
f6X012 virtual void f6() { }
13 };
14
f3()15 inline void X0::f3() { }
16
17 template<typename T>
18 struct X1 {
f1X119 void __attribute__((visibility("default"))) f1() { }
f2X120 void f2() { }
21 void f3();
22 void f4();
f5X123 static void f5() { }
f6X124 virtual void f6() { }
25 };
26
27 template<typename T>
f3()28 inline void X1<T>::f3() { }
29
30 template<>
f4()31 inline void X1<int>::f4() { }
32
33 struct __attribute__((visibility("default"))) X2 {
f2X234 void f2() { }
35 };
36
37 extern template struct X1<float>;
38
use(X0 * x0,X1<int> * x1,X2 * x2,X1<float> * x3)39 void use(X0 *x0, X1<int> *x1, X2 *x2, X1<float> *x3) {
40 // CHECK-LABEL: define linkonce_odr void @_ZN2X02f1Ev
41 x0->f1();
42 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f2Ev
43 x0->f2();
44 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f3Ev
45 x0->f3();
46 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f5Ev
47 X0::f5();
48 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f6Ev
49 x0->X0::f6();
50 // CHECK-LABEL: define linkonce_odr void @_ZN2X1IiE2f1Ev
51 x1->f1();
52 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev
53 x1->f2();
54 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev
55 x1->f3();
56 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev
57 x1->f4();
58 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev
59 X1<int>::f5();
60 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev
61 x1->X1::f6();
62 // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X22f2Ev
63 x2->f2();
64 // CHECK-LABEL: 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
test()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"))) {
foo()90 template <class T> inline void foo() {}
91 extern template void foo<arg>();
92 }
93
test()94 void test() {
95 ns::foo<arg>();
96 }
97
98 // CHECK-LABEL: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv()
99 }
100
101 namespace PR11642 {
102 template <typename T>
103 class Foo {
104 public:
foo(T x)105 T foo(T x) { return x; }
106 };
107 extern template class Foo<int>;
108 template class Foo<int>;
109 // CHECK-LABEL: 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 {
foo(void)115 inline void foo(void) {
116 }
117 template<typename T>
zed()118 inline void zed() {
119 }
120 template void zed<float>();
bar(void)121 void bar(void) {
122 foo();
123 zed<int>();
124 }
125 // CHECK-LABEL: define weak_odr void @_ZN5test33zedIfEEvv
126 // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33fooEv
127 // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
128 }
129
130 namespace test4 {
131 extern inline __attribute__ ((__gnu_inline__))
foo()132 void foo() {}
bar()133 void bar() {
134 foo();
135 }
136 // CHECK-LABEL: define available_externally void @_ZN5test43fooE
137 }
138
139 namespace test5 {
140 // just don't crash.
141 template <int> inline void Op();
142 class UnaryInstruction {
UnaryInstruction()143 UnaryInstruction() {
144 Op<0>();
145 }
146 };
Op()147 template <int Idx_nocapture> void Op() {
148 }
149 }
150
151 namespace test6 {
152 // just don't crash.
153 template <typename T>
f(T x)154 void f(T x) {
155 }
156 struct C {
gtest6::C157 static void g() {
158 f([](){});
159 }
160 };
g()161 void g() {
162 C::g();
163 }
164 }
165
166 namespace PR34811 {
tf()167 template <typename T> void tf() {}
168
169 // CHECK-LABEL: define linkonce_odr hidden i8* @_ZN7PR348111fEv(
f()170 inline void *f() {
171 auto l = []() {};
172 // CHECK-LABEL: define linkonce_odr hidden void @_ZN7PR348112tfIZNS_1fEvEUlvE_EEvv(
173 return (void *)&tf<decltype(l)>;
174 }
175
176 void *p = (void *)f;
177 }
178