summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-06-23 20:34:18 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-06-23 20:34:18 +0000
commit08ef2ba113d225db7348b7541a15f29c740b823c (patch)
treea67d71a4dba89186e496fa37492bb936d7e784b1 /clang
parente44dd6dbd06814e0d8d6b1497fb681c00fe8f2dc (diff)
downloadbcm5719-llvm-08ef2ba113d225db7348b7541a15f29c740b823c.tar.gz
bcm5719-llvm-08ef2ba113d225db7348b7541a15f29c740b823c.zip
[MS ABI] Account for the virtual inheritance quirk when mangling
Virtual inheritance member pointers are always relative to the vbindex, even when the member pointer doesn't point into a virtual base. This is corrected by adjusting the non-virtual offset backwards from the vbptr back to the top of the most derived class. While we performed this adjustment when manifesting member pointers as constants or when performing conversions, we didn't perform the adjustment when mangling them. llvm-svn: 240453
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h11
-rw-r--r--clang/lib/AST/ASTContext.cpp10
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp9
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp34
-rw-r--r--clang/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp12
5 files changed, 47 insertions, 29 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index da288c4fe5e..75334eabacb 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1780,6 +1780,17 @@ public:
/// \param method should be the declaration from the class definition
void setNonKeyFunction(const CXXMethodDecl *method);
+ /// Loading virtual member pointers using the virtual inheritance model
+ /// always results in an adjustment using the vbtable even if the index is
+ /// zero.
+ ///
+ /// This is usually OK because the first slot in the vbtable points
+ /// backwards to the top of the MDC. However, the MDC might be reusing a
+ /// vbptr from an nv-base. In this case, the first slot in the vbtable
+ /// points to the start of the nv-base which introduced the vbptr and *not*
+ /// the MDC. Modify the NonVirtualBaseAdjustment to account for this.
+ CharUnits getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const;
+
/// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
uint64_t getFieldOffset(const ValueDecl *FD) const;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 049eebd82b6..e88ea946e72 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1866,6 +1866,16 @@ CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const {
return toCharUnitsFromBits(getAlignOfGlobalVar(T));
}
+CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const {
+ CharUnits Offset = CharUnits::Zero();
+ const ASTRecordLayout *Layout = &getASTRecordLayout(RD);
+ while (const CXXRecordDecl *Base = Layout->getBaseSharingVBPtr()) {
+ Offset += Layout->getBaseClassOffset(Base);
+ Layout = &getASTRecordLayout(Base);
+ }
+ return Offset;
+}
+
/// DeepCollectObjCIvars -
/// This routine first collects all declared, but not synthesized, ivars in
/// super class and then collects all ivars, including those synthesized for
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 26894bb91eb..c50db60abe5 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -502,6 +502,9 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD,
FieldOffset /= getASTContext().getCharWidth();
VBTableOffset = 0;
+
+ if (IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+ FieldOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
@@ -570,6 +573,10 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
mangleName(MD);
mangleFunctionEncoding(MD, /*ShouldMangle=*/true);
}
+
+ if (VBTableOffset == 0 &&
+ IM == MSInheritanceAttr::Keyword_virtual_inheritance)
+ NVOffset -= getASTContext().getOffsetOfBaseWithVBPtr(RD).getQuantity();
} else {
// Null single inheritance member functions are encoded as a simple nullptr.
if (IM == MSInheritanceAttr::Keyword_single_inheritance) {
@@ -582,7 +589,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
}
if (MSInheritanceAttr::hasNVOffsetField(/*IsMemberFunction=*/true, IM))
- mangleNumber(NVOffset);
+ mangleNumber(static_cast<uint32_t>(NVOffset));
if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
mangleNumber(VBPtrOffset);
if (MSInheritanceAttr::hasVBTableOffsetField(IM))
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index fabdef3d158..de1d4dae69b 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2514,33 +2514,13 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
return llvm::ConstantStruct::getAnon(fields);
}
-// Loading virtual member pointers using the virtual inheritance model
-// always results in an adjustment using the vbtable even if the index is
-// zero.
-//
-// This is usually OK because the first slot in the vbtable points
-// backwards to the top of the MDC. However, the MDC might be reusing a
-// vbptr from an nv-base. In this case, the first slot in the vbtable
-// points to the start of the nv-base which introduced the vbptr and *not*
-// the MDC. Modify the NonVirtualBaseAdjustment to account for this.
-static CharUnits computeOffsetOfBaseWithVBPtr(const ASTContext &Ctx,
- const CXXRecordDecl *RD) {
- CharUnits Offset = CharUnits::Zero();
- const ASTRecordLayout *Layout = &Ctx.getASTRecordLayout(RD);
- while (const CXXRecordDecl *Base = Layout->getBaseSharingVBPtr()) {
- Offset += Layout->getBaseClassOffset(Base);
- Layout = &Ctx.getASTRecordLayout(Base);
- }
- return Offset;
-}
-
llvm::Constant *
MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
CharUnits offset) {
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
if (RD->getMSInheritanceModel() ==
MSInheritanceAttr::Keyword_virtual_inheritance)
- offset -= computeOffsetOfBaseWithVBPtr(getContext(), RD);
+ offset -= getContext().getOffsetOfBaseWithVBPtr(RD);
llvm::Constant *FirstField =
llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
@@ -2639,7 +2619,7 @@ MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
if (VBTableIndex == 0 &&
RD->getMSInheritanceModel() ==
MSInheritanceAttr::Keyword_virtual_inheritance)
- NonVirtualBaseAdjustment -= computeOffsetOfBaseWithVBPtr(getContext(), RD);
+ NonVirtualBaseAdjustment -= getContext().getOffsetOfBaseWithVBPtr(RD);
// The rest of the fields are common with data member pointers.
FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
@@ -2987,7 +2967,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
Builder.CreateICmpEQ(VirtualBaseAdjustmentOffset, getZeroInt());
if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
if (int64_t SrcOffsetToFirstVBase =
- computeOffsetOfBaseWithVBPtr(getContext(), SrcRD).getQuantity()) {
+ getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity()) {
llvm::Value *UndoSrcAdjustment = Builder.CreateSelect(
SrcVBIndexEqZero,
llvm::ConstantInt::get(CGM.IntTy, SrcOffsetToFirstVBase),
@@ -3049,7 +3029,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
// virtual base and the top of the MDC.
if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
if (int64_t DstOffsetToFirstVBase =
- computeOffsetOfBaseWithVBPtr(getContext(), DstRD).getQuantity()) {
+ getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity()) {
llvm::Value *DoDstAdjustment = Builder.CreateSelect(
DstVBIndexEqZero,
llvm::ConstantInt::get(CGM.IntTy, DstOffsetToFirstVBase),
@@ -3155,8 +3135,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
llvm::ICmpInst::ICMP_EQ, VirtualBaseAdjustmentOffset, getZeroInt());
if (SrcInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
llvm::Constant *SrcOffsetToFirstVBase = llvm::ConstantInt::get(
- CGM.IntTy,
- computeOffsetOfBaseWithVBPtr(getContext(), SrcRD).getQuantity());
+ CGM.IntTy, getContext().getOffsetOfBaseWithVBPtr(SrcRD).getQuantity());
llvm::Constant *UndoSrcAdjustment = llvm::ConstantExpr::getSelect(
SrcVBIndexEqZero, SrcOffsetToFirstVBase, getZeroInt());
NVAdjustField =
@@ -3219,8 +3198,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
// virtual base and the top of the MDC.
if (DstInheritance == MSInheritanceAttr::Keyword_virtual_inheritance) {
llvm::Constant *DstOffsetToFirstVBase = llvm::ConstantInt::get(
- CGM.IntTy,
- computeOffsetOfBaseWithVBPtr(getContext(), DstRD).getQuantity());
+ CGM.IntTy, getContext().getOffsetOfBaseWithVBPtr(DstRD).getQuantity());
llvm::Constant *DoDstAdjustment = llvm::ConstantExpr::getSelect(
DstVBIndexEqZero, DstOffsetToFirstVBase, getZeroInt());
NVAdjustField =
diff --git a/clang/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/clang/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
index 803cac3748b..42237f5b7d4 100644
--- a/clang/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp
@@ -141,3 +141,15 @@ void CallMethods() {
// CHECK: call {{.*}} @"\01??$CallMethod@UM@@$0A@@@YAXAAUM@@@Z"
// CHECK: call {{.*}} @"\01??$CallMethod@UV@@$0A@@@YAXAAUV@@@Z"
// CHECK: call {{.*}} @"\01??$CallMethod@UU@@$0A@@@YAXAAUU@@@Z"
+
+namespace NegativeNVOffset {
+struct A {};
+struct B : virtual A {};
+struct C : B {
+ virtual void f();
+};
+}
+
+template void CallMethod<NegativeNVOffset::C, &NegativeNVOffset::C::f>(NegativeNVOffset::C &);
+
+// CHECK-LABEL: define {{.*}} @"\01??$CallMethod@UC@NegativeNVOffset@@$I??_912@$BA@AEPPPPPPPM@A@@@YAXAAUC@NegativeNVOffset@@@Z"
OpenPOWER on IntegriCloud