When a target's `getVTableUniqueness()` is `UniqueIfStrongLinkage`, as on Apple Mach-O, the platform may emit a class's weak vtable as a separate copy in more than one linkage unit. A symbol that can legitimately exist at several addresses has no meaningful address, so such a vtable can be marked `unnamed_addr`. On Mach-O, a weak vtable that is `unnamed_addr` lowers to a `.weak_def_can_be_hidden` definition, which the static linker coalesces and then drops from the dynamic export trie. Keeping these vtables out of the exported symbol set cuts the work dyld has to do at load time. #200108 dropped `unnamed_addr` from vtables because the exact `dynamic_cast` optimization compares an object's vtable pointer against a known vtable address and depends on that address being unique. Adding `unnamed_addr` is safe here because that optimization is never performed for these weak vtables, so nothing relies on them having a unique address. rdar://179929460
56 lines
2.0 KiB
C++
56 lines
2.0 KiB
C++
// RUN: %clang_cc1 -triple x86_64-none-linux-gnu %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,LINUX
|
|
// RUN: %clang_cc1 -triple arm-apple-darwin %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DARWIN
|
|
|
|
// Simple key function test
|
|
struct testa { virtual void a(); };
|
|
void testa::a() {}
|
|
|
|
// Simple key function test
|
|
struct testb { virtual void a() {} };
|
|
testb *testbvar = new testb;
|
|
|
|
// Key function with out-of-line inline definition
|
|
struct testc { virtual void a(); };
|
|
inline void testc::a() {}
|
|
|
|
// Functions with inline specifier are not key functions (PR5705)
|
|
struct testd { inline virtual void a(); };
|
|
void testd::a() {}
|
|
|
|
// Functions with inline specifier are not key functions (PR5705)
|
|
struct teste { inline virtual void a(); };
|
|
teste *testevar = new teste;
|
|
|
|
// Key functions with namespace (PR5711)
|
|
namespace {
|
|
struct testf { virtual void a(); };
|
|
}
|
|
void testf::a() {}
|
|
|
|
// Key functions with namespace (PR5711)
|
|
namespace {
|
|
struct testg { virtual void a(); };
|
|
}
|
|
void testg::a() {}
|
|
testg *testgvar = new testg;
|
|
|
|
struct X0 { virtual ~X0(); };
|
|
struct X1 : X0 {
|
|
virtual void f();
|
|
};
|
|
|
|
inline void X1::f() { }
|
|
|
|
void use_X1() { X1 x1; }
|
|
|
|
// LINUX-DAG: @_ZTV2X1 = linkonce_odr constant
|
|
// DARWIN-DAG: @_ZTV2X1 = linkonce_odr unnamed_addr constant
|
|
// CHECK-DAG: @_ZTV5testa ={{.*}}constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// LINUX-DAG: @_ZTV5testc = linkonce_odr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// DARWIN-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// LINUX-DAG: @_ZTV5testb = linkonce_odr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// DARWIN-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// LINUX-DAG: @_ZTV5teste = linkonce_odr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// DARWIN-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null
|
|
// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal constant { [3 x ptr] } { [3 x ptr] [ptr null
|