forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			165 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -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-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();
 | 
						|
  }
 | 
						|
}
 |