forked from OSchip/llvm-project
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. llvm-svn: 215164
This commit is contained in:
parent
76e8af88b8
commit
b3e5654923
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<MemberPointerType>())
|
||||
return getCXXABI().isMemberPointerConvertible(MPT);
|
||||
|
||||
// If this isn't a tagged type, we can convert it!
|
||||
const TagType *TT = Ty->getAs<TagType>();
|
||||
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<RecordType>(TT);
|
||||
if (!RT) return true;
|
||||
|
|
|
@ -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<MSInheritanceAttr>() != nullptr;
|
||||
}
|
||||
|
||||
llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
|
||||
|
||||
llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -249,6 +249,25 @@ struct __virtual_inheritance D;
|
|||
struct D : virtual B {};
|
||||
}
|
||||
#ifdef VMB
|
||||
|
||||
namespace PR20017 {
|
||||
template <typename T>
|
||||
struct A {
|
||||
int T::*f();
|
||||
};
|
||||
|
||||
struct B;
|
||||
|
||||
auto a = &A<B>::f;
|
||||
|
||||
struct B {};
|
||||
|
||||
void q() {
|
||||
A<B> b;
|
||||
(b.*a)();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma pointers_to_members(full_generality, multiple_inheritance)
|
||||
struct TrulySingleInheritance;
|
||||
static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");
|
||||
|
|
Loading…
Reference in New Issue