forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			178 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | 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-LABEL: define linkonce_odr void @_ZN2X02f1Ev
 | |
|   x0->f1();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f2Ev
 | |
|   x0->f2();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f3Ev
 | |
|   x0->f3();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f5Ev
 | |
|   X0::f5();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X02f6Ev
 | |
|   x0->X0::f6();
 | |
|   // CHECK-LABEL: define linkonce_odr void @_ZN2X1IiE2f1Ev
 | |
|   x1->f1();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f2Ev
 | |
|   x1->f2();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f3Ev
 | |
|   x1->f3();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f4Ev
 | |
|   x1->f4();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f5Ev
 | |
|   X1<int>::f5();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X1IiE2f6Ev
 | |
|   x1->X1::f6();
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN2X22f2Ev
 | |
|   x2->f2();
 | |
|   // CHECK-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: define weak_odr void @_ZN5test33zedIfEEvv
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33fooEv
 | |
|   // CHECK-LABEL: define linkonce_odr hidden void @_ZN5test33zedIiEEvv
 | |
| }
 | |
| 
 | |
| namespace test4 {
 | |
|   extern inline __attribute__ ((__gnu_inline__))
 | |
|   void foo() {}
 | |
|   void bar() {
 | |
|     foo();
 | |
|   }
 | |
|   // CHECK-LABEL: define available_externally void @_ZN5test43fooE
 | |
| }
 | |
| 
 | |
| namespace test5 {
 | |
|   // just don't crash.
 | |
|   template <int> inline void Op();
 | |
|   class UnaryInstruction {
 | |
|     UnaryInstruction() {
 | |
|       Op<0>();
 | |
|     }
 | |
|   };
 | |
|   template <int Idx_nocapture> void Op() {
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace test6 {
 | |
|   // just don't crash.
 | |
|   template <typename T>
 | |
|   void f(T x) {
 | |
|   }
 | |
|   struct C {
 | |
|     static void g() {
 | |
|       f([](){});
 | |
|     }
 | |
|   };
 | |
|   void g() {
 | |
|     C::g();
 | |
|   }
 | |
| }
 | |
| 
 | |
| namespace PR34811 {
 | |
|   template <typename T> void tf() {}
 | |
|   
 | |
|   // CHECK-LABEL: define linkonce_odr hidden i8* @_ZN7PR348111fEv(
 | |
|   inline void *f() {
 | |
|     auto l = []() {};
 | |
|     // CHECK-LABEL: define linkonce_odr hidden void @_ZN7PR348112tfIZNS_1fEvEUlvE_EEvv(
 | |
|     return (void *)&tf<decltype(l)>;
 | |
|   }
 | |
|   
 | |
|   void *p = (void *)f;
 | |
| }
 |