diff options
author | Hans Wennborg <hans@chromium.org> | 2025-03-12 16:18:07 +0100 |
---|---|---|
committer | Hans Wennborg <hans@chromium.org> | 2025-03-12 16:26:00 +0100 |
commit | e11ede5e90ee193dde179fe1a9ac9af718ede3db (patch) | |
tree | d719a4919d44cc8f4a5665a199a96bf98863b711 /clang/lib/CodeGen/CGClass.cpp | |
parent | 90a8322399c7beb021cfe704003d36fafb1a7d29 (diff) | |
download | llvm-e11ede5e90ee193dde179fe1a9ac9af718ede3db.zip llvm-e11ede5e90ee193dde179fe1a9ac9af718ede3db.tar.gz llvm-e11ede5e90ee193dde179fe1a9ac9af718ede3db.tar.bz2 |
Revert "[MS][clang] Add support for vector deleting destructors (#126240)"
This caused link errors when building with sancov. See comment on the PR.
> Whereas it is UB in terms of the standard to delete an array of objects
> via pointer whose static type doesn't match its dynamic type, MSVC
> supports an extension allowing to do it.
> Aside from array deletion not working correctly in the mentioned case,
> currently not having this extension implemented causes clang to generate
> code that is not compatible with the code generated by MSVC, because
> clang always puts scalar deleting destructor to the vftable. This PR
> aims to resolve these problems.
>
> Fixes https://github.com/llvm/llvm-project/issues/19772
This reverts commit d6942d54f677000cf713d2b0eba57b641452beb4.
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 77 |
1 files changed, 4 insertions, 73 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index e54fd54..fa69caa4 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1433,70 +1433,6 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, return true; } -static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD, - CodeGenFunction &CGF, - llvm::Value *ShouldDeleteCondition) { - Address ThisPtr = CGF.LoadCXXThisAddress(); - llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar"); - llvm::BasicBlock *callDeleteBB = - CGF.createBasicBlock("dtor.call_delete_after_array_destroy"); - llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector"); - auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType()); - llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2)); - llvm::Value *ShouldDestroyArray = - CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy); - CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB); - - CGF.EmitBlock(VectorBB); - - llvm::Value *numElements = nullptr; - llvm::Value *allocatedPtr = nullptr; - CharUnits cookieSize; - QualType EltTy = DD->getThisType()->getPointeeType(); - CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements, - allocatedPtr, cookieSize); - - // Destroy the elements. - QualType::DestructionKind dtorKind = EltTy.isDestructedType(); - - assert(dtorKind); - assert(numElements && "no element count for a type with a destructor!"); - - CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy); - CharUnits elementAlign = - ThisPtr.getAlignment().alignmentOfArrayElement(elementSize); - - llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF); - llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( - ThisPtr.getElementType(), arrayBegin, numElements, "delete.end"); - - // We already checked that the array is not 0-length before entering vector - // deleting dtor. - CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign, - CGF.getDestroyer(dtorKind), - /*checkZeroLength*/ false, CGF.needsEHCleanup(dtorKind)); - - llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont"); - CGF.EmitBlock(VectorBBCont); - - llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1)); - - llvm::Value *ShouldCallDelete = - CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall); - CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(), - callDeleteBB); - CGF.EmitBlock(callDeleteBB); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr, - CGF.getContext().getTagDeclType(ClassDecl)); - - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - CGF.EmitBlock(ScalarBB); -} - /// EmitDestructorBody - Emits the body of the current destructor. void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); @@ -1526,9 +1462,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // outside of the function-try-block, which means it's always // possible to delegate the destructor body to the complete // destructor. Do so. - if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) { - if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting) - EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue); + if (DtorType == Dtor_Deleting) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); if (HaveInsertPoint()) { @@ -1557,8 +1491,6 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { switch (DtorType) { case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT"); case Dtor_Deleting: llvm_unreachable("already handled deleting case"); - case Dtor_VectorDeleting: - llvm_unreachable("already handled vector deleting case"); case Dtor_Complete: assert((Body || getTarget().getCXXABI().isMicrosoft()) && @@ -1641,6 +1573,7 @@ namespace { return CGF.EmitScalarExpr(ThisArg); return CGF.LoadCXXThis(); } + /// Call the operator delete associated with the current destructor. struct CallDtorDelete final : EHScopeStack::Cleanup { CallDtorDelete() {} @@ -1659,10 +1592,8 @@ namespace { bool ReturnAfterDelete) { llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); - auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType()); - llvm::Value *CheckTheBit = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1)); - llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(CheckTheBit); + llvm::Value *ShouldCallDelete + = CGF.Builder.CreateIsNull(ShouldDeleteCondition); CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); CGF.EmitBlock(callDeleteBB); |