blob: 2bb13485e922bf638f53cef6a82735877cf4d7f3 [file] [log] [blame]
// RUN: %clang_cc1 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s
// The trickery with optimization in the run line is to get IR
// generation to emit available_externally function bodies, but not
// actually inline them (and thus remove the emitted bodies).
struct X0 {
void __attribute__((visibility("default"))) f1() { }
void f2() { }
void f3();
static void f5() { }
virtual void f6() { }
};
inline void X0::f3() { }
template<typename T>
struct X1 {
void __attribute__((visibility("default"))) f1() { }
void f2() { }
void f3();
void f4();
static void f5() { }
virtual void f6() { }
};
template<typename T>
inline void X1<T>::f3() { }
template<>
inline void X1<int>::f4() { }
struct __attribute__((visibility("default"))) X2 {
void f2() { }
};
extern template struct X1<float>;
void use(X0 *x0, X1<int> *x1, X2 *x2, X1<float> *x3) {
// CHECK: define linkonce_odr void @_ZN2X02f1Ev
x0->f1();
// CHECK: define linkonce_odr hidden void @_ZN2X02f2Ev
x0->f2();
// CHECK: define linkonce_odr hidden void @_ZN2X02f3Ev
x0->f3();
// CHECK: define linkonce_odr hidden void @_ZN2X02f5Ev
X0::f5();
// CHECK: define linkonce_odr hidden void @_ZN2X02f6Ev
x0->X0::f6();
// CHECK: define linkonce_odr void @_ZN2X1IiE2f1Ev
x1->f1();
// CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev
x1->f2();
// CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev
x1->f3();
// CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev
x1->f4();
// CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev
X1<int>::f5();
// CHECK: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev
x1->X1::f6();
// CHECK: define linkonce_odr hidden void @_ZN2X22f2Ev
x2->f2();
// CHECK: define available_externally void @_ZN2X1IfE2f2Ev
x3->f2();
}
// rdar://problem/8614470
namespace test1 {
struct __attribute__((visibility("default"))) A {
inline void foo();
~A();
};
void test() {
A a;
a.foo();
}
// CHECK: declare void @_ZN5test11A3fooEv
// CHECK: declare {{.*}} @_ZN5test11AD1Ev
}
// PR8713
namespace test2 {
struct A {};
template <class T> class B {};
typedef B<A> arg;
namespace ns __attribute__((visibility("default"))) {
template <class T> inline void foo() {}
extern template void foo<arg>();
}
void test() {
ns::foo<arg>();
}
// CHECK: define available_externally void @_ZN5test22ns3fooINS_1BINS_1AEEEEEvv()
}
namespace PR11642 {
template <typename T>
class Foo {
public:
T foo(T x) { return x; }
};
extern template class Foo<int>;
template class Foo<int>;
// CHECK: define weak_odr i32 @_ZN7PR116423FooIiE3fooEi
}
// Test that clang implements the new gcc behaviour for inline functions.
// GCC PR30066.
namespace test3 {
inline void foo(void) {
}
template<typename T>
inline void zed() {
}
template void zed<float>();
void bar(void) {
foo();
zed<int>();
}
// CHECK: define weak_odr void @_ZN5test33zedIfEEvv
// CHECK: define linkonce_odr hidden void @_ZN5test33fooEv
// CHECK: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
}