From 3b03114d3df351fccec48be6a8c8717366ca889b Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 11 Jun 2015 00:20:57 +0000 Subject: [PATCH] [MS ABI] Allow memfn pointers with unconvertible types to be formed Remove the restriction which forbade forming pointers to member functions which had parameter types or return types which were not convertible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@239499 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MicrosoftCXXABI.cpp | 7 +----- .../microsoft-abi-virtual-member-pointers.cpp | 23 +++++++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index de30883c54..bb95a123c5 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2423,12 +2423,7 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD, FirstField = CGM.GetAddrOfFunction(MD, Ty); FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy); } else { - if (!CGM.getTypes().isFuncTypeConvertible( - MD->getType()->castAs())) { - CGM.ErrorUnsupported(MD, "pointer to virtual member function with " - "incomplete return or parameter type"); - FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy); - } else if (FPT->getCallConv() == CC_X86FastCall) { + if (FPT->getCallConv() == CC_X86FastCall) { CGM.ErrorUnsupported(MD, "pointer to fastcall virtual member function"); FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy); } else { diff --git a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp index f6f75835c6..eb5f90dc86 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32 -// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64 +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32 +// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64 struct S { int x, y, z; @@ -13,12 +13,15 @@ struct U { U(const U &); }; +struct B; + struct C { virtual void foo(); virtual int bar(int, double); virtual S baz(int); virtual S qux(U); virtual void thud(...); + virtual void (B::*plugh())(); }; namespace { @@ -47,6 +50,8 @@ void f() { void (C::*ptr6)(...); ptr6 = &C::thud; + auto ptr7 = &C::plugh; + // CHECK32-LABEL: define void @"\01?f@@YAXXZ"() // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr @@ -167,4 +172,18 @@ void f() { // CHECK64: ret void // CHECK64: } +// CHECK32: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 { +// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %vtable, i64 5 +// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] +// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) +// CHECK32: ret void +// CHECK32: } + +// CHECK64: define linkonce_odr void @"\01??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { +// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %vtable, i64 5 +// 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"{{.*}}} -- 2.40.0