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
7struct X0 {
8  void __attribute__((visibility("default"))) f1() { }
9  void f2() { }
10  void f3();
11  static void f5() { }
12  virtual void f6() { }
13};
14
15inline void X0::f3() { }
16
17template<typename T>
18struct 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
27template<typename T>
28inline void X1<T>::f3() { }
29
30template<>
31inline void X1<int>::f4() { }
32
33struct __attribute__((visibility("default"))) X2 {
34  void f2() { }
35};
36
37extern template struct X1<float>;
38
39void 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
69namespace 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
84namespace 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
101namespace 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.
114namespace 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
130namespace 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
139namespace 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
151namespace 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