Sema: Do not assert when dereferencing member pointer using virtual inheritance with an incomplete class type
The MS ABI requires that we determine the vbptr offset if have a virtual inheritance model. Instead, raise an error pointing to the diagnostic when this happens. This fixes PR18583. Differential Revision: http://llvm-reviews.chandlerc.com/D2842 llvm-svn: 201824
This commit is contained in:
parent
af1465cef5
commit
2b0d66df24
|
@ -37,10 +37,9 @@ CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
|
|||
return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
|
||||
}
|
||||
|
||||
llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
|
||||
llvm::Value *MemPtr, const MemberPointerType *MPT) {
|
||||
ErrorUnsupportedABI(CGF, "calls through member pointers");
|
||||
|
||||
const FunctionProtoType *FPT =
|
||||
|
@ -52,10 +51,10 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|||
return llvm::Constant::getNullValue(FTy->getPointerTo());
|
||||
}
|
||||
|
||||
llvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *
|
||||
CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
|
||||
llvm::Value *Base, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
ErrorUnsupportedABI(CGF, "loads of member pointers");
|
||||
llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
|
||||
return llvm::Constant::getNullValue(Ty);
|
||||
|
|
|
@ -122,17 +122,15 @@ public:
|
|||
/// Load a member function from an object and a member function
|
||||
/// pointer. Apply the this-adjustment and set 'This' to the
|
||||
/// adjusted value.
|
||||
virtual llvm::Value *
|
||||
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
virtual llvm::Value *EmitLoadOfMemberFunctionPointer(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
|
||||
llvm::Value *MemPtr, const MemberPointerType *MPT);
|
||||
|
||||
/// Calculate an l-value from an object and a data member pointer.
|
||||
virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
virtual llvm::Value *
|
||||
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
|
||||
llvm::Value *Base, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
/// Perform a derived-to-base, base-to-derived, or bitcast member
|
||||
/// pointer conversion.
|
||||
|
|
|
@ -390,7 +390,7 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
|
|||
case SubobjectAdjustment::MemberPointerAdjustment: {
|
||||
llvm::Value *Ptr = EmitScalarExpr(Adjustment.Ptr.RHS);
|
||||
Object = CGM.getCXXABI().EmitMemberDataPointerAddress(
|
||||
*this, Object, Ptr, Adjustment.Ptr.MPT);
|
||||
*this, E, Object, Ptr, Adjustment.Ptr.MPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3239,8 +3239,8 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
|
|||
const MemberPointerType *MPT
|
||||
= E->getRHS()->getType()->getAs<MemberPointerType>();
|
||||
|
||||
llvm::Value *AddV =
|
||||
CGM.getCXXABI().EmitMemberDataPointerAddress(*this, BaseV, OffsetV, MPT);
|
||||
llvm::Value *AddV = CGM.getCXXABI().EmitMemberDataPointerAddress(
|
||||
*this, E, BaseV, OffsetV, MPT);
|
||||
|
||||
return MakeAddrLValue(AddV, MPT->getPointeeType());
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
|
|||
|
||||
// Ask the ABI to load the callee. Note that This is modified.
|
||||
llvm::Value *Callee =
|
||||
CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, This, MemFnPtr, MPT);
|
||||
CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This, MemFnPtr, MPT);
|
||||
|
||||
CallArgList Args;
|
||||
|
||||
|
|
|
@ -71,11 +71,12 @@ public:
|
|||
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
|
||||
|
||||
llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
const Expr *E,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemFnPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
@ -300,11 +301,9 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
|
|||
///
|
||||
/// If the member is non-virtual, memptr.ptr is the address of
|
||||
/// the function to call.
|
||||
llvm::Value *
|
||||
ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemFnPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
|
||||
llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
|
||||
CGBuilderTy &Builder = CGF.Builder;
|
||||
|
||||
const FunctionProtoType *FPT =
|
||||
|
@ -386,10 +385,9 @@ ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|||
|
||||
/// Compute an l-value by applying the given pointer-to-member to a
|
||||
/// base object.
|
||||
llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *Base, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
assert(MemPtr->getType() == CGM.PtrDiffTy);
|
||||
|
||||
CGBuilderTy &Builder = CGF.Builder;
|
||||
|
|
|
@ -302,8 +302,8 @@ private:
|
|||
|
||||
/// \brief Performs a full virtual base adjustment. Used to dereference
|
||||
/// pointers to members of virtual bases.
|
||||
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const CXXRecordDecl *RD,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const Expr *E,
|
||||
const CXXRecordDecl *RD, llvm::Value *Base,
|
||||
llvm::Value *VirtualBaseAdjustmentOffset,
|
||||
llvm::Value *VBPtrOffset /* optional */);
|
||||
|
||||
|
@ -353,10 +353,10 @@ public:
|
|||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
virtual llvm::Value *
|
||||
EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
|
||||
llvm::Value *Base, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
|
||||
const CastExpr *E,
|
||||
|
@ -366,9 +366,8 @@ public:
|
|||
llvm::Constant *Src);
|
||||
|
||||
virtual llvm::Value *
|
||||
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
|
||||
llvm::Value *&This, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT);
|
||||
|
||||
private:
|
||||
|
@ -1687,11 +1686,9 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
|
|||
|
||||
// Returns an adjusted base cast to i8*, since we do more address arithmetic on
|
||||
// it.
|
||||
llvm::Value *
|
||||
MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
|
||||
const CXXRecordDecl *RD, llvm::Value *Base,
|
||||
llvm::Value *VBTableOffset,
|
||||
llvm::Value *VBPtrOffset) {
|
||||
llvm::Value *MicrosoftCXXABI::AdjustVirtualBase(
|
||||
CodeGenFunction &CGF, const Expr *E, const CXXRecordDecl *RD,
|
||||
llvm::Value *Base, llvm::Value *VBTableOffset, llvm::Value *VBPtrOffset) {
|
||||
CGBuilderTy &Builder = CGF.Builder;
|
||||
Base = Builder.CreateBitCast(Base, CGM.Int8PtrTy);
|
||||
llvm::BasicBlock *OriginalBB = 0;
|
||||
|
@ -1717,7 +1714,14 @@ MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
|
|||
// know the vbptr offset.
|
||||
if (!VBPtrOffset) {
|
||||
CharUnits offs = CharUnits::Zero();
|
||||
if (RD->getNumVBases())
|
||||
if (!RD->hasDefinition()) {
|
||||
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"member pointer representation requires a "
|
||||
"complete class type for %0 to perform this expression");
|
||||
Diags.Report(E->getExprLoc(), DiagID) << RD << E->getSourceRange();
|
||||
} else if (RD->getNumVBases())
|
||||
offs = getContext().getASTRecordLayout(RD).getVBPtrOffset();
|
||||
VBPtrOffset = llvm::ConstantInt::get(CGM.IntTy, offs.getQuantity());
|
||||
}
|
||||
|
@ -1738,11 +1742,9 @@ MicrosoftCXXABI::AdjustVirtualBase(CodeGenFunction &CGF,
|
|||
return AdjustedBase;
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
||||
llvm::Value *Base,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *Base, llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
assert(MPT->isMemberDataPointer());
|
||||
unsigned AS = Base->getType()->getPointerAddressSpace();
|
||||
llvm::Type *PType =
|
||||
|
@ -1767,7 +1769,7 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
|
|||
}
|
||||
|
||||
if (VirtualBaseAdjustmentOffset) {
|
||||
Base = AdjustVirtualBase(CGF, RD, Base, VirtualBaseAdjustmentOffset,
|
||||
Base = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset,
|
||||
VBPtrOffset);
|
||||
}
|
||||
|
||||
|
@ -1975,11 +1977,9 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
|
|||
return llvm::ConstantStruct::getAnon(Fields);
|
||||
}
|
||||
|
||||
llvm::Value *
|
||||
MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
||||
llvm::Value *&This,
|
||||
llvm::Value *MemPtr,
|
||||
const MemberPointerType *MPT) {
|
||||
llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
|
||||
CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
|
||||
llvm::Value *MemPtr, const MemberPointerType *MPT) {
|
||||
assert(MPT->isMemberFunctionPointer());
|
||||
const FunctionProtoType *FPT =
|
||||
MPT->getPointeeType()->castAs<FunctionProtoType>();
|
||||
|
@ -2010,7 +2010,7 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
|
|||
}
|
||||
|
||||
if (VirtualBaseAdjustmentOffset) {
|
||||
This = AdjustVirtualBase(CGF, RD, This, VirtualBaseAdjustmentOffset,
|
||||
This = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset,
|
||||
VBPtrOffset);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
|
||||
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
|
||||
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
|
||||
// FIXME: Test x86_64 member pointers when codegen no longer asserts on records
|
||||
// with virtual bases.
|
||||
|
||||
#ifndef INCOMPLETE_VIRTUAL
|
||||
struct B1 {
|
||||
void foo();
|
||||
int b;
|
||||
|
@ -557,3 +560,15 @@ int *load_data(A *a, int A::*mp) {
|
|||
}
|
||||
|
||||
}
|
||||
#else
|
||||
struct __virtual_inheritance A;
|
||||
#ifdef MEMFUN
|
||||
int foo(A *a, int (A::*mp)()) {
|
||||
return (a->*mp)(); // expected-error{{requires a complete class type}}
|
||||
}
|
||||
#else
|
||||
int foo(A *a, int A::*mp) {
|
||||
return a->*mp; // expected-error{{requires a complete class type}}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue