summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2014-04-21 20:23:34 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2014-04-21 20:23:34 +0000
commitd60ae72c42bd9c87408b5705e7896d58851604a7 (patch)
treea826cb7161e66f6eaf7c2fdfbbe728ff47ea583a /clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
parent29cdbc63193d2c8cbf7fc370237fb5d306a07047 (diff)
downloadbcm5719-llvm-d60ae72c42bd9c87408b5705e7896d58851604a7.tar.gz
bcm5719-llvm-d60ae72c42bd9c87408b5705e7896d58851604a7.zip
Split out the rest of MS ABI multiple inheritance tests
Intentionally duplicate base class definitions per test, so it's easier to copy tests while debugging failures. llvm-svn: 206782
Diffstat (limited to 'clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp')
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
new file mode 100644
index 00000000000..2d0bf636229
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-return-adjustment.cpp
@@ -0,0 +1,297 @@
+// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -emit-llvm -o %t.ll -fdump-vtable-layouts >%t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck --check-prefix=MANGLING %s < %t.ll
+
+namespace test1 {
+struct A {
+ virtual void g();
+ // Add an extra virtual method so it's easier to check for the absence of thunks.
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+// Overrides a method of two bases at the same time, thus needing thunks.
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct X : D {
+ // CHECK-LABEL: VFTable for 'test1::D' in 'test1::X' (3 entries).
+ // CHECK-NEXT: 0 | test1::C *test1::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test1::D::z()
+ // CHECK-NEXT: 2 | test1::C *test1::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test1::C *test1::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test1::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test1::X' (1 entry).
+ // CHECK-NEXT: 2 | test1::C *test1::X::foo()
+
+ // MANGLING-DAG: @"\01??_7X@test1@@6B@"
+
+ virtual C* foo();
+} x;
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test2 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : C { };
+
+struct X : E {
+ virtual F* foo();
+ // CHECK-LABEL: VFTable for 'test2::D' in 'test2::E' in 'test2::X' (4 entries).
+ // CHECK-NEXT: 0 | test2::F *test2::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test2::D::z()
+ // CHECK-NEXT: 2 | test2::F *test2::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test2::C *'): 0 non-virtual]
+ // CHECK-NEXT: 3 | test2::F *test2::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test2::F *test2::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test2::C *'): 0 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test2::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test2::X' (1 entry).
+ // CHECK-NEXT: 3 | test2::F *test2::X::foo()
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test3 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : E {
+ // CHECK-LABEL: VFTable for 'test3::D' in 'test3::E' in 'test3::X' (4 entries).
+ // CHECK-NEXT: 0 | test3::F *test3::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test3::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test3::D::z()
+ // CHECK-NEXT: 2 | test3::F *test3::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test3::C *'): 4 non-virtual]
+ // CHECK-NEXT: 3 | test3::F *test3::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test3::F *test3::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test3::C *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test3::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test3::X' (1 entry).
+ // CHECK-NEXT: 3 | test3::F *test3::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test4 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : D, E {
+ // CHECK-LABEL: VFTable for 'test4::D' in 'test4::X' (3 entries).
+ // CHECK-NEXT: 0 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test4::D::z()
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable for 'test4::D' in 'test4::E' in 'test4::X' (4 entries).
+ // CHECK-NEXT: 0 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | void test4::D::z()
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::C *'): 4 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 3 | test4::F *test4::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test4::F *'): 0 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: Thunks for 'test4::F *test4::X::foo()' (3 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test4::F *'): 0 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test4::C *'): 4 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+ // CHECK-NEXT: 2 | [return adjustment (to type 'struct test4::B *'): 8 non-virtual]
+ // CHECK-NEXT: [this adjustment: -4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test4::X' (1 entry).
+ // CHECK-NEXT: 2 | test4::F *test4::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test5 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct X : A, D {
+ // CHECK-LABEL: VFTable for 'test5::A' in 'test5::X' (2 entries).
+ // CHECK-NEXT: 0 | void test5::A::g()
+ // CHECK-NEXT: 1 | void test5::A::h()
+
+ // CHECK-LABEL: VFTable for 'test5::D' in 'test5::X' (3 entries).
+ // CHECK-NEXT: 0 | test5::C *test5::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test5::B *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | void test5::D::z()
+ // CHECK-NEXT: 2 | test5::C *test5::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test5::C *test5::X::foo()' (1 entry).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test5::B *'): 4 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test5::X' (1 entry).
+ // CHECK-NEXT: via vfptr at offset 4
+ // CHECK-NEXT: 2 | test5::C *test5::X::foo()
+
+ virtual C* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
+
+namespace test6 {
+struct A {
+ virtual void g();
+ virtual void h();
+};
+
+struct B {
+ virtual void g();
+};
+
+struct C : A, B {
+ virtual void g();
+};
+
+struct D {
+ virtual B* foo();
+ virtual void z();
+};
+
+struct E : A, D {
+ virtual C* foo();
+};
+
+struct F : A, C { };
+
+struct X : E {
+ // CHECK-LABEL: VFTable for 'test6::A' in 'test6::E' in 'test6::X' (2 entries).
+ // CHECK-NEXT: 0 | void test6::A::g()
+ // CHECK-NEXT: 1 | void test6::A::h()
+
+ // CHECK-LABEL: VFTable for 'test6::D' in 'test6::E' in 'test6::X' (4 entries).
+ // CHECK-NEXT: 0 | test6::F *test6::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test6::B *'): 8 non-virtual]
+ // CHECK-NEXT: 1 | void test6::D::z()
+ // CHECK-NEXT: 2 | test6::F *test6::X::foo()
+ // CHECK-NEXT: [return adjustment (to type 'struct test6::C *'): 4 non-virtual]
+ // CHECK-NEXT: 3 | test6::F *test6::X::foo()
+
+ // CHECK-LABEL: Thunks for 'test6::F *test6::X::foo()' (2 entries).
+ // CHECK-NEXT: 0 | [return adjustment (to type 'struct test6::C *'): 4 non-virtual]
+ // CHECK-NEXT: 1 | [return adjustment (to type 'struct test6::B *'): 8 non-virtual]
+
+ // CHECK-LABEL: VFTable indices for 'test6::X' (1 entry).
+ // CHECK-NEXT: -- accessible via vfptr at offset 4 --
+ // CHECK-NEXT: 3 | test6::F *test6::X::foo()
+
+ virtual F* foo();
+};
+
+void build_vftable(X *obj) { obj->foo(); }
+}
OpenPOWER on IntegriCloud