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