forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			394 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			394 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t
 | 
						|
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-optzns -emit-llvm -o %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST8 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST9 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST10 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST11 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST12 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST13 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
 | 
						|
// RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
 | 
						|
 | 
						|
#include <typeinfo>
 | 
						|
 | 
						|
// CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant
 | 
						|
namespace Test1 {
 | 
						|
 | 
						|
struct A {
 | 
						|
  A();
 | 
						|
  virtual void f();
 | 
						|
  virtual ~A() { }
 | 
						|
};
 | 
						|
 | 
						|
A::A() { }
 | 
						|
 | 
						|
void f(A* a) {
 | 
						|
  a->f();
 | 
						|
};
 | 
						|
 | 
						|
// CHECK-LABEL: define void @_ZN5Test11gEv
 | 
						|
// CHECK: call void @_ZN5Test11A1fEv
 | 
						|
void g() {
 | 
						|
  A a;
 | 
						|
  f(&a);
 | 
						|
}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// Test2::A's key function (f) is defined in this translation unit, but when
 | 
						|
// we're doing codegen for the typeid(A) call, we don't know that yet.
 | 
						|
// This tests mainly that the typeinfo and typename constants have their linkage
 | 
						|
// updated correctly.
 | 
						|
 | 
						|
// CHECK-TEST2: @_ZTSN5Test21AE = constant
 | 
						|
// CHECK-TEST2: @_ZTIN5Test21AE = constant
 | 
						|
// CHECK-TEST2: @_ZTVN5Test21AE = unnamed_addr constant
 | 
						|
namespace Test2 {
 | 
						|
  struct A {
 | 
						|
    virtual void f();
 | 
						|
  };
 | 
						|
 | 
						|
  const std::type_info &g() {
 | 
						|
    return typeid(A);
 | 
						|
  };
 | 
						|
 | 
						|
  void A::f() { }
 | 
						|
}
 | 
						|
 | 
						|
// Test that we don't assert on this test.
 | 
						|
namespace Test3 {
 | 
						|
 | 
						|
struct A {
 | 
						|
  virtual void f();
 | 
						|
  virtual ~A() { }
 | 
						|
};
 | 
						|
 | 
						|
struct B : A {
 | 
						|
  B();
 | 
						|
  virtual void f();
 | 
						|
};
 | 
						|
 | 
						|
B::B() { }
 | 
						|
 | 
						|
void g(A* a) {
 | 
						|
  a->f();
 | 
						|
};
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// PR9114, test that we don't try to instantiate RefPtr<Node>.
 | 
						|
namespace Test4 {
 | 
						|
 | 
						|
template <class T> struct RefPtr {
 | 
						|
  T* p;
 | 
						|
  ~RefPtr() {
 | 
						|
    p->deref();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
struct A {
 | 
						|
  virtual ~A();
 | 
						|
};
 | 
						|
 | 
						|
struct Node;
 | 
						|
 | 
						|
struct B : A {
 | 
						|
  virtual void deref();
 | 
						|
  RefPtr<Node> m;
 | 
						|
};
 | 
						|
 | 
						|
void f() {
 | 
						|
  RefPtr<B> b;
 | 
						|
}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// PR9130, test that we emit a definition of A::f.
 | 
						|
// CHECK-TEST5-LABEL: define linkonce_odr void @_ZN5Test51A1fEv
 | 
						|
namespace Test5 {
 | 
						|
 | 
						|
struct A {
 | 
						|
  virtual void f() { }
 | 
						|
};
 | 
						|
 | 
						|
struct B : A { 
 | 
						|
  virtual ~B();
 | 
						|
};
 | 
						|
 | 
						|
B::~B() { }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// Check that we don't assert on this test.
 | 
						|
namespace Test6 {
 | 
						|
 | 
						|
struct A {
 | 
						|
  virtual ~A();
 | 
						|
  int a;
 | 
						|
};
 | 
						|
 | 
						|
struct B {
 | 
						|
  virtual ~B();
 | 
						|
  int b;
 | 
						|
};
 | 
						|
 | 
						|
struct C : A, B { 
 | 
						|
  C();
 | 
						|
};
 | 
						|
 | 
						|
struct D : C {
 | 
						|
  virtual void f();
 | 
						|
  D();
 | 
						|
};
 | 
						|
 | 
						|
D::D() { }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
namespace Test7 {
 | 
						|
 | 
						|
struct c1 {};
 | 
						|
struct c10 : c1{
 | 
						|
  virtual void foo ();
 | 
						|
};
 | 
						|
struct c11 : c10, c1{
 | 
						|
  virtual void f6 ();
 | 
						|
};
 | 
						|
struct c28 : virtual c11{
 | 
						|
  void f6 ();
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
namespace Test8 {
 | 
						|
// CHECK-TEST8: @_ZTVN5Test81YE = available_externally unnamed_addr constant
 | 
						|
// vtable for X is not generated because there are no stores here
 | 
						|
struct X {
 | 
						|
  X();
 | 
						|
  virtual void foo();
 | 
						|
};
 | 
						|
struct Y : X {
 | 
						|
  void foo();
 | 
						|
};
 | 
						|
 | 
						|
void g(X* p) { p->foo(); }
 | 
						|
void f() {
 | 
						|
  Y y;
 | 
						|
  g(&y);
 | 
						|
  X x;
 | 
						|
  g(&x);
 | 
						|
}
 | 
						|
 | 
						|
}  // Test8
 | 
						|
 | 
						|
namespace Test9 {
 | 
						|
// All virtual functions are outline, so we can assume that it will
 | 
						|
// be generated in translation unit where foo is defined.
 | 
						|
// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant
 | 
						|
// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant
 | 
						|
struct A {
 | 
						|
  virtual void foo();
 | 
						|
  virtual void bar();
 | 
						|
};
 | 
						|
void A::bar() {}
 | 
						|
 | 
						|
struct B : A {
 | 
						|
  void foo();
 | 
						|
};
 | 
						|
 | 
						|
void g() {
 | 
						|
  A a;
 | 
						|
  a.foo();
 | 
						|
  B b;
 | 
						|
  b.foo();
 | 
						|
}
 | 
						|
 | 
						|
}  // Test9
 | 
						|
 | 
						|
namespace Test10 {
 | 
						|
 | 
						|
// because A's key function is defined here, vtable is generated in this TU
 | 
						|
// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
 | 
						|
struct A {
 | 
						|
  virtual void foo();
 | 
						|
  virtual void bar();
 | 
						|
};
 | 
						|
void A::foo() {}
 | 
						|
 | 
						|
// Because key function is inline we will generate vtable as linkonce_odr.
 | 
						|
// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
 | 
						|
struct D : A {
 | 
						|
  void bar();
 | 
						|
};
 | 
						|
inline void D::bar() {}
 | 
						|
 | 
						|
// Because B has outline all virtual functions, we can refer to them.
 | 
						|
// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant
 | 
						|
struct B : A {
 | 
						|
  void foo();
 | 
						|
  void bar();
 | 
						|
};
 | 
						|
 | 
						|
// C's key function (car) is outline, but C has inline virtual function so we
 | 
						|
// can't guarantee that we will be able to refer to bar from name
 | 
						|
// so (at the moment) we can't emit vtable available_externally.
 | 
						|
// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
 | 
						|
struct C : A {
 | 
						|
  void bar() {}               // defined in body - not key function
 | 
						|
  virtual inline void gar();  // inline in body - not key function
 | 
						|
  virtual void car();
 | 
						|
};
 | 
						|
 | 
						|
// no key function, vtable will be generated everywhere it will be used
 | 
						|
// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
 | 
						|
struct E : A {};
 | 
						|
 | 
						|
void g(A& a) {
 | 
						|
  a.foo();
 | 
						|
  a.bar();
 | 
						|
}
 | 
						|
 | 
						|
void f() {
 | 
						|
  A a;
 | 
						|
  g(a);
 | 
						|
  B b;
 | 
						|
  g(b);
 | 
						|
  C c;
 | 
						|
  g(c);
 | 
						|
  D d;
 | 
						|
  g(d);
 | 
						|
  E e;
 | 
						|
  g(e);
 | 
						|
}
 | 
						|
 | 
						|
}  // Test10
 | 
						|
 | 
						|
namespace Test11 {
 | 
						|
struct D;
 | 
						|
// Can emit C's vtable available_externally.
 | 
						|
// CHECK-TEST11: @_ZTVN6Test111CE = available_externally unnamed_addr constant
 | 
						|
struct C {
 | 
						|
  virtual D& operator=(const D&);
 | 
						|
};
 | 
						|
 | 
						|
// Cannot emit B's vtable available_externally, because we cannot create
 | 
						|
// a reference to the inline virtual B::operator= function.
 | 
						|
// CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant
 | 
						|
struct D : C {
 | 
						|
  virtual void key();
 | 
						|
};
 | 
						|
D f();
 | 
						|
 | 
						|
void g(D& a) {
 | 
						|
  C c;
 | 
						|
  c = a;
 | 
						|
  a.key();
 | 
						|
  a.key();
 | 
						|
}
 | 
						|
void g() {
 | 
						|
  D d;
 | 
						|
  d = f();
 | 
						|
  g(d);
 | 
						|
}
 | 
						|
}  // Test 11
 | 
						|
 | 
						|
namespace Test12 {
 | 
						|
 | 
						|
// CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
 | 
						|
struct A {
 | 
						|
  virtual void foo();
 | 
						|
  virtual ~A() {}
 | 
						|
};
 | 
						|
// CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
 | 
						|
struct B : A {
 | 
						|
  void foo();
 | 
						|
};
 | 
						|
 | 
						|
void g() {
 | 
						|
  A a;
 | 
						|
  a.foo();
 | 
						|
  B b;
 | 
						|
  b.foo();
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace Test13 {
 | 
						|
 | 
						|
// CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
 | 
						|
// CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
 | 
						|
struct A {
 | 
						|
  virtual ~A();
 | 
						|
};
 | 
						|
struct B : A {
 | 
						|
  virtual void f();
 | 
						|
  void operator delete(void *);
 | 
						|
  ~B() {}
 | 
						|
};
 | 
						|
 | 
						|
void g() {
 | 
						|
  A *b = new B;
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace Test14 {
 | 
						|
 | 
						|
// CHECK-TEST14: @_ZTVN6Test141AE = available_externally unnamed_addr constant
 | 
						|
struct A {
 | 
						|
  virtual void f();
 | 
						|
  void operator delete(void *);
 | 
						|
  ~A();
 | 
						|
};
 | 
						|
 | 
						|
void g() {
 | 
						|
  A *b = new A;
 | 
						|
  delete b;
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace Test15 {
 | 
						|
// In this test D's vtable has two slots for function f(), but uses only one,
 | 
						|
// so the second slot is set to null.
 | 
						|
// CHECK-TEST15: @_ZTVN6Test151DE = available_externally unnamed_addr constant
 | 
						|
struct A { virtual void f() {} };
 | 
						|
struct B : virtual A {};
 | 
						|
struct C : virtual A {};
 | 
						|
struct D : B, C {
 | 
						|
  virtual void g();
 | 
						|
  void f();
 | 
						|
};
 | 
						|
 | 
						|
void test() {
 | 
						|
  D * d = new D;
 | 
						|
  d->f();
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
namespace Test16 {
 | 
						|
// S has virtual method that is hidden, because of it we can't
 | 
						|
// generate available_externally vtable for it.
 | 
						|
// CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant
 | 
						|
// CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally
 | 
						|
 | 
						|
struct S {
 | 
						|
  __attribute__((visibility("hidden"))) virtual void doStuff();
 | 
						|
};
 | 
						|
 | 
						|
struct S2 {
 | 
						|
  virtual void doStuff();
 | 
						|
  __attribute__((visibility("hidden"))) void unused();
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
void test() {
 | 
						|
  S *s = new S;
 | 
						|
  s->doStuff();
 | 
						|
 | 
						|
  S2 *s2 = new S2;
 | 
						|
  s2->doStuff();
 | 
						|
}
 | 
						|
}
 | 
						|
 |