Skip to content

Commit 0b14646

Browse files
committed
Update based on review feedback
1 parent 7b74158 commit 0b14646

File tree

4 files changed

+32
-34
lines changed

4 files changed

+32
-34
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,6 +2855,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
28552855
return getCanonicalDecl()->OperatorDeleteThisArg;
28562856
}
28572857

2858+
/// Will this destructor ever be called when considering which deallocation
2859+
/// function is associated with the destructor? Can optionally be passed an
2860+
/// 'operator delete' function declaration to test against specifically.
2861+
bool isDestructorCalled(const FunctionDecl *OpDel = nullptr) const;
2862+
28582863
CXXDestructorDecl *getCanonicalDecl() override {
28592864
return cast<CXXDestructorDecl>(FunctionDecl::getCanonicalDecl());
28602865
}

clang/lib/AST/DeclCXX.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,6 +2969,28 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
29692969
}
29702970
}
29712971

2972+
bool CXXDestructorDecl::isDestructorCalled(const FunctionDecl *OpDel) const {
2973+
// C++20 [expr.delete]p6: If the value of the operand of the delete-
2974+
// expression is not a null pointer value and the selected deallocation
2975+
// function (see below) is not a destroying operator delete, the delete-
2976+
// expression will invoke the destructor (if any) for the object or the
2977+
// elements of the array being deleted.
2978+
//
2979+
// This means we should not look at the destructor for a destroying
2980+
// delete operator, as that destructor is never called, unless the
2981+
// destructor is virtual (see [expr.delete]p8.1) because then the
2982+
// selected operator depends on the dynamic type of the pointer.
2983+
const FunctionDecl *SelectedOperatorDelete = OpDel ? OpDel : OperatorDelete;
2984+
if (!SelectedOperatorDelete)
2985+
return true;
2986+
2987+
if (!SelectedOperatorDelete->isDestroyingOperatorDelete())
2988+
return true;
2989+
2990+
// We have a destroying operator delete, so it depends on the dtor.
2991+
return isVirtual();
2992+
}
2993+
29722994
void CXXConversionDecl::anchor() {}
29732995

29742996
CXXConversionDecl *CXXConversionDecl::CreateDeserialized(ASTContext &C,

clang/lib/Sema/SemaExceptionSpec.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,17 +1210,11 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
12101210
// function (see below) is not a destroying operator delete, the delete-
12111211
// expression will invoke the destructor (if any) for the object or the
12121212
// elements of the array being deleted.
1213-
//
1214-
// So if the destructor is virtual, we only look at the exception
1215-
// specification of the destructor regardless of what operator delete is
1216-
// selected. Otherwise, we look at the selected operator delete, and if
1217-
// it is not a destroying delete, then we look at the destructor.
12181213
const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
12191214
if (const auto *RD = DTy->getAsCXXRecordDecl()) {
1220-
if (const CXXDestructorDecl *DD = RD->getDestructor()) {
1221-
if (DD->isVirtual() || !OperatorDelete->isDestroyingOperatorDelete())
1222-
CT = canCalleeThrow(*this, DE, DD);
1223-
}
1215+
if (const CXXDestructorDecl *DD = RD->getDestructor();
1216+
DD && DD->isDestructorCalled(OperatorDelete))
1217+
CT = canCalleeThrow(*this, DE, DD);
12241218
}
12251219

12261220
// We always look at the exception specification of the operator delete.

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3767,29 +3767,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
37673767

37683768
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
37693769
ArrayForm ? OO_Array_Delete : OO_Delete);
3770-
3771-
// C++20 [expr.delete]p6: If the value of the operand of the delete-
3772-
// expression is not a null pointer value and the selected deallocation
3773-
// function (see below) is not a destroying operator delete, the delete-
3774-
// expression will invoke the destructor (if any) for the object or the
3775-
// elements of the array being deleted.
3776-
//
3777-
// This means we should not look at the destructor for a destroying
3778-
// delete operator, as that destructor is never called, unless the
3779-
// destructor is virtual (see [expr.delete]p8.1) because then the
3780-
// selected operator depends on the dynamic type of the pointer.
3781-
auto IsDtorCalled = [](const CXXMethodDecl *Dtor,
3782-
const FunctionDecl *OperatorDelete) {
3783-
if (!OperatorDelete)
3784-
return true;
3785-
3786-
if (!OperatorDelete->isDestroyingOperatorDelete())
3787-
return true;
3788-
3789-
// We have a destroying operator delete, so it depends on the dtor.
3790-
return Dtor->isVirtual();
3791-
};
3792-
37933770
if (PointeeRD) {
37943771
if (!UseGlobal &&
37953772
FindDeallocationFunction(StartLoc, PointeeRD, DeleteName,
@@ -3816,7 +3793,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
38163793

38173794
if (!PointeeRD->hasIrrelevantDestructor()) {
38183795
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
3819-
if (IsDtorCalled(Dtor, OperatorDelete)) {
3796+
if (Dtor->isDestructorCalled(OperatorDelete)) {
38203797
MarkFunctionReferenced(StartLoc,
38213798
const_cast<CXXDestructorDecl *>(Dtor));
38223799
if (DiagnoseUseOfDecl(Dtor, StartLoc))
@@ -3858,7 +3835,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
38583835
bool IsVirtualDelete = false;
38593836
if (PointeeRD) {
38603837
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
3861-
if (IsDtorCalled(Dtor, OperatorDelete))
3838+
if (Dtor->isDestructorCalled(OperatorDelete))
38623839
CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
38633840
PDiag(diag::err_access_dtor) << PointeeElem);
38643841
IsVirtualDelete = Dtor->isVirtual();

0 commit comments

Comments
 (0)