171568a9eSLeonard Chan // Diamond inheritance.
271568a9eSLeonard Chan // A more complicated multiple inheritance example that includes longer chain of inheritance and a common ancestor.
371568a9eSLeonard Chan 
4*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s
571568a9eSLeonard Chan 
6cf8ff75bSLeonard Chan // CHECK-DAG: %class.B = type { %class.A }
7cf8ff75bSLeonard Chan // CHECK-DAG: %class.A = type { i32 (...)** }
8cf8ff75bSLeonard Chan // CHECK-DAG: %class.C = type { %class.A }
9cf8ff75bSLeonard Chan // CHECK-DAG: %class.D = type { %class.B, %class.C }
1071568a9eSLeonard Chan 
1171568a9eSLeonard Chan // VTable for B should contain offset to top (0), RTTI pointer, A::foo(), and B::barB().
12cf8ff75bSLeonard Chan // CHECK: @_ZTV1B.local = private unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i8* }** @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.A*)* dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4
1371568a9eSLeonard Chan 
1471568a9eSLeonard Chan // VTable for C should contain offset to top (0), RTTI pointer, A::foo(), and C::barC().
15cf8ff75bSLeonard Chan // CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i8* }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.A*)* dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4
1671568a9eSLeonard Chan 
1771568a9eSLeonard Chan // VTable for D should be similar to the mutiple inheritance example where this
1871568a9eSLeonard Chan // vtable contains 2 inner vtables:
1971568a9eSLeonard Chan // - 1st table containing D::foo(), B::barB(), and D::baz().
2071568a9eSLeonard Chan // - 2nd table containing a thunk to D::foo() and C::barC().
21cf8ff75bSLeonard Chan // CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32] } { [5 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32)], [4 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZThn8_N1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
2271568a9eSLeonard Chan 
23fd739804SFangrui Song // @_ZTV1B ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1B.local
24fd739804SFangrui Song // @_ZTV1C ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1C.local
25fd739804SFangrui Song // @_ZTV1D ={{.*}} unnamed_addr alias { [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local
2671568a9eSLeonard Chan 
2771568a9eSLeonard Chan class A {
2871568a9eSLeonard Chan public:
2971568a9eSLeonard Chan   virtual void foo();
3071568a9eSLeonard Chan };
3171568a9eSLeonard Chan 
3271568a9eSLeonard Chan class B : public A {
3371568a9eSLeonard Chan public:
3471568a9eSLeonard Chan   virtual void barB();
3571568a9eSLeonard Chan };
3671568a9eSLeonard Chan 
3771568a9eSLeonard Chan class C : public A {
3871568a9eSLeonard Chan   virtual void barC();
3971568a9eSLeonard Chan };
4071568a9eSLeonard Chan 
4171568a9eSLeonard Chan // Should be a struct with 2 arrays from 2 parents.
4271568a9eSLeonard Chan // The 1st contains D::foo(), B::barB(), and D::baz().
4371568a9eSLeonard Chan // The 2nd contains C::barC(), and a thunk that points to D::foo().
4471568a9eSLeonard Chan class D : public B, C {
4571568a9eSLeonard Chan public:
4671568a9eSLeonard Chan   virtual void baz();
4771568a9eSLeonard Chan   void foo() override;
4871568a9eSLeonard Chan };
4971568a9eSLeonard Chan 
barB()5071568a9eSLeonard Chan void B::barB() {}
barC()5171568a9eSLeonard Chan void C::barC() {}
foo()5271568a9eSLeonard Chan void D::foo() {}
baz()5371568a9eSLeonard Chan void D::baz() {}
5471568a9eSLeonard Chan 
D_foo(D * d)5571568a9eSLeonard Chan void D_foo(D *d) {
5671568a9eSLeonard Chan   d->foo();
5771568a9eSLeonard Chan }
58