diff options
Diffstat (limited to 'test/CodeGenCXX/vtable-available-externally.cpp')
-rw-r--r-- | test/CodeGenCXX/vtable-available-externally.cpp | 241 |
1 files changed, 240 insertions, 1 deletions
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp index e07d484..f38d177 100644 --- a/test/CodeGenCXX/vtable-available-externally.cpp +++ b/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,7 +1,17 @@ -// 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 -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> @@ -152,3 +162,232 @@ 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(); +} +} + |