From: David Majnemer Date: Thu, 20 Feb 2014 23:22:07 +0000 (+0000) Subject: Sema: Do not assert when dereferencing member pointer using virtual inheritance with... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c1f8c88ff426b317deb83ff7c2af0a21bb640d53;p=clang 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201824 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index e9e34b0a1a..72b84dc3e9 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -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); diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 6c89143c5f..1112739cc1 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -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. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 40ca588939..5ba748a88d 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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(); - 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()); } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 1e49d4ffd3..3f07e17b6c 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -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; diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index bd3305e9a2..a9090ee13c 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -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; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 572bb098c9..57ad9fb1ad 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -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(); @@ -2010,7 +2010,7 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, } if (VirtualBaseAdjustmentOffset) { - This = AdjustVirtualBase(CGF, RD, This, VirtualBaseAdjustmentOffset, + This = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 7624cee879..dd526490c1 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -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