xref: /llvm-project/clang/test/CodeGenCXX/ps-dllstorage-vtable-rtti.cpp (revision 0ad4c8075985a0b82c01b28750a49e9e46a8c220)
1 /// For a class that has a vtable and typeinfo symbol for RTTI, if a user marks
2 /// either:
3 ///
4 ///   (a) The entire class as dllexport (dllimport)
5 ///   (b) Any non-inline method of the class as dllexport (dllimport)
6 ///
7 /// then Clang must export the vtable and typeinfo symbol from the TU where they
8 /// are defined (the TU containing the definition of the Itanium C++ ABI "key
9 /// function") and must import them in other modules where they are referenced.
10 
11 // RUN: %clang_cc1 -I%S -fdeclspec -triple x86_64-unknown-windows-itanium -emit-llvm -o - %s -fhalf-no-semantic-interposition \
12 // RUN:   | FileCheck %s -check-prefix=WI
13 // RUN: %clang_cc1 -I%S -fdeclspec -triple x86_64-scei-windows-itanium    -emit-llvm -o - %s -fhalf-no-semantic-interposition \
14 // RUN:   | FileCheck %s --check-prefixes=PS
15 // RUN: %clang_cc1 -I%S -fdeclspec -triple x86_64-scei-ps4 -emit-llvm -o - %s -fhalf-no-semantic-interposition \
16 // RUN:   | FileCheck %s --check-prefixes=PS
17 // RUN: %clang_cc1 -I%S -fdeclspec -triple x86_64-sie-ps5  -emit-llvm -o - %s -fhalf-no-semantic-interposition \
18 // RUN:   | FileCheck %s --check-prefixes=PS
19 
20 #include <typeinfo>
21 
22 /// Case (a) -- Import Aspect
23 /// The entire class is imported. The typeinfo symbol must also be imported, but
24 /// the vtable will not be referenced, and so does not need to be imported.
25 
26 // PS-DAG: @_ZTI10FullImport = {{.*}}dllimport
27 // WI-DAG: @_ZTI10FullImport = external dllimport constant ptr
28 struct __declspec(dllimport) FullImport {
inlineFuncFullImport29   virtual void inlineFunc() const {}
30   virtual void key();
31   virtual void func();
32 };
33 
34 /// 'FullImport::key()' is the key function, so the vtable and typeinfo symbol
35 /// of 'FullImport' will be defined in the TU that contains the definition of
36 /// 'key()' (and they must be exported from there).
FullImportTest()37 void FullImportTest() { typeid(FullImport).name(); }
38 
39 /// Case (a) -- Export Aspect
40 /// The entire class is exported. The vtable and typeinfo symbols must also be
41 /// exported.
42 
43 // PS-DAG: @_ZTV10FullExport = {{.*}}dllexport
44 // WI-DAG: @_ZTV10FullExport = {{.*}}dllexport
45 // PS-DAG: @_ZTI10FullExport = {{.*}}dllexport
46 // WI-DAG: @_ZTI10FullExport = dso_local dllexport constant {
47 struct __declspec(dllexport) FullExport {
inlineFuncFullExport48   virtual void inlineFunc() const {}
49   virtual void key();
50   virtual void func();
51 };
52 
53 /// This is the key function of the class 'FullExport', so the vtable and
54 /// typeinfo symbols of 'FullExport' will be defined in this TU, and so they
55 /// must be exported from this TU.
key()56 void FullExport::key() { typeid(FullExport).name(); }
57 
58 /// Case (b) -- Import Aspect
59 /// The class as a whole is not imported, but a non-inline method of the class
60 /// is, so the vtable and typeinfo symbol must be imported.
61 
62 // PS-DAG: @_ZTV10PartImport = {{.*}}dllimport
63 // WI-DAG: @_ZTV10PartImport = external dso_local unnamed_addr constant {
64 // PS-DAG: @_ZTI10PartImport = {{.*}}dllimport
65 // WI-DAG: @_ZTI10PartImport = external dso_local constant ptr
66 struct PartImport {
inlineFuncPartImport67   virtual void inlineFunc() const {}
68   virtual void key();
69   __declspec(dllimport) virtual void func();
70 };
71 
72 /// 'PartImport::key()' is the key function, so the vtable and typeinfo symbol
73 /// of 'PartImport' will be defined in the TU that contains the definition of
74 /// 'key()' (and they must be exported from there). Here, we will reference the
75 /// vtable and typeinfo symbol, so we must also import them.
PartImportTest()76 void PartImportTest() {
77   PartImport f;
78   typeid(PartImport).name();
79 }
80 
81 /// Case (b) -- Export Aspect
82 /// The class as a whole is not exported, but a non-inline method of the class
83 /// is, so the vtable and typeinfo symbol must be exported.
84 
85 // PS-DAG: @_ZTV10PartExport = {{.*}}dllexport
86 // WI-DAG: @_ZTV10PartExport = dso_local unnamed_addr constant {
87 // PS-DAG: @_ZTI10PartExport = {{.*}}dllexport
88 // WI-DAG: @_ZTI10PartExport = dso_local constant {
89 struct PartExport {
inlineFuncPartExport90   virtual void inlineFunc() const {}
91   virtual void key();
92   __declspec(dllexport) virtual void func();
93 };
94 
95 /// This is the key function of the class 'PartExport', so the vtable and
96 /// typeinfo symbol of 'PartExport' will be defined in this TU, and so they must
97 /// be exported from this TU.
key()98 void PartExport::key() { typeid(PartExport).name(); }
99 
100 /// Case (b) -- Export Aspect
101 /// The class as a whole is not exported, but the constructor of the class
102 /// is, so the vtable and typeinfo symbol must be exported.
103 
104 // PS-DAG: @_ZTV10ConsExport = {{.*}}dllexport
105 // WI-DAG: @_ZTV10ConsExport = dso_local unnamed_addr constant {
106 // PS-DAG: @_ZTI10ConsExport = {{.*}}dllexport
107 // WI-DAG: @_ZTI10ConsExport = dso_local constant {
108 struct ConsExport {
109   __declspec(dllexport) ConsExport();
110   virtual void key();
111 };
112 
ConsExport()113 ConsExport::ConsExport() {}
key()114 void ConsExport::key() { typeid(ConsExport).name(); }
115