171568a9eSLeonard Chan // Cross comdat example
271568a9eSLeonard Chan // Child VTable is in a comdat section.
371568a9eSLeonard Chan
4*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm | FileCheck %s
571568a9eSLeonard Chan
671568a9eSLeonard Chan // A comdat is emitted for B but not A
771568a9eSLeonard Chan // CHECK-DAG: $_ZTV1B = comdat any
871568a9eSLeonard Chan // CHECK-DAG: $_ZTS1B = comdat any
971568a9eSLeonard Chan // CHECK-DAG: $_ZTI1B = comdat any
1071568a9eSLeonard Chan // CHECK-DAG: $_ZTI1B.rtti_proxy = comdat any
1171568a9eSLeonard Chan // CHECK-DAG: $_ZTI1A.rtti_proxy = comdat any
1271568a9eSLeonard Chan
1371568a9eSLeonard Chan // VTable for B is emitted here since we access it when creating an instance of B. The VTable is also linkonce_odr and in its own comdat.
14cf8ff75bSLeonard Chan // CHECK-DAG: @_ZTV1B.local = linkonce_odr hidden unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i8* }** @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [3 x i32] }, { [3 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 @_ZN1B3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [3 x i32] }, { [3 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, comdat($_ZTV1B), align 4
1571568a9eSLeonard Chan
1671568a9eSLeonard Chan // The RTTI objects aren’t that important, but it is good to know that they are emitted here since they are used in the vtable for B, and external references are used for RTTI stuff from A.
1771568a9eSLeonard Chan // CHECK-DAG: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global i8*
1871568a9eSLeonard Chan // CHECK-DAG: @_ZTS1B =
1971568a9eSLeonard Chan // CHECK-DAG: @_ZTI1A =
2071568a9eSLeonard Chan // CHECK-DAG: @_ZTI1B =
2171568a9eSLeonard Chan // CHECK-DAG: @_ZTI1B.rtti_proxy = hidden unnamed_addr constant { i8*, i8*, i8* }* @_ZTI1B, comdat
2271568a9eSLeonard Chan
2371568a9eSLeonard Chan // We will emit a vtable for B here, so it does have an alias, but we will not
2471568a9eSLeonard Chan // emit one for A.
2571568a9eSLeonard Chan // CHECK: @_ZTV1B = linkonce_odr unnamed_addr alias { [3 x i32] }, { [3 x i32] }* @_ZTV1B.local
2671568a9eSLeonard Chan // CHECK-NOT: @_ZTV1A = {{.*}}alias
2771568a9eSLeonard Chan
2871568a9eSLeonard Chan class A {
2971568a9eSLeonard Chan public:
3071568a9eSLeonard Chan virtual void foo();
3171568a9eSLeonard Chan };
3271568a9eSLeonard Chan class B : public A {
3371568a9eSLeonard Chan public:
foo()3471568a9eSLeonard Chan inline void foo() override {}
3571568a9eSLeonard Chan };
3671568a9eSLeonard Chan void A_foo(A *a);
3771568a9eSLeonard Chan
3871568a9eSLeonard Chan // func() is used so that the vtable for B is accessed when creating the instance.
func()3971568a9eSLeonard Chan void func() {
4071568a9eSLeonard Chan B b;
4171568a9eSLeonard Chan A_foo(&b);
4271568a9eSLeonard Chan }
43