xref: /llvm-project/clang/test/CodeGenCXX/vtable-linkage-address-space.cpp (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
18acdcf40SAlex Voicu // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o %t
28acdcf40SAlex Voicu // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -std=c++03 -o %t.03
38acdcf40SAlex Voicu // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -std=c++11 -o %t.11
48acdcf40SAlex Voicu // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -disable-llvm-passes -O3 -emit-llvm -o %t.opt
58acdcf40SAlex Voicu // RUN: FileCheck %s < %t
68acdcf40SAlex Voicu // RUN: FileCheck %s < %t.03
78acdcf40SAlex Voicu // RUN: FileCheck %s < %t.11
88acdcf40SAlex Voicu // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
98acdcf40SAlex Voicu 
108acdcf40SAlex Voicu namespace {
118acdcf40SAlex Voicu   struct A {
f__anon46f5fe5f0111::A128acdcf40SAlex Voicu     virtual void f() { }
138acdcf40SAlex Voicu   };
148acdcf40SAlex Voicu }
158acdcf40SAlex Voicu 
f()168acdcf40SAlex Voicu void f() { A b; }
178acdcf40SAlex Voicu 
188acdcf40SAlex Voicu struct B {
198acdcf40SAlex Voicu   B();
208acdcf40SAlex Voicu   virtual void f();
218acdcf40SAlex Voicu };
228acdcf40SAlex Voicu 
B()238acdcf40SAlex Voicu B::B() { }
248acdcf40SAlex Voicu 
258acdcf40SAlex Voicu struct C : virtual B {
268acdcf40SAlex Voicu   C();
fC278acdcf40SAlex Voicu   virtual void f() { }
288acdcf40SAlex Voicu };
298acdcf40SAlex Voicu 
C()308acdcf40SAlex Voicu C::C() { }
318acdcf40SAlex Voicu 
328acdcf40SAlex Voicu struct D {
338acdcf40SAlex Voicu   virtual void f();
348acdcf40SAlex Voicu };
358acdcf40SAlex Voicu 
f()368acdcf40SAlex Voicu void D::f() { }
378acdcf40SAlex Voicu 
388acdcf40SAlex Voicu static struct : D { } e;
398acdcf40SAlex Voicu 
408acdcf40SAlex Voicu // Force 'e' to be constructed and therefore have a vtable defined.
use_e()418acdcf40SAlex Voicu void use_e() {
428acdcf40SAlex Voicu   e.f();
438acdcf40SAlex Voicu }
448acdcf40SAlex Voicu 
458acdcf40SAlex Voicu // The destructor is the key function.
468acdcf40SAlex Voicu template<typename T>
478acdcf40SAlex Voicu struct E {
488acdcf40SAlex Voicu   virtual ~E();
498acdcf40SAlex Voicu };
508acdcf40SAlex Voicu 
~E()518acdcf40SAlex Voicu template<typename T> E<T>::~E() { }
528acdcf40SAlex Voicu 
538acdcf40SAlex Voicu // Anchor is the key function
548acdcf40SAlex Voicu template<>
558acdcf40SAlex Voicu struct E<char> {
568acdcf40SAlex Voicu   virtual void anchor();
578acdcf40SAlex Voicu };
588acdcf40SAlex Voicu 
anchor()598acdcf40SAlex Voicu void E<char>::anchor() { }
608acdcf40SAlex Voicu 
618acdcf40SAlex Voicu template struct E<short>;
628acdcf40SAlex Voicu extern template struct E<int>;
638acdcf40SAlex Voicu 
use_E()648acdcf40SAlex Voicu void use_E() {
658acdcf40SAlex Voicu   E<int> ei;
668acdcf40SAlex Voicu   (void)ei;
678acdcf40SAlex Voicu   E<long> el;
688acdcf40SAlex Voicu   (void)el;
698acdcf40SAlex Voicu }
708acdcf40SAlex Voicu 
718acdcf40SAlex Voicu // No key function
728acdcf40SAlex Voicu template<typename T>
738acdcf40SAlex Voicu struct F {
fooF748acdcf40SAlex Voicu   virtual void foo() { }
758acdcf40SAlex Voicu };
768acdcf40SAlex Voicu 
778acdcf40SAlex Voicu // No key function
788acdcf40SAlex Voicu template<>
798acdcf40SAlex Voicu struct F<char> {
fooF808acdcf40SAlex Voicu   virtual void foo() { }
818acdcf40SAlex Voicu };
828acdcf40SAlex Voicu 
838acdcf40SAlex Voicu template struct F<short>;
848acdcf40SAlex Voicu extern template struct F<int>;
858acdcf40SAlex Voicu 
use_F()868acdcf40SAlex Voicu void use_F() {
878acdcf40SAlex Voicu   F<char> fc;
888acdcf40SAlex Voicu   fc.foo();
898acdcf40SAlex Voicu   F<int> fi;
908acdcf40SAlex Voicu   fi.foo();
918acdcf40SAlex Voicu   F<long> fl;
928acdcf40SAlex Voicu   (void)fl;
938acdcf40SAlex Voicu }
948acdcf40SAlex Voicu 
958acdcf40SAlex Voicu // B has a key function that is not defined in this translation unit so its vtable
968acdcf40SAlex Voicu // has external linkage.
978acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1B = external unnamed_addr addrspace(1) constant
988acdcf40SAlex Voicu 
998acdcf40SAlex Voicu // C has no key function, so its vtable should have weak_odr linkage
100*0f1c1be1SAaron Ballman // and hidden visibility
1018acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1C = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1028acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1C = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1038acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1C = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1048acdcf40SAlex Voicu // CHECK-DAG: @_ZTT1C = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1058acdcf40SAlex Voicu 
1068acdcf40SAlex Voicu // D has a key function that is defined in this translation unit so its vtable is
1078acdcf40SAlex Voicu // defined in the translation unit.
1088acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1D ={{.*}} unnamed_addr addrspace(1) constant
1098acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1D ={{.*}} addrspace(1) constant
1108acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1D ={{.*}} addrspace(1) constant
1118acdcf40SAlex Voicu 
1128acdcf40SAlex Voicu // E<char> is an explicit specialization with a key function defined
1138acdcf40SAlex Voicu // in this translation unit, so its vtable should have external
1148acdcf40SAlex Voicu // linkage.
1158acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1EIcE ={{.*}} unnamed_addr addrspace(1) constant
1168acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1EIcE ={{.*}} addrspace(1) constant
1178acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1EIcE ={{.*}} addrspace(1) constant
1188acdcf40SAlex Voicu 
1198acdcf40SAlex Voicu // E<short> is an explicit template instantiation with a key function
1208acdcf40SAlex Voicu // defined in this translation unit, so its vtable should have
1218acdcf40SAlex Voicu // weak_odr linkage.
1228acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1EIsE = weak_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1238acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1EIsE = weak_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1248acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1EIsE = weak_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1258acdcf40SAlex Voicu 
1268acdcf40SAlex Voicu // F<short> is an explicit template instantiation without a key
1278acdcf40SAlex Voicu // function, so its vtable should have weak_odr linkage
1288acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1FIsE = weak_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1298acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1FIsE = weak_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1308acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1FIsE = weak_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1318acdcf40SAlex Voicu 
1328acdcf40SAlex Voicu // E<long> is an implicit template instantiation with a key function
1338acdcf40SAlex Voicu // defined in this translation unit, so its vtable should have
1348acdcf40SAlex Voicu // linkonce_odr linkage.
1358acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1EIlE = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1368acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1EIlE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1378acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1EIlE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1388acdcf40SAlex Voicu 
1398acdcf40SAlex Voicu // F<long> is an implicit template instantiation with no key function,
1408acdcf40SAlex Voicu // so its vtable should have linkonce_odr linkage.
1418acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1FIlE = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1428acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1FIlE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1438acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1FIlE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1448acdcf40SAlex Voicu 
1458acdcf40SAlex Voicu // F<int> is an explicit template instantiation declaration without a
1468acdcf40SAlex Voicu // key function, so its vtable should have external linkage.
1478acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1FIiE = external unnamed_addr addrspace(1) constant
1488acdcf40SAlex Voicu // CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr addrspace(1) constant
1498acdcf40SAlex Voicu 
1508acdcf40SAlex Voicu // E<int> is an explicit template instantiation declaration. It has a
1518acdcf40SAlex Voicu // key function is not instantiated, so we know that vtable definition
1528acdcf40SAlex Voicu // will be generated in TU where key function will be defined
1538acdcf40SAlex Voicu // so we can mark it as external (without optimizations) and
1548acdcf40SAlex Voicu // available_externally (with optimizations) because all of the inline
1558acdcf40SAlex Voicu // virtual functions have been emitted.
1568acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1EIiE = external unnamed_addr addrspace(1) constant
1578acdcf40SAlex Voicu // CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr addrspace(1) constant
1588acdcf40SAlex Voicu 
1598acdcf40SAlex Voicu // The anonymous struct for e has no linkage, so the vtable should have
1608acdcf40SAlex Voicu // internal linkage.
1618acdcf40SAlex Voicu // CHECK-DAG: @"_ZTV3$_0" = internal unnamed_addr addrspace(1) constant
1628acdcf40SAlex Voicu // CHECK-DAG: @"_ZTS3$_0" = internal addrspace(1) constant
1638acdcf40SAlex Voicu // CHECK-DAG: @"_ZTI3$_0" = internal addrspace(1) constant
1648acdcf40SAlex Voicu 
1658acdcf40SAlex Voicu // The A vtable should have internal linkage since it is inside an anonymous
1668acdcf40SAlex Voicu // namespace.
1678acdcf40SAlex Voicu // CHECK-DAG: @_ZTVN12_GLOBAL__N_11AE = internal unnamed_addr addrspace(1) constant
1688acdcf40SAlex Voicu // CHECK-DAG: @_ZTSN12_GLOBAL__N_11AE = internal addrspace(1) constant
1698acdcf40SAlex Voicu // CHECK-DAG: @_ZTIN12_GLOBAL__N_11AE = internal addrspace(1) constant
1708acdcf40SAlex Voicu 
1718acdcf40SAlex Voicu // F<char> is an explicit specialization without a key function, so
1728acdcf40SAlex Voicu // its vtable should have linkonce_odr linkage.
1738acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1FIcE = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1748acdcf40SAlex Voicu // CHECK-DAG: @_ZTS1FIcE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 1{{$}}
1758acdcf40SAlex Voicu // CHECK-DAG: @_ZTI1FIcE = linkonce_odr addrspace(1) constant {{.*}}, comdat, align 8{{$}}
1768acdcf40SAlex Voicu 
1778acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1GIiE = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1788acdcf40SAlex Voicu template <typename T>
1798acdcf40SAlex Voicu class G {
1808acdcf40SAlex Voicu public:
G()1818acdcf40SAlex Voicu   G() {}
1828acdcf40SAlex Voicu   virtual void f0();
1838acdcf40SAlex Voicu   virtual void f1();
1848acdcf40SAlex Voicu };
1858acdcf40SAlex Voicu template <>
f1()1868acdcf40SAlex Voicu void G<int>::f1() {}
1878acdcf40SAlex Voicu template <typename T>
f0()1888acdcf40SAlex Voicu void G<T>::f0() {}
G_f0()1898acdcf40SAlex Voicu void G_f0()  { new G<int>(); }
1908acdcf40SAlex Voicu 
1918acdcf40SAlex Voicu // H<int> has a key function without a body but it's a template instantiation
1928acdcf40SAlex Voicu // so its VTable must be emitted.
1938acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1HIiE = linkonce_odr unnamed_addr addrspace(1) constant {{.*}}, comdat,
1948acdcf40SAlex Voicu template <typename T>
1958acdcf40SAlex Voicu class H {
1968acdcf40SAlex Voicu public:
1978acdcf40SAlex Voicu   virtual ~H();
1988acdcf40SAlex Voicu };
1998acdcf40SAlex Voicu 
use_H()2008acdcf40SAlex Voicu void use_H() {
2018acdcf40SAlex Voicu   H<int> h;
2028acdcf40SAlex Voicu }
2038acdcf40SAlex Voicu 
2048acdcf40SAlex Voicu // I<int> has an explicit instantiation declaration and needs a VTT and
2058acdcf40SAlex Voicu // construction vtables.
2068acdcf40SAlex Voicu 
2078acdcf40SAlex Voicu // CHECK-DAG: @_ZTV1IIiE = external unnamed_addr addrspace(1) constant
2088acdcf40SAlex Voicu // CHECK-DAG: @_ZTT1IIiE = external unnamed_addr addrspace(1) constant
2098acdcf40SAlex Voicu // CHECK-NOT: @_ZTC1IIiE
2108acdcf40SAlex Voicu //
2118acdcf40SAlex Voicu // CHECK-OPT-DAG: @_ZTV1IIiE = available_externally unnamed_addr addrspace(1) constant
2128acdcf40SAlex Voicu // CHECK-OPT-DAG: @_ZTT1IIiE = available_externally unnamed_addr addrspace(1) constant
2138acdcf40SAlex Voicu struct VBase1 { virtual void f(); }; struct VBase2 : virtual VBase1 {};
2148acdcf40SAlex Voicu template<typename T>
2158acdcf40SAlex Voicu struct I : VBase2 {};
2168acdcf40SAlex Voicu extern template struct I<int>;
2178acdcf40SAlex Voicu I<int> i;
218