xref: /llvm-project/clang/test/CodeGenCXX/visibility-inlines-hidden.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
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 namespace test1 {
69   struct __attribute__((visibility("default"))) A {
70     inline void foo();
71     ~A();
72   };
73 
test()74   void test() {
75     A a;
76     a.foo();
77   }
78 // CHECK: declare void @_ZN5test11A3fooEv
79 // CHECK: declare {{.*}} @_ZN5test11AD1Ev
80 }
81 
82 // PR8713
83 namespace test2 {
84   struct A {};
85   template <class T> class B {};
86   typedef B<A> arg;
87 
88   namespace ns __attribute__((visibility("default"))) {
foo()89     template <class T> inline void foo() {}
90     extern template void foo<arg>();
91   }
92 
test()93   void test() {
94     ns::foo<arg>();
95   }
96 
97   // CHECK-LABEL: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv()
98 }
99 
100 namespace PR11642 {
101   template <typename T>
102   class Foo {
103   public:
foo(T x)104     T foo(T x) { return x; }
105   };
106   extern template class Foo<int>;
107   template class Foo<int>;
108   // CHECK-LABEL: define weak_odr noundef i32 @_ZN7PR116423FooIiE3fooEi
109 }
110 
111 // Test that clang implements the new gcc behaviour for inline functions.
112 // GCC PR30066.
113 namespace test3 {
foo(void)114   inline void foo(void) {
115   }
116   template<typename T>
zed()117   inline void zed() {
118   }
119   template void zed<float>();
bar(void)120   void bar(void) {
121     foo();
122     zed<int>();
123   }
124   // CHECK-LABEL: define weak_odr void @_ZN5test33zedIfEEvv
125   // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33fooEv
126   // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
127 }
128 
129 namespace test4 {
130   extern inline __attribute__ ((__gnu_inline__))
foo()131   void foo() {}
bar()132   void bar() {
133     foo();
134   }
135   // CHECK-LABEL: define available_externally void @_ZN5test43fooE
136 }
137 
138 namespace test5 {
139   // just don't crash.
140   template <int> inline void Op();
141   class UnaryInstruction {
UnaryInstruction()142     UnaryInstruction() {
143       Op<0>();
144     }
145   };
Op()146   template <int Idx_nocapture> void Op() {
147   }
148 }
149 
150 namespace test6 {
151   // just don't crash.
152   template <typename T>
f(T x)153   void f(T x) {
154   }
155   struct C {
gtest6::C156     static void g() {
157       f([](){});
158     }
159   };
g()160   void g() {
161     C::g();
162   }
163 }
164 
165 namespace PR34811 {
tf()166   template <typename T> void tf() {}
167 
168   // CHECK-LABEL: define linkonce_odr hidden noundef ptr @_ZN7PR348111fEv(
f()169   inline void *f() {
170     auto l = []() {};
171     // CHECK-LABEL: define linkonce_odr hidden void @_ZN7PR348112tfIZNS_1fEvEUlvE_EEvv(
172     return (void *)&tf<decltype(l)>;
173   }
174 
175   void *p = (void *)f;
176 }
177