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 { |
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-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 | |
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-LABEL: 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-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 { |
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-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__)) |
132 | void foo() {} |
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 { |
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 | |
166 | namespace PR34811 { |
167 | template <typename T> void tf() {} |
168 | |
169 | // CHECK-LABEL: define linkonce_odr hidden i8* @_ZN7PR348111fEv( |
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 | |