[libcxx-commits] [libcxx] [libc++] Implement LWG4477: placement operator delete should be constexpr (PR #189915)

Fernando Pelliccioni via libcxx-commits libcxx-commits at lists.llvm.org
Wed Apr 1 01:37:42 PDT 2026


https://github.com/fpelliccioni created https://github.com/llvm/llvm-project/pull/189915

Implement the proposed resolution of [LWG4477](https://cplusplus.github.io/LWG/issue4477).

P2747R2 made placement `operator new` constexpr since C++26, but the corresponding placement `operator delete` was not. When a constructor throws during placement new in a constant expression, the placement delete is invoked and fails because it's not constexpr.

Add `_LIBCPP_CONSTEXPR_SINCE_CXX26` to placement `operator delete(void*, void*)` and `operator delete[](void*, void*)`.

Note: LWG4477 has not been formally adopted yet, but this is a speculative implementation.

Closes #189914

>From 686cdac0d7259b36b594edab9d6ad5c59236fde8 Mon Sep 17 00:00:00 2001
From: Fernando Pelliccioni <fpelliccioni at gmail.com>
Date: Wed, 1 Apr 2026 10:36:10 +0200
Subject: [PATCH] [libc++] Implement LWG4477: placement operator delete should
 be constexpr

P2747R2 made placement operator new constexpr since C++26, but the
corresponding placement operator delete was not. When a constructor
throws during placement new in a constant expression, the placement
delete is invoked and fails because it's not constexpr.

Add _LIBCPP_CONSTEXPR_SINCE_CXX26 to placement operator delete and
operator delete[].
---
 libcxx/docs/Status/Cxx2cIssues.csv          | 1 +
 libcxx/include/__new/placement_new_delete.h | 5 +++--
 libcxx/include/new                          | 4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 60b1bd6ff70da..83dd79b244ea3 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -263,4 +263,5 @@
 "`LWG4139 <https://wg21.link/LWG4139>`__","ยง[time.zone.leap] recursive constraint in ``<=>``","Not Adopted Yet","|Complete|","20","`#118369 <https://github.com/llvm/llvm-project/issues/118369>`__",""
 "`LWG3456 <https://wg21.link/LWG3456>`__","Pattern used by ``std::from_chars`` is underspecified (option B)","Not Adopted Yet","|Complete|","20","`#118370 <https://github.com/llvm/llvm-project/issues/118370>`__",""
 "`LWG3882 <https://wg21.link/LWG3882>`__","``tuple`` relational operators have confused friendships","Not Adopted Yet","|Complete|","22","","The comparison operators are constrained harder than the proposed resolution. libstdc++ and MSVC STL do the same."
+"`LWG4477 <https://wg21.link/LWG4477>`__","Placement operator delete should be ``constexpr``","Not Adopted Yet","|Complete|","23","`#189914 <https://github.com/llvm/llvm-project/issues/189914>`__",""
 "","","","","","",""
diff --git a/libcxx/include/__new/placement_new_delete.h b/libcxx/include/__new/placement_new_delete.h
index 42c9f34036775..92851358a7569 100644
--- a/libcxx/include/__new/placement_new_delete.h
+++ b/libcxx/include/__new/placement_new_delete.h
@@ -27,8 +27,9 @@ operator new(std::size_t, void* __p) _NOEXCEPT {
 operator new[](std::size_t, void* __p) _NOEXCEPT {
   return __p;
 }
-inline _LIBCPP_HIDE_FROM_ABI void operator delete(void*, void*) _NOEXCEPT {}
-inline _LIBCPP_HIDE_FROM_ABI void operator delete[](void*, void*) _NOEXCEPT {}
+// LWG4477 placement operator delete should be constexpr
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator delete(void*, void*) _NOEXCEPT {}
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator delete[](void*, void*) _NOEXCEPT {}
 #endif
 
 #endif // _LIBCPP___NEW_PLACEMENT_NEW_DELETE_H
diff --git a/libcxx/include/new b/libcxx/include/new
index 4d72ec27675c9..29137b7304438 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -81,8 +81,8 @@ void  operator delete[](void* ptr, std::align_val_t alignment,
 
 void* operator new  (std::size_t size, void* ptr) noexcept;             // nodiscard in C++20, constexpr since C++26
 void* operator new[](std::size_t size, void* ptr) noexcept;             // nodiscard in C++20, constexpr since C++26
-void  operator delete  (void* ptr, void*) noexcept;
-void  operator delete[](void* ptr, void*) noexcept;
+void  operator delete  (void* ptr, void*) noexcept;                       // constexpr since C++26
+void  operator delete[](void* ptr, void*) noexcept;                       // constexpr since C++26
 
 */
 



More information about the libcxx-commits mailing list