llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) <details> <summary>Changes</summary> When a destroying delete overload is selected, the destructor is not automatically called. Therefore, the destructor can be deleted without causing the program to be ill-formed. --- Full diff: https://github.com/llvm/llvm-project/pull/118800.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/lib/Sema/SemaExprCXX.cpp (+4-2) - (modified) clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp (+20-2) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e484eb7a76e63a..4a72e4046e2d03 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -663,6 +663,8 @@ Bug Fixes in This Version - Fixed a crash when GNU statement expression contains invalid statement (#GH113468). - Fixed a failed assertion when using ``__attribute__((noderef))`` on an ``_Atomic``-qualified type (#GH116124). +- No longer incorrectly diagnosing use of a deleted destructor when the + selected overload of ``operator delete`` for that type is a destroying delete. Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index db9ea7fb66e05a..45840dfa31ac92 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3792,13 +3792,15 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, .HasSizeT; } - if (!PointeeRD->hasIrrelevantDestructor()) + if (!PointeeRD->hasIrrelevantDestructor() && + (!OperatorDelete || !OperatorDelete->isDestroyingOperatorDelete())) { if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) { MarkFunctionReferenced(StartLoc, - const_cast<CXXDestructorDecl*>(Dtor)); + const_cast<CXXDestructorDecl *>(Dtor)); if (DiagnoseUseOfDecl(Dtor, StartLoc)) return ExprError(); } + } CheckVirtualDtorCall(PointeeRD->getDestructor(), StartLoc, /*IsDelete=*/true, /*CallCanBeVirtual=*/true, diff --git a/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp b/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp index aad2747dd32f24..b2c0a2c79695fc 100644 --- a/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp @@ -1,7 +1,14 @@ -// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++20 -verify %s using size_t = decltype(sizeof(0)); -namespace std { enum class align_val_t : size_t {}; } +namespace std { + enum class align_val_t : size_t {}; + struct destroying_delete_t { + explicit destroying_delete_t() = default; + }; + + inline constexpr destroying_delete_t destroying_delete{}; +} // Aligned version is preferred over unaligned version, // unsized version is preferred over sized version. @@ -23,3 +30,14 @@ struct alignas(Align) B { }; void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; } void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}} + +// Ensure that a deleted destructor is acceptable when the selected overload +// for operator delete is a destroying delete. See the comments in GH118660. +struct S { + ~S() = delete; + void operator delete(S *, std::destroying_delete_t) noexcept {} +}; + +void foo(S *s) { + delete s; // Was rejected, is intended to be accepted. +} `````````` </details> https://github.com/llvm/llvm-project/pull/118800 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits