vtable-layout.cpp revision 7dbf47adb8b8ca84484fae0861ffb2f1eaf44011
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::A, 0) vtable address -- 80// CHECK-NEXT: -- (Test3::B, 0) vtable address -- 81// CHECK-NEXT: 2 | void Test3::B::f() 82// CHECK-NEXT: 3 | void Test3::B::g() 83struct B : A { 84 virtual void f(); 85 virtual void g(); 86}; 87void B::f() { } 88 89// CHECK: Vtable for 'Test3::C' (5 entries). 90// CHECK-NEXT: 0 | offset_to_top (0) 91// CHECK-NEXT: 1 | Test3::C RTTI 92// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 93// CHECK-NEXT: -- (Test3::C, 0) vtable address -- 94// CHECK-NEXT: 2 | void Test3::A::f() 95// CHECK-NEXT: 3 | void Test3::C::g() 96// CHECK-NEXT: 4 | void Test3::C::h() 97struct C : A { 98 virtual void g(); 99 virtual void h(); 100}; 101void C::g() { } 102 103// CHECK: Vtable for 'Test3::D' (5 entries). 104// CHECK-NEXT: 0 | offset_to_top (0) 105// CHECK-NEXT: 1 | Test3::D RTTI 106// CHECK-NEXT: -- (Test3::A, 0) vtable address -- 107// CHECK-NEXT: -- (Test3::B, 0) vtable address -- 108// CHECK-NEXT: -- (Test3::D, 0) vtable address -- 109// CHECK-NEXT: 2 | void Test3::D::f() 110// CHECK-NEXT: 3 | void Test3::D::g() 111// CHECK-NEXT: 4 | void Test3::D::h() 112struct D : B { 113 virtual void f(); 114 virtual void g(); 115 virtual void h(); 116}; 117 118void D::f() { } 119} 120 121namespace Test4 { 122 123// Test simple non-virtual result adjustments. 124 125struct R1 { int r1; }; 126struct R2 { int r2; }; 127struct R3 : R1, R2 { int r3; }; 128 129struct A { 130 virtual R2 *f(); 131}; 132 133// CHECK: Vtable for 'Test4::B' (4 entries). 134// CHECK-NEXT: 0 | offset_to_top (0) 135// CHECK-NEXT: 1 | Test4::B RTTI 136// CHECK-NEXT: -- (Test4::A, 0) vtable address -- 137// CHECK-NEXT: -- (Test4::B, 0) vtable address -- 138// CHECK-NEXT: 2 | Test4::R3 *Test4::B::f() 139// CHECK-NEXT: [return adjustment: 4 non-virtual] 140// CHECK-NEXT: 3 | Test4::R3 *Test4::B::f() 141 142struct B : A { 143 virtual R3 *f(); 144}; 145 146R3 *B::f() { return 0; } 147 148} 149 150// For now, just verify this doesn't crash. 151namespace test0 { 152 struct Obj {}; 153 154 struct Base { virtual const Obj *foo() = 0; }; 155 struct Derived : Base { virtual Obj *foo() { return new Obj(); } }; 156 157 void test(Derived *D) { D->foo(); } 158} 159