diff options
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 119 |
1 files changed, 43 insertions, 76 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 0ee74c01dcc..fea72f6818e 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1806,14 +1806,12 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, bool ForVirtualBase, bool Delegating, llvm::Value *This, const CXXConstructExpr *E) { - const CXXRecordDecl *ClassDecl = D->getParent(); - // C++11 [class.mfct.non-static]p2: // If a non-static member function of a class X is called for an object that // is not of type X, or of a type derived from X, the behavior is undefined. // FIXME: Provide a source location here. EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), This, - getContext().getRecordType(ClassDecl)); + getContext().getRecordType(D->getParent())); if (D->isTrivial() && D->isDefaultConstructor()) { assert(E->getNumArgs() == 0 && "trivial default ctor with args"); @@ -1829,7 +1827,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const Expr *Arg = E->getArg(0); QualType SrcTy = Arg->getType(); llvm::Value *Src = EmitLValue(Arg).getAddress(); - QualType DestTy = getContext().getTypeDeclType(ClassDecl); + QualType DestTy = getContext().getTypeDeclType(D->getParent()); EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); return; } @@ -1852,41 +1850,6 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs); EmitCall(Info, Callee, ReturnValueSlot(), Args, D); - - // Generate vtable assumptions if we're constructing a complete object - // with a vtable. We don't do this for base subobjects for two reasons: - // first, it's incorrect for classes with virtual bases, and second, we're - // about to overwrite the vptrs anyway. - if (CGM.getCodeGenOpts().OptimizationLevel > 0 && - ClassDecl->isDynamicClass() && Type != Ctor_Base) - EmitVTableAssumptionLoads(ClassDecl, This); -} - -void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, - llvm::Value *This) { - llvm::Value *VTableGlobal = - CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass); - if (!VTableGlobal) - return; - - // We can just use the base offset in the complete class. - CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset(); - - if (!NonVirtualOffset.isZero()) - This = - ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr); - - llvm::Value *VPtrValue = GetVTablePtr(This, VTableGlobal->getType()); - llvm::Value *Cmp = - Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables"); - Builder.CreateAssumption(Cmp); -} - -void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, - llvm::Value *This) { - if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl)) - for (const VPtr &Vptr : getVTablePointers(ClassDecl)) - EmitVTableAssumptionLoad(Vptr, This); } void @@ -2054,12 +2017,24 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) { PushDestructorCleanup(D, Addr); } -void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { +void +CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, + const CXXRecordDecl *NearestVBase, + CharUnits OffsetFromNearestVBase, + const CXXRecordDecl *VTableClass) { + const CXXRecordDecl *RD = Base.getBase(); + + // Don't initialize the vtable pointer if the class is marked with the + // 'novtable' attribute. + if ((RD == VTableClass || RD == NearestVBase) && + VTableClass->hasAttr<MSNoVTableAttr>()) + return; + // Compute the address point. + bool NeedsVirtualOffset; llvm::Value *VTableAddressPoint = CGM.getCXXABI().getVTableAddressPointInStructor( - *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase); - + *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset); if (!VTableAddressPoint) return; @@ -2067,15 +2042,17 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { llvm::Value *VirtualOffset = nullptr; CharUnits NonVirtualOffset = CharUnits::Zero(); - if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) { + if (NeedsVirtualOffset) { // We need to use the virtual base offset offset because the virtual base // might have a different offset in the most derived class. - VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset( - *this, LoadCXXThis(), Vptr.VTableClass, Vptr.NearestVBase); - NonVirtualOffset = Vptr.OffsetFromNearestVBase; + VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this, + LoadCXXThis(), + VTableClass, + NearestVBase); + NonVirtualOffset = OffsetFromNearestVBase; } else { // We can just use the base offset in the complete class. - NonVirtualOffset = Vptr.Base.getBaseOffset(); + NonVirtualOffset = Base.getBaseOffset(); } // Apply the offsets. @@ -2094,36 +2071,23 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { ->getPointerTo(); VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo()); VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy); - llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField); CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr()); } -CodeGenFunction::VPtrsVector -CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) { - CodeGenFunction::VPtrsVector VPtrsResult; - VisitedVirtualBasesSetTy VBases; - getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()), - /*NearestVBase=*/nullptr, - /*OffsetFromNearestVBase=*/CharUnits::Zero(), - /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases, - VPtrsResult); - return VPtrsResult; -} - -void CodeGenFunction::getVTablePointers(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - bool BaseIsNonVirtualPrimaryBase, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy &VBases, - VPtrsVector &Vptrs) { +void +CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, + const CXXRecordDecl *NearestVBase, + CharUnits OffsetFromNearestVBase, + bool BaseIsNonVirtualPrimaryBase, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy& VBases) { // If this base is a non-virtual primary base the address point has already // been set. if (!BaseIsNonVirtualPrimaryBase) { // Initialize the vtable pointer for this base. - VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass}; - Vptrs.push_back(Vptr); + InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase, + VTableClass); } const CXXRecordDecl *RD = Base.getBase(); @@ -2161,10 +2125,11 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base, BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; } - getVTablePointers( - BaseSubobject(BaseDecl, BaseOffset), - I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase, - BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs); + InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), + I.isVirtual() ? BaseDecl : NearestVBase, + BaseOffsetFromNearestVBase, + BaseDeclIsNonVirtualPrimaryBase, + VTableClass, VBases); } } @@ -2174,9 +2139,11 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { return; // Initialize the vtable pointers for this class and all of its bases. - if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD)) - for (const VPtr &Vptr : getVTablePointers(RD)) - InitializeVTablePointer(Vptr); + VisitedVirtualBasesSetTy VBases; + InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()), + /*NearestVBase=*/nullptr, + /*OffsetFromNearestVBase=*/CharUnits::Zero(), + /*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases); if (RD->getNumVBases()) CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD); |