1 // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | 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