vtable-layout.cpp revision 96058953c72355efb266abe8e333db4f5715dbd2
1// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s 2namespace Test1 { 3 4// CHECK: Vtable for 'Test1::A' (3 entries). 5// CHECK-NEXT: 0 | offset_to_top (0) 6// CHECK-NEXT: 1 | Test1::A RTTI 7// CHECK-NEXT: -- (Test1::A, 0) vtable address -- 8// CHECK-NEXT: 2 | void Test1::A::f() 9struct A { 10 virtual void f(); 11}; 12void A::f() { } 13 14} 15 16namespace Test2 { 17 18// This is a smoke test of the vtable dumper. 19// CHECK: Vtable for 'Test2::A' (9 entries). 20// CHECK-NEXT: 0 | offset_to_top (0) 21// CHECK-NEXT: 1 | Test2::A RTTI 22// CHECK-NEXT: -- (Test2::A, 0) vtable address -- 23// CHECK-NEXT: 2 | void Test2::A::f() 24// CHECK-NEXT: 3 | void Test2::A::f() const 25// CHECK-NEXT: 4 | Test2::A *Test2::A::g(int) 26// CHECK-NEXT: 5 | Test2::A::~A() [complete] 27// CHECK-NEXT: 6 | Test2::A::~A() [deleting] 28// CHECK-NEXT: 7 | void Test2::A::h() 29// CHECK-NEXT: 8 | Test2::A &Test2::A::operator=(Test2::A const &) 30struct A { 31 virtual void f(); 32 virtual void f() const; 33 34 virtual A* g(int a); 35 virtual ~A(); 36 virtual void h(); 37 virtual A& operator=(const A&); 38}; 39void A::f() { } 40 41// Another simple vtable dumper test. 42 43// CHECK: Vtable for 'Test2::B' (6 entries). 44// CHECK-NEXT: 0 | offset_to_top (0) 45// CHECK-NEXT: 1 | Test2::B RTTI 46// CHECK-NEXT: -- (Test2::B, 0) vtable address -- 47// CHECK-NEXT: 2 | void Test2::B::f() 48// CHECK-NEXT: 3 | void Test2::B::g() [pure] 49// CHECK-NEXT: 4 | Test2::B::~B() [complete] [pure] 50// CHECK-NEXT: 5 | Test2::B::~B() [deleting] [pure] 51struct B { 52 virtual void f(); 53 virtual void g() = 0; 54 virtual ~B() = 0; 55}; 56void B::f() { } 57 58} 59 60namespace Test3 { 61 62// If a function in a derived class overrides a function in a primary base, 63// then the function should not have an entry in the derived class (unless the return 64// value requires adjusting). 65 66// CHECK: Vtable for 'Test3::A' (3 entries). 67// CHECK-NEXT: 0 | offset_to_top (0) 68// CHECK-NEXT: 1 | Test3::A RTTI 69// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 70// CHECK-NEXT: 2 | void Test3::A::f() 71struct A { 72 virtual void f(); 73}; 74void A::f() { } 75 76// CHECK: Vtable for 'Test3::B' (4 entries). 77// CHECK-NEXT: 0 | offset_to_top (0) 78// CHECK-NEXT: 1 | Test3::B RTTI 79// CHECK-NEXT: -- (Test3::B, 0) vtable address -- 80// CHECK-NEXT: 2 | void Test3::A::f() 81// CHECK-NEXT: 3 | void Test3::B::g() 82struct B : A { 83 virtual void f(); 84 virtual void g(); 85}; 86void B::f() { } 87 88// CHECK: Vtable for 'Test3::C' (5 entries). 89// CHECK-NEXT: 0 | offset_to_top (0) 90// CHECK-NEXT: 1 | Test3::C RTTI 91// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 92// CHECK-NEXT: 2 | void Test3::A::f() 93// CHECK-NEXT: 3 | void Test3::C::g() 94// CHECK-NEXT: 4 | void Test3::C::h() 95struct C : A { 96 virtual void g(); 97 virtual void h(); 98}; 99void C::g() { } 100 101// CHECK: Vtable for 'Test3::D' (5 entries). 102// CHECK-NEXT: 0 | offset_to_top (0) 103// CHECK-NEXT: 1 | Test3::D RTTI 104// CHECK-NEXT: -- (Test3::D, 0) vtable address -- 105// CHECK-NEXT: 2 | void Test3::A::f() 106// CHECK-NEXT: 3 | void Test3::B::g() 107// CHECK-NEXT: 4 | void Test3::D::h() 108struct D : B { 109 virtual void f(); 110 virtual void g(); 111 virtual void h(); 112}; 113 114void D::f() { } 115} 116 117// For now, just verify this doesn't crash. 118namespace test0 { 119 struct Obj {}; 120 121 struct Base { virtual const Obj *foo() = 0; }; 122 struct Derived : Base { virtual Obj *foo() { return new Obj(); } }; 123 124 void test(Derived *D) { D->foo(); } 125} 126