1 // Cross comdat example
2 // Child VTable is in a comdat section.
3 
4 // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s
5 
6 // CHECK-DAG: $_ZN1B3fooEv.stub = comdat any
7 // CHECK-DAG: $_ZN1A3fooEv.stub = comdat any
8 
9 // A comdat is emitted for B but not A
10 // CHECK-DAG: $_ZTV1B = comdat any
11 // CHECK-DAG: $_ZTS1B = comdat any
12 // CHECK-DAG: $_ZTI1B = comdat any
13 // CHECK-DAG: $_ZTI1B.rtti_proxy = comdat any
14 // CHECK-DAG: $_ZTI1A.rtti_proxy = comdat any
15 
16 // 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.
17 // 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*)* @_ZN1B3fooEv.stub 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
18 
19 // 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.
20 // CHECK-DAG: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global i8*
21 // CHECK-DAG: @_ZTS1B =
22 // CHECK-DAG: @_ZTI1A =
23 // CHECK-DAG: @_ZTI1B =
24 // CHECK-DAG: @_ZTI1B.rtti_proxy = hidden unnamed_addr constant { i8*, i8*, i8* }* @_ZTI1B, comdat
25 
26 // We will emit a vtable for B here, so it does have an alias, but we will not
27 // emit one for A.
28 // CHECK: @_ZTV1B = linkonce_odr unnamed_addr alias { [3 x i32] }, { [3 x i32] }* @_ZTV1B.local
29 // CHECK-NOT: @_ZTV1A = {{.*}}alias
30 
31 // CHECK: define hidden void @_ZN1B3fooEv.stub(%class.B* {{.*}}%0) unnamed_addr #{{[0-9]+}} comdat
32 
33 // CHECK: declare void @_ZN1A3fooEv(%class.A* {{[^,]*}}) unnamed_addr
34 
35 // CHECK:      define hidden void @_ZN1A3fooEv.stub(%class.A* {{[^,]*}} %0) unnamed_addr #{{[0-9]+}} comdat
36 // CHECK-NEXT: entry:
37 // CHECK-NEXT:   tail call void @_ZN1A3fooEv(%class.A* {{[^,]*}} %0)
38 // CHECK-NEXT:   ret void
39 // CHECK-NEXT: }
40 
41 class A {
42 public:
43   virtual void foo();
44 };
45 class B : public A {
46 public:
47   inline void foo() override {}
48 };
49 void A_foo(A *a);
50 
51 // func() is used so that the vtable for B is accessed when creating the instance.
52 void func() {
53   B b;
54   A_foo(&b);
55 }
56