summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/MicrosoftCXXABI.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 21:55:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 21:55:13 +0000
commitb96995b67f15110f39c41149543e19c8189abdaf (patch)
tree1971f6467f0c9a77b68ee72bcba9b89bbea52f08 /clang/lib/CodeGen/MicrosoftCXXABI.cpp
parentfa0a39b7ea7d26d220d018044055197a5284f2b5 (diff)
Diffstat (limited to 'clang/lib/CodeGen/MicrosoftCXXABI.cpp')
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index ca06ad3f042bb..e02c9ae0b8f2b 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()) {