diff options
Diffstat (limited to 'clang/lib/CodeGen/MicrosoftCXXABI.cpp')
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index ca06ad3f042b..e02c9ae0b8f2 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -617,6 +617,9 @@ private: llvm::Function *EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, const MethodVFTableLocation &ML); + llvm::Constant *EmitMemberDataPointer(const CXXRecordDecl *RD, + CharUnits offset); + public: llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override; @@ -2700,7 +2703,11 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, llvm::Constant * MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + return EmitMemberDataPointer(MPT->getMostRecentCXXRecordDecl(), offset); +} + +llvm::Constant *MicrosoftCXXABI::EmitMemberDataPointer(const CXXRecordDecl *RD, + CharUnits offset) { if (RD->getMSInheritanceModel() == MSInheritanceAttr::Keyword_virtual_inheritance) offset -= getContext().getOffsetOfBaseWithVBPtr(RD); @@ -2724,8 +2731,17 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) { C = EmitMemberFunctionPointer(MD); } else { + // For a pointer to data member, start off with the offset of the field in + // the class in which it was declared, and convert from there if necessary. + // For indirect field decls, get the outermost anonymous field and use the + // parent class. CharUnits FieldOffset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(MPD)); - C = EmitMemberDataPointer(DstTy, FieldOffset); + const FieldDecl *FD = dyn_cast<FieldDecl>(MPD); + if (!FD) + FD = cast<FieldDecl>(*cast<IndirectFieldDecl>(MPD)->chain_begin()); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(FD->getParent()); + RD = RD->getMostRecentNonInjectedDecl(); + C = EmitMemberDataPointer(RD, FieldOffset); } if (!MemberPointerPath.empty()) { |