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 62 C::C() {} // Emits vftable and forces thunk generation. 63 64 // CODEGEN-LABEL: define linkonce_odr x86_thiscallcc void @"\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 void @"\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 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 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 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 i8** 132 // CODEGEN: %[[VBTABLE:.*]] = load i8** %[[VBPTR]] 133 // CODEGEN: %[[VBASE_OFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 8 134 // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = bitcast i8* %[[VBASE_OFFSET_PTR_i8]] to i32* 135 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32* %[[VBASE_OFFSET_PTR]] 136 // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]] 137 // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F* 138 // CODEGEN: phi %struct.F* {{.*}} %[[RES]] 139 // CODEGEN: ret %struct.{{[BF]}}* 140 141 namespace CrashOnThunksForAttributedType { 142 // We used to crash on this because the type of foo is an AttributedType, not 143 // FunctionType, and we had to look through the sugar. 144 struct A { 145 virtual void __stdcall foo(); 146 }; 147 struct B { 148 virtual void __stdcall foo(); 149 }; 150 struct C : A, B { 151 virtual void __stdcall foo(); 152 }; 153 C c; 154 } 155 156 namespace { 157 struct E : D { 158 E(); 159 virtual C* goo(); 160 }; 161 E::E() {} 162 E e; 163 // Class with internal linkage has internal linkage thunks. 164 // CODEGEN: define internal x86_thiscallcc %struct.C* @"\01?goo@E@?A@@QAEPAUB@@XZ" 165 } 166