From bc02d32f4d818fdc58e6029e1a9465e431891ad9 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sat, 14 Mar 2015 06:34:41 +0000 Subject: [PATCH] MS ABI: Mangle virtual member pointer thunks with the correct CC Virtual member pointers are implemented using a thunk. We assumed that the calling convention for this thunk was always __thiscall for 32-bit targets and __cdecl for 64-bit targets. However, this is not the case. Mangle in whichever calling convention is appropriate for this member function thunk. llvm-svn: 232254 --- clang/lib/AST/MicrosoftMangle.cpp | 2 +- .../microsoft-abi-virtual-member-pointers.cpp | 19 +++++++++++++++++++ .../microsoft-abi-vmemptr-conflicts.cpp | 6 +++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 6a0ebda7b33f..1b10fe3c2ebc 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -583,7 +583,7 @@ void MicrosoftCXXNameMangler::mangleVirtualMemPtrThunk( Out << "$B"; mangleNumber(OffsetInVFTable); Out << 'A'; - Out << (PointersAre64Bit ? 'A' : 'E'); + mangleCallingConvention(MD->getType()->getAs()); } void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp index 0479f6aa69fb..fe6468620b8c 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp @@ -18,6 +18,7 @@ struct C { virtual int bar(int, double); virtual S baz(int); virtual S qux(U); + virtual void thud(...); }; namespace { @@ -43,6 +44,9 @@ void f() { S (C::*ptr5)(U); ptr5 = &C::qux; + void (C::*ptr6)(...); + ptr6 = &C::thud; + // CHECK32-LABEL: define void @"\01?f@@YAXXZ"() // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr @@ -148,4 +152,19 @@ void f() { // CHECK64: ret void // CHECK64: } +// Thunk for calling the fifth virtual function in C which uses the __cdecl calling convention. +// CHECK32-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32: ret void +// CHECK32: } +// +// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4 +// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] +// CHECK64: musttail call void (%struct.C*, ...)* [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK64: ret void +// CHECK64: } + // CHECK32: #[[ATTR]] = {{{.*}}"thunk"{{.*}}} diff --git a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp index 896b768a93ed..0b00ef5b585d 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp @@ -93,9 +93,9 @@ void f(C *c) { } // CHECK-LABEL: define void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c) -// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AE" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}}) -// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AE" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}}) +// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}}) +// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}}) -// CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AE"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat +// CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat // CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...)* %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...) // CHECK-NEXT: ret void