aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r--lib/CodeGen/CGClass.cpp664
1 files changed, 211 insertions, 453 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 177e86230477..a604eef49a13 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -20,65 +20,61 @@ using namespace clang;
using namespace CodeGen;
static uint64_t
-ComputeNonVirtualBaseClassOffset(ASTContext &Context,
- const CXXBasePath &Path,
- unsigned Start) {
+ComputeNonVirtualBaseClassOffset(ASTContext &Context,
+ const CXXRecordDecl *DerivedClass,
+ CXXBaseSpecifierArray::iterator Start,
+ CXXBaseSpecifierArray::iterator End) {
uint64_t Offset = 0;
-
- for (unsigned i = Start, e = Path.size(); i != e; ++i) {
- const CXXBasePathElement& Element = Path[i];
+
+ const CXXRecordDecl *RD = DerivedClass;
+
+ for (CXXBaseSpecifierArray::iterator I = Start; I != End; ++I) {
+ const CXXBaseSpecifier *Base = *I;
+ assert(!Base->isVirtual() && "Should not see virtual bases here!");
// Get the layout.
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class);
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- const CXXBaseSpecifier *BS = Element.Base;
- assert(!BS->isVirtual() && "Should not see virtual bases here!");
-
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(BS->getType()->getAs<RecordType>()->getDecl());
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
// Add the offset.
- Offset += Layout.getBaseClassOffset(Base) / 8;
+ Offset += Layout.getBaseClassOffset(BaseDecl);
+
+ RD = BaseDecl;
}
-
- return Offset;
+
+ // FIXME: We should not use / 8 here.
+ return Offset / 8;
}
llvm::Constant *
-CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *Class,
- const CXXRecordDecl *BaseClass) {
- if (Class == BaseClass)
- return 0;
-
- CXXBasePaths Paths(/*FindAmbiguities=*/false,
- /*RecordPaths=*/true, /*DetectVirtual=*/false);
- if (!const_cast<CXXRecordDecl *>(Class)->
- isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClass), Paths)) {
- assert(false && "Class must be derived from the passed in base class!");
- return 0;
- }
+CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
+ const CXXBaseSpecifierArray &BasePath) {
+ assert(!BasePath.empty() && "Base path should not be empty!");
- uint64_t Offset = ComputeNonVirtualBaseClassOffset(getContext(),
- Paths.front(), 0);
+ uint64_t Offset =
+ ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
+ BasePath.begin(), BasePath.end());
if (!Offset)
return 0;
-
+
const llvm::Type *PtrDiffTy =
- Types.ConvertType(getContext().getPointerDiffType());
-
+ Types.ConvertType(getContext().getPointerDiffType());
+
return llvm::ConstantInt::get(PtrDiffTy, Offset);
}
-/// Gets the address of a virtual base class within a complete object.
+/// Gets the address of a direct base class within a complete object.
/// This should only be used for (1) non-virtual bases or (2) virtual bases
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
llvm::Value *
-CodeGenFunction::GetAddressOfBaseOfCompleteClass(llvm::Value *This,
- bool isBaseVirtual,
- const CXXRecordDecl *Derived,
- const CXXRecordDecl *Base) {
+CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This,
+ const CXXRecordDecl *Derived,
+ const CXXRecordDecl *Base,
+ bool BaseIsVirtual) {
// 'this' must be a pointer (in some address space) to Derived.
assert(This->getType()->isPointerTy() &&
cast<llvm::PointerType>(This->getType())->getElementType()
@@ -87,7 +83,7 @@ CodeGenFunction::GetAddressOfBaseOfCompleteClass(llvm::Value *This,
// Compute the offset of the virtual base.
uint64_t Offset;
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
- if (isBaseVirtual)
+ if (BaseIsVirtual)
Offset = Layout.getVBaseClassOffset(Base);
else
Offset = Layout.getBaseClassOffset(Base);
@@ -105,51 +101,63 @@ CodeGenFunction::GetAddressOfBaseOfCompleteClass(llvm::Value *This,
return V;
}
-llvm::Value *
-CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
- const CXXRecordDecl *Class,
- const CXXRecordDecl *BaseClass,
- bool NullCheckValue) {
- QualType BTy =
- getContext().getCanonicalType(
- getContext().getTypeDeclType(BaseClass));
- const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy));
-
- if (Class == BaseClass) {
- // Just cast back.
- return Builder.CreateBitCast(Value, BasePtrTy);
- }
+static llvm::Value *
+ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr,
+ uint64_t NonVirtual, llvm::Value *Virtual) {
+ const llvm::Type *PtrDiffTy =
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
+
+ llvm::Value *NonVirtualOffset = 0;
+ if (NonVirtual)
+ NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, NonVirtual);
+
+ llvm::Value *BaseOffset;
+ if (Virtual) {
+ if (NonVirtualOffset)
+ BaseOffset = CGF.Builder.CreateAdd(Virtual, NonVirtualOffset);
+ else
+ BaseOffset = Virtual;
+ } else
+ BaseOffset = NonVirtualOffset;
+
+ // Apply the base offset.
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ ThisPtr = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
+ ThisPtr = CGF.Builder.CreateGEP(ThisPtr, BaseOffset, "add.ptr");
- CXXBasePaths Paths(/*FindAmbiguities=*/false,
- /*RecordPaths=*/true, /*DetectVirtual=*/false);
- if (!const_cast<CXXRecordDecl *>(Class)->
- isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClass), Paths)) {
- assert(false && "Class must be derived from the passed in base class!");
- return 0;
- }
+ return ThisPtr;
+}
- unsigned Start = 0;
- llvm::Value *VirtualOffset = 0;
+llvm::Value *
+CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
+ const CXXRecordDecl *Derived,
+ const CXXBaseSpecifierArray &BasePath,
+ bool NullCheckValue) {
+ assert(!BasePath.empty() && "Base path should not be empty!");
- const CXXBasePath &Path = Paths.front();
+ CXXBaseSpecifierArray::iterator Start = BasePath.begin();
const CXXRecordDecl *VBase = 0;
- for (unsigned i = 0, e = Path.size(); i != e; ++i) {
- const CXXBasePathElement& Element = Path[i];
- if (Element.Base->isVirtual()) {
- Start = i+1;
- QualType VBaseType = Element.Base->getType();
- VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
- }
+
+ // Get the virtual base.
+ if ((*Start)->isVirtual()) {
+ VBase =
+ cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl());
+ ++Start;
}
+
+ uint64_t NonVirtualOffset =
+ ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
+ Start, BasePath.end());
- uint64_t Offset =
- ComputeNonVirtualBaseClassOffset(getContext(), Paths.front(), Start);
+ // Get the base pointer type.
+ const llvm::Type *BasePtrTy =
+ ConvertType((BasePath.end()[-1])->getType())->getPointerTo();
- if (!Offset && !VBase) {
+ if (!NonVirtualOffset && !VBase) {
// Just cast back.
return Builder.CreateBitCast(Value, BasePtrTy);
}
-
+
llvm::BasicBlock *CastNull = 0;
llvm::BasicBlock *CastNotNull = 0;
llvm::BasicBlock *CastEnd = 0;
@@ -165,28 +173,15 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
EmitBlock(CastNotNull);
}
-
+
+ llvm::Value *VirtualOffset = 0;
+
if (VBase)
- VirtualOffset = GetVirtualBaseClassOffset(Value, Class, VBase);
+ VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase);
- const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
- llvm::Value *NonVirtualOffset = 0;
- if (Offset)
- NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, Offset);
-
- llvm::Value *BaseOffset;
- if (VBase) {
- if (NonVirtualOffset)
- BaseOffset = Builder.CreateAdd(VirtualOffset, NonVirtualOffset);
- else
- BaseOffset = VirtualOffset;
- } else
- BaseOffset = NonVirtualOffset;
-
- // Apply the base offset.
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
- Value = Builder.CreateBitCast(Value, Int8PtrTy);
- Value = Builder.CreateGEP(Value, BaseOffset, "add.ptr");
+ // Apply the offsets.
+ Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
+ VirtualOffset);
// Cast back.
Value = Builder.CreateBitCast(Value, BasePtrTy);
@@ -210,21 +205,17 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
llvm::Value *
CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
- const CXXRecordDecl *Class,
- const CXXRecordDecl *DerivedClass,
+ const CXXRecordDecl *Derived,
+ const CXXBaseSpecifierArray &BasePath,
bool NullCheckValue) {
+ assert(!BasePath.empty() && "Base path should not be empty!");
+
QualType DerivedTy =
- getContext().getCanonicalType(
- getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(DerivedClass)));
+ getContext().getCanonicalType(getContext().getTagDeclType(Derived));
const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
- if (Class == DerivedClass) {
- // Just cast back.
- return Builder.CreateBitCast(Value, DerivedPtrTy);
- }
-
llvm::Value *NonVirtualOffset =
- CGM.GetNonVirtualBaseClassOffset(DerivedClass, Class);
+ CGM.GetNonVirtualBaseClassOffset(Derived, BasePath);
if (!NonVirtualOffset) {
// No offset, we can just cast back.
@@ -274,23 +265,16 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
/// EmitCopyCtorCall - Emit a call to a copy constructor.
static void
-EmitCopyCtorCall(CodeGenFunction &CGF,
- const CXXConstructorDecl *CopyCtor, CXXCtorType CopyCtorType,
- llvm::Value *ThisPtr, llvm::Value *VTT, llvm::Value *Src) {
- llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, CopyCtorType);
+EmitCopyCtorCall(CodeGenFunction &CGF, const CXXConstructorDecl *CopyCtor,
+ llvm::Value *ThisPtr, llvm::Value *Src) {
+ llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, Ctor_Complete);
CallArgList CallArgs;
// Push the this ptr.
CallArgs.push_back(std::make_pair(RValue::get(ThisPtr),
CopyCtor->getThisType(CGF.getContext())));
-
- // Push the VTT parameter if necessary.
- if (VTT) {
- QualType T = CGF.getContext().getPointerType(CGF.getContext().VoidPtrTy);
- CallArgs.push_back(std::make_pair(RValue::get(VTT), T));
- }
-
+
// Push the Src ptr.
CallArgs.push_back(std::make_pair(RValue::get(Src),
CopyCtor->getParamDecl(0)->getType()));
@@ -325,13 +309,8 @@ EmitCopyCtorCall(CodeGenFunction &CGF,
// FIXME. Consolidate this with EmitCXXAggrConstructorCall.
void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
llvm::Value *Src,
- const ArrayType *Array,
- const CXXRecordDecl *BaseClassDecl,
- QualType Ty) {
- const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
- assert(CA && "VLA cannot be copied over");
- bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor();
-
+ const ConstantArrayType *Array,
+ const CXXRecordDecl *ClassDecl) {
// Create a temporary for the loop index and initialize it with 0.
llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
"loop.index");
@@ -347,7 +326,7 @@ void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
llvm::BasicBlock *ForBody = createBasicBlock("for.body");
// Generate: if (loop-index < number-of-elements fall to the loop body,
// otherwise, go to the block after the for-loop.
- uint64_t NumElements = getContext().getConstantArrayElementCount(CA);
+ uint64_t NumElements = getContext().getConstantArrayElementCount(Array);
llvm::Value * NumElementsPtr =
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements);
llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
@@ -362,95 +341,8 @@ void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest,
Counter = Builder.CreateLoad(IndexPtr);
Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
- if (BitwiseCopy)
- EmitAggregateCopy(Dest, Src, Ty);
- else if (CXXConstructorDecl *BaseCopyCtor =
- BaseClassDecl->getCopyConstructor(getContext(), 0))
- EmitCopyCtorCall(*this, BaseCopyCtor, Ctor_Complete, Dest, 0, Src);
-
- EmitBlock(ContinueBlock);
-
- // Emit the increment of the loop counter.
- llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
- Counter = Builder.CreateLoad(IndexPtr);
- NextVal = Builder.CreateAdd(Counter, NextVal, "inc");
- Builder.CreateStore(NextVal, IndexPtr);
-
- // Finally, branch back up to the condition for the next iteration.
- EmitBranch(CondBlock);
-
- // Emit the fall-through block.
- EmitBlock(AfterFor, true);
-}
-
-/// EmitClassAggrCopyAssignment - This routine generates code to assign a class
-/// array of objects from SrcValue to DestValue. Assignment can be either a
-/// bitwise assignment or via a copy assignment operator function call.
-/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy
-void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
- llvm::Value *Src,
- const ArrayType *Array,
- const CXXRecordDecl *BaseClassDecl,
- QualType Ty) {
- const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array);
- assert(CA && "VLA cannot be asssigned");
- bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment();
-
- // Create a temporary for the loop index and initialize it with 0.
- llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext),
- "loop.index");
- llvm::Value* zeroConstant =
- llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext));
- Builder.CreateStore(zeroConstant, IndexPtr);
- // Start the loop with a block that tests the condition.
- llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
- llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
-
- EmitBlock(CondBlock);
-
- llvm::BasicBlock *ForBody = createBasicBlock("for.body");
- // Generate: if (loop-index < number-of-elements fall to the loop body,
- // otherwise, go to the block after the for-loop.
- uint64_t NumElements = getContext().getConstantArrayElementCount(CA);
- llvm::Value * NumElementsPtr =
- llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements);
- llvm::Value *Counter = Builder.CreateLoad(IndexPtr);
- llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr,
- "isless");
- // If the condition is true, execute the body.
- Builder.CreateCondBr(IsLess, ForBody, AfterFor);
-
- EmitBlock(ForBody);
- llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc");
- // Inside the loop body, emit the assignment operator call on array element.
- Counter = Builder.CreateLoad(IndexPtr);
- Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress");
- Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress");
- const CXXMethodDecl *MD = 0;
- if (BitwiseAssign)
- EmitAggregateCopy(Dest, Src, Ty);
- else {
- BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
- assert(MD && "EmitClassAggrCopyAssignment - No user assign");
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *LTy =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
- llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy);
-
- CallArgList CallArgs;
- // Push the this (Dest) ptr.
- CallArgs.push_back(std::make_pair(RValue::get(Dest),
- MD->getThisType(getContext())));
-
- // Push the Src ptr.
- QualType SrcTy = MD->getParamDecl(0)->getType();
- RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
- RValue::getAggregate(Src);
- CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
- EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
- Callee, ReturnValueSlot(), CallArgs, MD);
- }
+ EmitClassMemberwiseCopy(Dest, Src, ClassDecl);
+
EmitBlock(ContinueBlock);
// Emit the increment of the loop counter.
@@ -468,7 +360,8 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
-static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
+static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
+ bool ForVirtualBase) {
if (!CodeGenVTables::needsVTTParameter(GD)) {
// This constructor/destructor does not need a VTT parameter.
return 0;
@@ -486,9 +379,16 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
if (RD == Base) {
assert(!CodeGenVTables::needsVTTParameter(CGF.CurGD) &&
"doing no-op VTT offset in base dtor/ctor?");
+ assert(!ForVirtualBase && "Can't have same class as virtual base!");
SubVTTIndex = 0;
} else {
- SubVTTIndex = CGF.CGM.getVTables().getSubVTTIndex(RD, Base);
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(RD);
+ uint64_t BaseOffset = ForVirtualBase ?
+ Layout.getVBaseClassOffset(Base) : Layout.getBaseClassOffset(Base);
+
+ SubVTTIndex =
+ CGF.CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
}
@@ -511,75 +411,16 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
/// or via a copy constructor call.
void CodeGenFunction::EmitClassMemberwiseCopy(
llvm::Value *Dest, llvm::Value *Src,
- const CXXRecordDecl *ClassDecl,
- const CXXRecordDecl *BaseClassDecl, QualType Ty) {
- CXXCtorType CtorType = Ctor_Complete;
-
- if (ClassDecl) {
- Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
- Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
-
- // We want to call the base constructor.
- CtorType = Ctor_Base;
- }
- if (BaseClassDecl->hasTrivialCopyConstructor()) {
- EmitAggregateCopy(Dest, Src, Ty);
+ const CXXRecordDecl *ClassDecl) {
+ if (ClassDecl->hasTrivialCopyConstructor()) {
+ EmitAggregateCopy(Dest, Src, getContext().getTagDeclType(ClassDecl));
return;
}
- CXXConstructorDecl *BaseCopyCtor =
- BaseClassDecl->getCopyConstructor(getContext(), 0);
- if (!BaseCopyCtor)
- return;
+ CXXConstructorDecl *CopyCtor = ClassDecl->getCopyConstructor(getContext(), 0);
+ assert(CopyCtor && "Did not have copy ctor!");
- llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(BaseCopyCtor, CtorType));
- EmitCopyCtorCall(*this, BaseCopyCtor, CtorType, Dest, VTT, Src);
-}
-
-/// EmitClassCopyAssignment - This routine generates code to copy assign a class
-/// object from SrcValue to DestValue. Assignment can be either a bitwise
-/// assignment of via an assignment operator call.
-// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot.
-void CodeGenFunction::EmitClassCopyAssignment(
- llvm::Value *Dest, llvm::Value *Src,
- const CXXRecordDecl *ClassDecl,
- const CXXRecordDecl *BaseClassDecl,
- QualType Ty) {
- if (ClassDecl) {
- Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
- Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
- }
- if (BaseClassDecl->hasTrivialCopyAssignment()) {
- EmitAggregateCopy(Dest, Src, Ty);
- return;
- }
-
- const CXXMethodDecl *MD = 0;
- BaseClassDecl->hasConstCopyAssignment(getContext(), MD);
- assert(MD && "EmitClassCopyAssignment - missing copy assign");
-
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *LTy =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
- llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy);
-
- CallArgList CallArgs;
- // Push the this (Dest) ptr.
- CallArgs.push_back(std::make_pair(RValue::get(Dest),
- MD->getThisType(getContext())));
-
- // Push the Src ptr.
- QualType SrcTy = MD->getParamDecl(0)->getType();
- RValue SrcValue = SrcTy->isReferenceType() ? RValue::get(Src) :
- RValue::getAggregate(Src);
- CallArgs.push_back(std::make_pair(SrcValue, SrcTy));
- EmitCall(CGM.getTypes().getFunctionInfo(CallArgs, FPT),
- Callee, ReturnValueSlot(), CallArgs, MD);
+ EmitCopyCtorCall(*this, CopyCtor, Dest, Src);
}
/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a
@@ -600,30 +441,25 @@ void CodeGenFunction::EmitClassCopyAssignment(
void
CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) {
const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
+ CXXCtorType CtorType = CurGD.getCtorType();
+ (void) CtorType;
+
const CXXRecordDecl *ClassDecl = Ctor->getParent();
assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
"SynthesizeCXXCopyConstructor - copy constructor has definition already");
assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");
- FunctionArgList::const_iterator i = Args.begin();
- const VarDecl *ThisArg = i->first;
- llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg);
- llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this");
- const VarDecl *SrcArg = (i+1)->first;
- llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg);
- llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj);
-
- for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- // FIXME. copy constrution of virtual base NYI
- if (Base->isVirtual())
- continue;
+ llvm::Value *ThisPtr = LoadCXXThis();
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl,
- Base->getType());
- }
+ // Find the source pointer.
+ unsigned SrcArgIndex = Args.size() - 1;
+ assert(CtorType == Ctor_Base || SrcArgIndex == 1);
+ assert(CtorType != Ctor_Base ||
+ (ClassDecl->getNumVBases() != 0 && SrcArgIndex == 2) ||
+ SrcArgIndex == 1);
+
+ llvm::Value *SrcPtr =
+ Builder.CreateLoad(GetAddrOfLocalVar(Args[SrcArgIndex].first));
for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
E = ClassDecl->field_end(); I != E; ++I) {
@@ -638,27 +474,26 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) {
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
- LValue LHS = EmitLValueForField(LoadOfThis, Field, 0);
- LValue RHS = EmitLValueForField(LoadOfSrc, Field, 0);
+ LValue LHS = EmitLValueForField(ThisPtr, Field, 0);
+ LValue RHS = EmitLValueForField(SrcPtr, Field, 0);
if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ const llvm::Type *BasePtr = ConvertType(FieldType)->getPointerTo();
llvm::Value *DestBaseAddrPtr =
Builder.CreateBitCast(LHS.getAddress(), BasePtr);
llvm::Value *SrcBaseAddrPtr =
Builder.CreateBitCast(RHS.getAddress(), BasePtr);
EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
- FieldClassDecl, FieldType);
+ FieldClassDecl);
}
else
EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(),
- 0 /*ClassDecl*/, FieldClassDecl, FieldType);
+ FieldClassDecl);
continue;
}
// Do a built-in assignment of scalar data members.
- LValue LHS = EmitLValueForFieldInitialization(LoadOfThis, Field, 0);
- LValue RHS = EmitLValueForFieldInitialization(LoadOfSrc, Field, 0);
+ LValue LHS = EmitLValueForFieldInitialization(ThisPtr, Field, 0);
+ LValue RHS = EmitLValueForFieldInitialization(SrcPtr, Field, 0);
if (!hasAggregateLLVMType(Field->getType())) {
RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
@@ -675,100 +510,6 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) {
InitializeVTablePointers(ClassDecl);
}
-/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator.
-/// Before the implicitly-declared copy assignment operator for a class is
-/// implicitly defined, all implicitly- declared copy assignment operators for
-/// its direct base classes and its nonstatic data members shall have been
-/// implicitly defined. [12.8-p12]
-/// The implicitly-defined copy assignment operator for class X performs
-/// memberwise assignment of its subob- jects. The direct base classes of X are
-/// assigned first, in the order of their declaration in
-/// the base-specifier-list, and then the immediate nonstatic data members of X
-/// are assigned, in the order in which they were declared in the class
-/// definition.Each subobject is assigned in the manner appropriate to its type:
-/// if the subobject is of class type, the copy assignment operator for the
-/// class is used (as if by explicit qualification; that is, ignoring any
-/// possible virtual overriding functions in more derived classes);
-///
-/// if the subobject is an array, each element is assigned, in the manner
-/// appropriate to the element type;
-///
-/// if the subobject is of scalar type, the built-in assignment operator is
-/// used.
-void CodeGenFunction::SynthesizeCXXCopyAssignment(const FunctionArgList &Args) {
- const CXXMethodDecl *CD = cast<CXXMethodDecl>(CurGD.getDecl());
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
- assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
- "SynthesizeCXXCopyAssignment - copy assignment has user declaration");
-
- FunctionArgList::const_iterator i = Args.begin();
- const VarDecl *ThisArg = i->first;
- llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg);
- llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this");
- const VarDecl *SrcArg = (i+1)->first;
- llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg);
- llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj);
-
- for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
- // FIXME. copy assignment of virtual base NYI
- if (Base->isVirtual())
- continue;
-
- CXXRecordDecl *BaseClassDecl
- = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl,
- Base->getType());
- }
-
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
- FieldEnd = ClassDecl->field_end();
- Field != FieldEnd; ++Field) {
- QualType FieldType = getContext().getCanonicalType((*Field)->getType());
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(FieldType);
- if (Array)
- FieldType = getContext().getBaseElementType(FieldType);
-
- if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
- CXXRecordDecl *FieldClassDecl
- = cast<CXXRecordDecl>(FieldClassType->getDecl());
- LValue LHS = EmitLValueForField(LoadOfThis, *Field, 0);
- LValue RHS = EmitLValueForField(LoadOfSrc, *Field, 0);
- if (Array) {
- const llvm::Type *BasePtr = ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *DestBaseAddrPtr =
- Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- llvm::Value *SrcBaseAddrPtr =
- Builder.CreateBitCast(RHS.getAddress(), BasePtr);
- EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array,
- FieldClassDecl, FieldType);
- }
- else
- EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(),
- 0 /*ClassDecl*/, FieldClassDecl, FieldType);
- continue;
- }
- // Do a built-in assignment of scalar data members.
- LValue LHS = EmitLValueForField(LoadOfThis, *Field, 0);
- LValue RHS = EmitLValueForField(LoadOfSrc, *Field, 0);
- if (!hasAggregateLLVMType(Field->getType())) {
- RValue RVRHS = EmitLoadOfLValue(RHS, Field->getType());
- EmitStoreThroughLValue(RVRHS, LHS, Field->getType());
- } else if (Field->getType()->isAnyComplexType()) {
- ComplexPairTy Pair = LoadComplexFromAddr(RHS.getAddress(),
- RHS.isVolatileQualified());
- StoreComplexToAddr(Pair, LHS.getAddress(), LHS.isVolatileQualified());
- } else {
- EmitAggregateCopy(LHS.getAddress(), RHS.getAddress(), Field->getType());
- }
- }
-
- // return *this;
- Builder.CreateStore(LoadOfThis, ReturnValue);
-}
-
static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXBaseOrMemberInitializer *BaseInit,
@@ -782,15 +523,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- // FIXME: This method of determining whether a base is virtual is ridiculous;
- // it should be part of BaseInit.
- bool isBaseVirtual = false;
- for (CXXRecordDecl::base_class_const_iterator I = ClassDecl->vbases_begin(),
- E = ClassDecl->vbases_end(); I != E; ++I)
- if (I->getType()->getAs<RecordType>()->getDecl() == BaseClassDecl) {
- isBaseVirtual = true;
- break;
- }
+ bool isBaseVirtual = BaseInit->isBaseVirtual();
// The base constructor doesn't construct virtual bases.
if (CtorType == Ctor_Base && isBaseVirtual)
@@ -798,9 +531,10 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
// We can pretend to be a complete class because it only matters for
// virtual bases, and we only do virtual bases for complete ctors.
- llvm::Value *V = ThisPtr;
- V = CGF.GetAddressOfBaseOfCompleteClass(V, isBaseVirtual,
- ClassDecl, BaseClassDecl);
+ llvm::Value *V =
+ CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
+ BaseClassDecl,
+ BaseInit->isBaseVirtual());
CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
@@ -809,7 +543,7 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
CodeGenFunction::EHCleanupBlock Cleanup(CGF);
CXXDestructorDecl *DD = BaseClassDecl->getDestructor(CGF.getContext());
- CGF.EmitCXXDestructorCall(DD, Dtor_Base, V);
+ CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V);
}
}
@@ -850,7 +584,9 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
LHS.isVolatileQualified());
} else {
CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(),
- LHS.isVolatileQualified(), false, true);
+ LHS.isVolatileQualified(),
+ /*IgnoreResult*/ false,
+ /*IsInitializer*/ true);
if (!CGF.Exceptions)
return;
@@ -868,7 +604,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
CXXDestructorDecl *DD = RD->getDestructor(CGF.getContext());
- CGF.EmitCXXDestructorCall(DD, Dtor_Complete, LHS.getAddress());
+ CGF.EmitCXXDestructorCall(DD, Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
}
}
}
@@ -976,8 +713,6 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> MemberInitializers;
- // FIXME: Add vbase initialization
-
for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
E = CD->init_end();
B != E; ++B) {
@@ -1028,7 +763,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// variant, then call the appropriate operator delete() on the way
// out.
if (DtorType == Dtor_Deleting) {
- EmitCXXDestructorCall(Dtor, Dtor_Complete, LoadCXXThis());
+ EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ LoadCXXThis());
SkipBody = true;
// If this is the complete variant, just invoke the base variant;
@@ -1036,7 +772,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// this optimization if the body is a function-try-block, because
// we'd introduce *two* handler blocks.
} else if (!isTryBody && DtorType == Dtor_Complete) {
- EmitCXXDestructorCall(Dtor, Dtor_Base, LoadCXXThis());
+ EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
+ LoadCXXThis());
SkipBody = true;
// Otherwise, we're in the base variant, so we need to ensure the
@@ -1117,11 +854,11 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
if (BaseClassDecl->hasTrivialDestructor())
continue;
const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
- llvm::Value *V = GetAddressOfBaseOfCompleteClass(LoadCXXThis(),
- true,
- ClassDecl,
- BaseClassDecl);
- EmitCXXDestructorCall(D, Dtor_Base, V);
+ llvm::Value *V =
+ GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(),
+ ClassDecl, BaseClassDecl,
+ /*BaseIsVirtual=*/true);
+ EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/true, V);
}
return;
}
@@ -1175,7 +912,8 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
Array, BaseAddrPtr);
} else
EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()),
- Dtor_Complete, LHS.getAddress());
+ Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
}
// Destroy non-virtual bases.
@@ -1193,12 +931,14 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
// Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
- const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
-
- llvm::Value *V = GetAddressOfBaseClass(LoadCXXThis(),
- ClassDecl, BaseClassDecl,
- /*NullCheckValue=*/false);
- EmitCXXDestructorCall(D, Dtor_Base, V);
+
+ const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext());
+ llvm::Value *V =
+ GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(), ClassDecl,
+ BaseClassDecl,
+ /*BaseIsVirtual=*/false);
+
+ EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/false, V);
}
}
@@ -1271,7 +1011,8 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
{
CXXTemporariesCleanupScope Scope(*this);
- EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd);
+ EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address,
+ ArgBeg, ArgEnd);
}
EmitBlock(ContinueBlock);
@@ -1345,7 +1086,7 @@ CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
Counter = Builder.CreateLoad(IndexPtr);
Counter = Builder.CreateSub(Counter, One);
llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx");
- EmitCXXDestructorCall(D, Dtor_Complete, Address);
+ EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Address);
EmitBlock(ContinueBlock);
@@ -1390,6 +1131,7 @@ CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
getContext().getTranslationUnitDecl(),
SourceLocation(), II, R, 0,
FunctionDecl::Static,
+ FunctionDecl::None,
false, true);
StartFunction(FD, R, Fn, Args, SourceLocation());
QualType BaseElementTy = getContext().getBaseElementType(Array);
@@ -1407,7 +1149,7 @@ CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
void
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
- CXXCtorType Type,
+ CXXCtorType Type, bool ForVirtualBase,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
@@ -1429,7 +1171,7 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
return;
}
- llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type));
+ llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase);
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
@@ -1450,7 +1192,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
++I;
// vtt
- if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType))) {
+ if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType),
+ /*ForVirtualBase=*/false)) {
QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP));
@@ -1502,8 +1245,10 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
+ bool ForVirtualBase,
llvm::Value *This) {
- llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type));
+ llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type),
+ ForVirtualBase);
llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0);
@@ -1538,7 +1283,8 @@ CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This,
void
CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
- bool BaseIsMorallyVirtual,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
llvm::Constant *VTable,
const CXXRecordDecl *VTableClass) {
const CXXRecordDecl *RD = Base.getBase();
@@ -1548,7 +1294,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
// Check if we need to use a vtable from the VTT.
if (CodeGenVTables::needsVTTParameter(CurGD) &&
- (RD->getNumVBases() || BaseIsMorallyVirtual)) {
+ (RD->getNumVBases() || NearestVBase)) {
// Get the secondary vpointer index.
uint64_t VirtualPointerIndex =
CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base);
@@ -1567,20 +1313,27 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
}
// Compute where to store the address point.
- llvm::Value *VTableField;
+ llvm::Value *VirtualOffset = 0;
+ uint64_t NonVirtualOffset = 0;
- if (CodeGenVTables::needsVTTParameter(CurGD) && BaseIsMorallyVirtual) {
+ if (CodeGenVTables::needsVTTParameter(CurGD) && NearestVBase) {
// We need to use the virtual base offset offset because the virtual base
// might have a different offset in the most derived class.
- VTableField = GetAddressOfBaseClass(LoadCXXThis(), VTableClass, RD,
- /*NullCheckValue=*/false);
+ VirtualOffset = GetVirtualBaseClassOffset(LoadCXXThis(), VTableClass,
+ NearestVBase);
+ NonVirtualOffset = OffsetFromNearestVBase / 8;
} else {
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
-
- VTableField = Builder.CreateBitCast(LoadCXXThis(), Int8PtrTy);
- VTableField =
- Builder.CreateConstInBoundsGEP1_64(VTableField, Base.getBaseOffset() / 8);
+ // We can just use the base offset in the complete class.
+ NonVirtualOffset = Base.getBaseOffset() / 8;
}
+
+ // Apply the offsets.
+ llvm::Value *VTableField = LoadCXXThis();
+
+ if (NonVirtualOffset || VirtualOffset)
+ VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField,
+ NonVirtualOffset,
+ VirtualOffset);
// Finally, store the address point.
const llvm::Type *AddressPointPtrTy =
@@ -1591,7 +1344,8 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
void
CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
- bool BaseIsMorallyVirtual,
+ const CXXRecordDecl *NearestVBase,
+ uint64_t OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
llvm::Constant *VTable,
const CXXRecordDecl *VTableClass,
@@ -1600,7 +1354,8 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
// been set.
if (!BaseIsNonVirtualPrimaryBase) {
// Initialize the vtable pointer for this base.
- InitializeVTablePointer(Base, BaseIsMorallyVirtual, VTable, VTableClass);
+ InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
+ VTable, VTableClass);
}
const CXXRecordDecl *RD = Base.getBase();
@@ -1616,7 +1371,7 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
continue;
uint64_t BaseOffset;
- bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual;
+ uint64_t BaseOffsetFromNearestVBase;
bool BaseDeclIsNonVirtualPrimaryBase;
if (I->isVirtual()) {
@@ -1628,17 +1383,20 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
getContext().getASTRecordLayout(VTableClass);
BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
- BaseDeclIsMorallyVirtual = true;
+ BaseOffsetFromNearestVBase = 0;
BaseDeclIsNonVirtualPrimaryBase = false;
} else {
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
+ BaseOffsetFromNearestVBase =
+ OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
}
InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
- BaseDeclIsMorallyVirtual,
+ I->isVirtual() ? BaseDecl : NearestVBase,
+ BaseOffsetFromNearestVBase,
BaseDeclIsNonVirtualPrimaryBase,
VTable, VTableClass, VBases);
}
@@ -1654,8 +1412,8 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
// Initialize the vtable pointers for this class and all of its bases.
VisitedVirtualBasesSetTy VBases;
- InitializeVTablePointers(BaseSubobject(RD, 0),
- /*BaseIsMorallyVirtual=*/false,
+ InitializeVTablePointers(BaseSubobject(RD, 0), /*NearestVBase=*/0,
+ /*OffsetFromNearestVBase=*/0,
/*BaseIsNonVirtualPrimaryBase=*/false,
VTable, RD, VBases);
}