1 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 >%t 2>&1
2 // RUN: FileCheck --check-prefix=MANGLING %s < %t
3 // RUN: FileCheck --check-prefix=XMANGLING %s < %t
4 // RUN: FileCheck --check-prefix=CODEGEN %s < %t
5 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
6 
7 void foo(void *);
8 
9 struct A {
10   virtual ~A();
11   virtual void public_f();
12   // Make sure we don't emit unneeded thunks:
13   // XMANGLING-NOT: @"\01?public_f@A@@QAEXXZ"
14  protected:
15   virtual void protected_f();
16  private:
17   virtual void private_f();
18 };
19 
20 struct B {
21   virtual ~B();
22   virtual void public_f();
23  protected:
24   virtual void protected_f();
25  private:
26   virtual void private_f();
27 };
28 
29 
30 struct C : A, B {
31   C();
32 
33   virtual ~C();
34   // MANGLING-DAG: @"\01??1C@@UAE@XZ"
35   // MANGLING-DAG: @"\01??_GC@@UAEPAXI@Z"
36   // MANGLING-DAG: @"\01??_EC@@W3AEPAXI@Z"
37   // MANGLING-X64-DAG: @"\01??1C@@UEAA@XZ"
38   // MANGLING-X64-DAG: @"\01??_GC@@UEAAPEAXI@Z"
39   // MANGLING-X64-DAG: @"\01??_EC@@W7EAAPEAXI@Z"
40 
41   // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
42   virtual void public_f();
43   // MANGLING-DAG: @"\01?public_f@C@@UAEXXZ"
44   // MANGLING-DAG: @"\01?public_f@C@@W3AEXXZ"
45   // MANGLING-X64-DAG: @"\01?public_f@C@@UEAAXXZ"
46   // MANGLING-X64-DAG: @"\01?public_f@C@@W7EAAXXZ"
47  protected:
48   virtual void protected_f();
49   // MANGLING-DAG: @"\01?protected_f@C@@MAEXXZ"
50   // MANGLING-DAG: @"\01?protected_f@C@@O3AEXXZ"
51   // MANGLING-X64-DAG: @"\01?protected_f@C@@MEAAXXZ"
52   // MANGLING-X64-DAG: @"\01?protected_f@C@@O7EAAXXZ"
53 
54  private:
55   virtual void private_f();
56   // MANGLING-DAG: @"\01?private_f@C@@EAEXXZ"
57   // MANGLING-DAG: @"\01?private_f@C@@G3AEXXZ"
58   // MANGLING-X64-DAG: @"\01?private_f@C@@EEAAXXZ"
59   // MANGLING-X64-DAG: @"\01?private_f@C@@G7EAAXXZ"
60 };
61 
62 C::C() {}  // Emits vftable and forces thunk generation.
63 
64 // CODEGEN: define weak x86_thiscallcc void @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete)
65 // CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
66 // FIXME: should actually call _EC, not _GC.
67 // CODEGEN:   call x86_thiscallcc void @"\01??_GC@@UAEPAXI@Z"
68 // CODEGEN: ret
69 
70 // CODEGEN: define weak x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
71 // CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 -4
72 // CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
73 // CODEGEN: ret
74 
75 void zoo(C* obj) {
76   delete obj;
77 }
78 
79 struct D {
80   virtual B* goo();
81 };
82 
83 struct E : D {
84   virtual C* goo();
85   // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
86   // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
87   // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
88   // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
89 };
90 
91 E e;  // Emits vftable and forces thunk generation.
92 
93 // CODEGEN: define weak x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
94 // CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
95 // CODEGEN:   getelementptr inbounds i8* {{.*}}, i64 4
96 // CODEGEN: ret
97 
98 struct F : virtual A, virtual B {
99   virtual ~F();
100 };
101 
102 F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
103 
104 struct G : C { };
105 
106 struct H : E {
107   virtual G* goo();
108   // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
109   // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
110   // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
111   // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
112   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
113   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
114 };
115 
116 H h;
117 
118 // FIXME: Write vtordisp adjusting thunk tests
119 
120 namespace CrashOnThunksForAttributedType {
121 // We used to crash on this because the type of foo is an AttributedType, not
122 // FunctionType, and we had to look through the sugar.
123 struct A {
124   virtual void __stdcall foo();
125 };
126 struct B {
127   virtual void __stdcall foo();
128 };
129 struct C : A, B {
130   virtual void __stdcall foo();
131 };
132 C c;
133 }
134