1 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -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 - -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 
C()62 C::C() {}  // Emits vftable and forces thunk generation.
63 
64 // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete)
65 // CODEGEN:   getelementptr i8* {{.*}}, i32 -4
66 // FIXME: should actually call _EC, not _GC.
67 // CODEGEN:   call x86_thiscallcc i8* @"\01??_GC@@UAEPAXI@Z"
68 // CODEGEN: ret
69 
70 // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\01?public_f@C@@W3AEXXZ"(%struct.C*
71 // CODEGEN:   getelementptr i8* {{.*}}, i32 -4
72 // CODEGEN:   call x86_thiscallcc void @"\01?public_f@C@@UAEXXZ"(%struct.C*
73 // CODEGEN: ret
74 
zoo(C * obj)75 void zoo(C* obj) {
76   delete obj;
77 }
78 
79 struct D {
80   virtual B* goo();
81 };
82 
83 struct E : D {
84   E();
85   virtual C* goo();
86   // MANGLING-DAG: @"\01?goo@E@@UAEPAUC@@XZ"
87   // MANGLING-DAG: @"\01?goo@E@@QAEPAUB@@XZ"
88   // MANGLING-X64-DAG: @"\01?goo@E@@UEAAPEAUC@@XZ"
89   // MANGLING-X64-DAG: @"\01?goo@E@@QEAAPEAUB@@XZ"
90 };
91 
E()92 E::E() {}  // Emits vftable and forces thunk generation.
93 
94 // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.C* @"\01?goo@E@@QAEPAUB@@XZ"
95 // CODEGEN:   call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ"
96 // CODEGEN:   getelementptr inbounds i8* {{.*}}, i32 4
97 // CODEGEN: ret
98 
99 struct F : virtual A, virtual B {
100   virtual void own_method();
101   virtual ~F();
102 };
103 
104 F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
105 
106 struct G : C { };
107 
108 struct H : E {
109   virtual G* goo();
110   // MANGLING-DAG: @"\01?goo@H@@UAEPAUG@@XZ"
111   // MANGLING-DAG: @"\01?goo@H@@QAEPAUB@@XZ"
112   // MANGLING-DAG: @"\01?goo@H@@QAEPAUC@@XZ"
113   // MANGLING-X64-DAG: @"\01?goo@H@@UEAAPEAUG@@XZ"
114   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUB@@XZ"
115   // MANGLING-X64-DAG: @"\01?goo@H@@QEAAPEAUC@@XZ"
116 };
117 
118 H h;
119 
120 struct I : D {
121   I();
122   virtual F* goo();
123 };
124 
I()125 I::I() {}  // Emits vftable and forces thunk generation.
126 
127 // CODEGEN-LABEL: define weak_odr x86_thiscallcc %struct.{{[BF]}}* @"\01?goo@I@@QAEPAUB@@XZ"
128 // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ"
129 // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
130 // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4
131 // CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
132 // CODEGEN: %[[VBTABLE:.*]] = load i32** %[[VBPTR]]
133 // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 2
134 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32* %[[VBASE_OFFSET_PTR]]
135 // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
136 // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
137 // CODEGEN: phi %struct.F* {{.*}} %[[RES]]
138 // CODEGEN: ret %struct.{{[BF]}}*
139 
140 namespace CrashOnThunksForAttributedType {
141 // We used to crash on this because the type of foo is an AttributedType, not
142 // FunctionType, and we had to look through the sugar.
143 struct A {
144   virtual void __stdcall foo();
145 };
146 struct B {
147   virtual void __stdcall foo();
148 };
149 struct C : A, B {
150   virtual void __stdcall foo();
151 };
152 C c;
153 }
154 
155 namespace {
156 struct E : D {
157   E();
158   virtual C* goo();
159 };
E()160 E::E() {}
161 E e;
162 // Class with internal linkage has internal linkage thunks.
163 // CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ"
164 }
165