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: declare {{.*}} @"\01??1C@@UAE@XZ"({{.*}}) 35 // MANGLING-DAG: define {{.*}} @"\01??_GC@@UAEPAXI@Z"({{.*}}) 36 // MANGLING-DAG: define {{.*}} @"\01??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat 37 // MANGLING-X64-DAG: declare {{.*}} @"\01??1C@@UEAA@XZ"({{.*}}) 38 // MANGLING-X64-DAG: define {{.*}} @"\01??_GC@@UEAAPEAXI@Z"({{.*}}) 39 // MANGLING-X64-DAG: define {{.*}} @"\01??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat 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 i8* @"\01??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat 65 // CODEGEN: getelementptr i8, 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, 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"{{.*}} comdat 95 // CODEGEN: call x86_thiscallcc %struct.C* @"\01?goo@E@@UAEPAUC@@XZ" 96 // CODEGEN: getelementptr inbounds i8, 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"{{.*}} comdat 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, i8* %[[ORIG_RET_i8]], i32 4 131 // CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32** 132 // CODEGEN: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]] 133 // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 2 134 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBASE_OFFSET_PTR]] 135 // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, 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 }; 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