From c137a233c54664d277eb810e5d7aaa2971673d12 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 7 Aug 2014 22:56:13 +0000 Subject: [PATCH] MS ABI: Handle member function pointers returning a member data pointer MSVC doesn't decide what the inheritance model for a returned member pointer *until* a call expression returns it. This fixes PR20017. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215164 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXXABI.h | 5 +++++ lib/CodeGen/CodeGenTypes.cpp | 7 ++++++- lib/CodeGen/MicrosoftCXXABI.cpp | 5 +++++ lib/Sema/SemaOverload.cpp | 4 ++++ test/SemaCXX/member-pointer-ms.cpp | 19 +++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 91e49707ba..40418b60c1 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -156,6 +156,11 @@ public: /// (in the C++ sense) with an LLVM zeroinitializer. virtual bool isZeroInitializable(const MemberPointerType *MPT); + /// Return whether or not a member pointers type is convertible to an IR type. + virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const { + return true; + } + /// Create a null member pointer of the given type. virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index d4e22623e0..6b0e4ad8b3 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -187,6 +187,11 @@ static bool isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT) { /// we've temporarily deferred expanding the type because we're in a recursive /// context. bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) { + // Some ABIs cannot have their member pointers represented in IR unless + // certain circumstances have been reached. + if (const auto *MPT = Ty->getAs()) + return getCXXABI().isMemberPointerConvertible(MPT); + // If this isn't a tagged type, we can convert it! const TagType *TT = Ty->getAs(); if (!TT) return true; @@ -194,7 +199,7 @@ bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) { // Incomplete types cannot be converted. if (TT->isIncompleteType()) return false; - + // If this is an enum, then it is always safe to convert. const RecordType *RT = dyn_cast(TT); if (!RT) return true; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 23f9768d4a..d01fb7bf34 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -482,6 +482,11 @@ public: bool isZeroInitializable(const MemberPointerType *MPT) override; + bool isMemberPointerConvertible(const MemberPointerType *MPT) const override { + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + return RD->getAttr() != nullptr; + } + llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override; llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e13fd14fd8..d719b84c96 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11353,6 +11353,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << (qualsString.find(' ') == std::string::npos ? 1 : 2); } + if (resultType->isMemberPointerType()) + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) + RequireCompleteType(LParenLoc, resultType, 0); + CXXMemberCallExpr *call = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, resultType, valueKind, RParenLoc); diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp index e7c4ae9409..39cf601dc9 100644 --- a/test/SemaCXX/member-pointer-ms.cpp +++ b/test/SemaCXX/member-pointer-ms.cpp @@ -249,6 +249,25 @@ struct __virtual_inheritance D; struct D : virtual B {}; } #ifdef VMB + +namespace PR20017 { +template +struct A { + int T::*f(); +}; + +struct B; + +auto a = &A::f; + +struct B {}; + +void q() { + A b; + (b.*a)(); +} +} + #pragma pointers_to_members(full_generality, multiple_inheritance) struct TrulySingleInheritance; static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, ""); -- 2.40.0