From 84080ec16ede6a6fe85a1d991690c6bda82a59ee Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 29 Sep 2009 03:13:20 +0000 Subject: [PATCH] Handle CK_BaseToDerivedMemberPointer for member function pointers. Fixes PR5091. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83041 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXXClass.cpp | 33 +++++++++++++++++++++++---------- lib/CodeGen/CGExprAgg.cpp | 35 ++++++++++++++++++++++++++++++++++- lib/CodeGen/CodeGenFunction.h | 5 +++++ 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/CGCXXClass.cpp b/lib/CodeGen/CGCXXClass.cpp index 6d53e83e7c..5d7b8a022c 100644 --- a/lib/CodeGen/CGCXXClass.cpp +++ b/lib/CodeGen/CGCXXClass.cpp @@ -69,21 +69,38 @@ static uint64_t ComputeBaseClassOffset(ASTContext &Context, return Offset; } +llvm::Constant * +CodeGenFunction::GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + if (ClassDecl == BaseClassDecl) + return 0; + + QualType BTy = + getContext().getCanonicalType( + getContext().getTypeDeclType(const_cast(BaseClassDecl))); + + uint64_t Offset = ComputeBaseClassOffset(getContext(), + ClassDecl, BaseClassDecl); + if (!Offset) + return 0; + + const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); + + return llvm::ConstantInt::get(PtrDiffTy, Offset); +} + llvm::Value * CodeGenFunction::GetAddressCXXOfBaseClass(llvm::Value *BaseValue, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl, bool NullCheckValue) { - if (ClassDecl == BaseClassDecl) - return BaseValue; - + llvm::Constant *Offset = GetCXXBaseClassOffset(ClassDecl, BaseClassDecl); + QualType BTy = getContext().getCanonicalType( getContext().getTypeDeclType(const_cast(BaseClassDecl))); const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy)); - uint64_t Offset = ComputeBaseClassOffset(getContext(), - ClassDecl, BaseClassDecl); if (!Offset) { // Just cast back. return Builder.CreateBitCast(BaseValue, BasePtrTy); @@ -105,16 +122,12 @@ CodeGenFunction::GetAddressCXXOfBaseClass(llvm::Value *BaseValue, EmitBlock(CastNotNull); } - const llvm::Type *LongTy = - CGM.getTypes().ConvertType(CGM.getContext().LongTy); const llvm::Type *Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); - llvm::Value *OffsetVal = llvm::ConstantInt::get(LongTy, Offset); - // Apply the offset. BaseValue = Builder.CreateBitCast(BaseValue, Int8PtrTy); - BaseValue = Builder.CreateGEP(BaseValue, OffsetVal, "add.ptr"); + BaseValue = Builder.CreateGEP(BaseValue, Offset, "add.ptr"); // Cast back. BaseValue = Builder.CreateBitCast(BaseValue, BasePtrTy); diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 3bc8c12974..017efd3c88 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -200,7 +200,6 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; case CastExpr::CK_NullToMemberPointer: { - QualType T = E->getType(); const llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); @@ -213,6 +212,40 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { break; } + + case CastExpr::CK_BaseToDerivedMemberPointer: { + QualType SrcType = E->getSubExpr()->getType(); + + llvm::Value *Src = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(SrcType), + "tmp"); + CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified()); + + llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr"); + SrcPtr = Builder.CreateLoad(SrcPtr); + + llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj"); + SrcAdj = Builder.CreateLoad(SrcAdj); + + llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr"); + Builder.CreateStore(SrcPtr, DstPtr, VolatileDest); + + llvm::Value *DstAdj = Builder.CreateStructGEP(DestPtr, 1, "dst.adj"); + + // Now See if we need to update the adjustment. + const CXXRecordDecl *SrcDecl = + cast(SrcType->getAs()-> + getClass()->getAs()->getDecl()); + const CXXRecordDecl *DstDecl = + cast(E->getType()->getAs()-> + getClass()->getAs()->getDecl()); + + llvm::Constant *Adj = CGF.GetCXXBaseClassOffset(DstDecl, SrcDecl); + if (Adj) + SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj"); + + Builder.CreateStore(SrcAdj, DstAdj, VolatileDest); + break; + } } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 73cac24431..faad45ad96 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -589,6 +589,11 @@ public: const CXXRecordDecl *BaseClassDecl, bool NullCheckValue); + /// GetCXXBaseClassOffset - Returns the offset from a derived class to its + /// base class. Returns null if the offset is 0. + llvm::Constant *GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl); + void EmitClassAggrMemberwiseCopy(llvm::Value *DestValue, llvm::Value *SrcValue, const ArrayType *Array, -- 2.40.0