================ @@ -1589,25 +1589,74 @@ namespace { void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF, llvm::Value *ShouldDeleteCondition, bool ReturnAfterDelete) { + const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); + const CXXRecordDecl *ClassDecl = Dtor->getParent(); + const FunctionDecl *OD = Dtor->getOperatorDelete(); + assert(OD->isDestroyingOperatorDelete() == ReturnAfterDelete && + "unexpected value for ReturnAfterDelete"); + auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType()); + if (OD->isDestroyingOperatorDelete()) { + llvm::BasicBlock *CallDtor = CGF.createBasicBlock("dtor.call_dtor"); + llvm::BasicBlock *DontCallDtor = CGF.createBasicBlock("dtor.entry_cont"); + // Third bit set signals that global operator delete is called. That means + // despite class having destroying operator delete which is responsible + // for calling dtor, we need to call dtor because global operator delete + // won't do that. + llvm::Value *Check3rdBit = CGF.Builder.CreateAnd( + ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4)); + llvm::Value *ShouldCallDtor = CGF.Builder.CreateIsNull(Check3rdBit); + CGF.Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor); + CGF.EmitBlock(CallDtor); + QualType ThisTy = Dtor->getFunctionObjectParameterType(); + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, + /*Delegating=*/false, CGF.LoadCXXThisAddress(), + ThisTy); + CGF.Builder.CreateBr(DontCallDtor); + CGF.EmitBlock(DontCallDtor); + } llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); - llvm::Value *ShouldCallDelete - = CGF.Builder.CreateIsNull(ShouldDeleteCondition); + // First bit set signals that operator delete must be called. + llvm::Value *Check1stBit = CGF.Builder.CreateAnd( + ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1)); + llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(Check1stBit); CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); CGF.EmitBlock(callDeleteBB); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), - LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); - assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() == - ReturnAfterDelete && - "unexpected value for ReturnAfterDelete"); - if (ReturnAfterDelete) - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - else - CGF.Builder.CreateBr(continueBB); + auto EmitDeleteAndGoToEnd = [&](const FunctionDecl *DeleteOp) { + CGF.EmitDeleteCall(DeleteOp, LoadThisForDtorDelete(CGF, Dtor), + CGF.getContext().getTagDeclType(ClassDecl)); + if (ReturnAfterDelete) + CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); + else + CGF.Builder.CreateBr(continueBB); + }; + // If Sema only found a global operator delete previously, the dtor can + // always call it. Otherwise we need to check the third bit and call the + // appropriate operator delete, i.e. global or class-specific. + if (isa<CXXMethodDecl>(OD)) { + // Third bit set signals that global operator delete is called, i.e. + // ::delete appears on the callsite. + llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd( + ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4)); + llvm::Value *ShouldCallGlobDelete = + CGF.Builder.CreateIsNull(CheckTheBitForGlobDeleteCall); + llvm::BasicBlock *GlobDelete = + CGF.createBasicBlock("dtor.call_glob_delete"); + llvm::BasicBlock *ClassDelete = + CGF.createBasicBlock("dtor.call_class_delete"); + CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete); + CGF.EmitBlock(GlobDelete); + + const FunctionDecl *GlobOD = Dtor->getOperatorGlobalDelete(); + if (GlobOD) + EmitDeleteAndGoToEnd(GlobOD); + else + CGF.Builder.CreateUnreachable(); ---------------- efriedma-quic wrote:
There isn't really any point to creating a branch if one of the destinations is just "unreachable"; it'll get eliminated by SimplifyCFG. https://github.com/llvm/llvm-project/pull/139566 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits