When using the relative vtable ABI, if a vtable is not dso_local, it's given private linkage (if not COMDAT) or hidden visibility (if COMDAT) to make it dso_local (to place it in rodata instead of data.rel.ro), and an alias generated with the original linkage and visibility. This alias could later be removed from the symbol table, e.g. if using a version script, at which point we lose all symbol information about the vtable. Use internal linkage instead of private linkage to avoid this. While I'm here, clarify the comment about why COMDAT vtables can't use internal (or private) linkage, and associate it with the else block where hidden visibility is applied instead of internal linkage.
35 lines
1.8 KiB
C++
35 lines
1.8 KiB
C++
// Override pure virtual function.
|
|
// We instead emit zero for the pure virtual function component. See PR43094 for
|
|
// details.
|
|
|
|
// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s
|
|
|
|
// CHECK: @_ZTV1A.local = internal unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4
|
|
|
|
// CHECK: @_ZTV1B.local = internal unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B3barEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4
|
|
|
|
// CHECK: @_ZTV1A ={{.*}} unnamed_addr alias { [4 x i32] }, ptr @_ZTV1A.local
|
|
// CHECK: @_ZTV1B ={{.*}} unnamed_addr alias { [4 x i32] }, ptr @_ZTV1B.local
|
|
|
|
// CHECK-NOT: declare void @__cxa_pure_virtual() unnamed_addr
|
|
|
|
class A {
|
|
public:
|
|
virtual void foo() = 0;
|
|
virtual void bar();
|
|
};
|
|
|
|
class B : public A {
|
|
public:
|
|
void foo() override;
|
|
void bar() override;
|
|
};
|
|
|
|
void A::bar() {}
|
|
void B::foo() {}
|
|
void B::bar() {}
|
|
|
|
void A_foo(A *a) {
|
|
a->foo();
|
|
}
|