[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
Tue Apr 7 05:06:40 PDT 2026


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

>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 1/4] [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
 
 */
 

>From 80f479bca8c7ef54c5f6150809d24ef4814ff7be Mon Sep 17 00:00:00 2001
From: Fernando Pelliccioni <fpelliccioni at gmail.com>
Date: Tue, 7 Apr 2026 13:53:50 +0200
Subject: [PATCH 2/4] [libc++] Address review: deduplicate LWG4477 entry in
 Cxx2cIssues.csv

Update the existing entry added by #189901 to mark it as Complete in
libc++ 23, and remove the duplicate row that was added under the
'Not Adopted Yet' section.
---
 libcxx/docs/Status/Cxx2cIssues.csv | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 799afe88da7fd..6f5af8eb9dbee 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -298,7 +298,7 @@
 "`LWG4472 <https://wg21.link/LWG4472>`__","``std::atomic_ref<const T>`` can be constructed from temporaries","2026-03 (Croydon)","","","`#189840 <https://github.com/llvm/llvm-project/issues/189840>`__",""
 "`LWG4474 <https://wg21.link/LWG4474>`__","""`round_to_nearest`"" rounding mode is unclear","2026-03 (Croydon)","","","`#189841 <https://github.com/llvm/llvm-project/issues/189841>`__",""
 "`LWG4476 <https://wg21.link/LWG4476>`__","``run_loop`` should not have a ``set_error`` completion","2026-03 (Croydon)","","","`#189842 <https://github.com/llvm/llvm-project/issues/189842>`__",""
-"`LWG4477 <https://wg21.link/LWG4477>`__","Placement ``operator delete`` should be constexpr","2026-03 (Croydon)","","","`#189843 <https://github.com/llvm/llvm-project/issues/189843>`__",""
+"`LWG4477 <https://wg21.link/LWG4477>`__","Placement ``operator delete`` should be constexpr","2026-03 (Croydon)","|Complete|","23","`#189843 <https://github.com/llvm/llvm-project/issues/189843>`__",""
 "`LWG4478 <https://wg21.link/LWG4478>`__","``meta::has_identifier`` is not specified for annotations","2026-03 (Croydon)","","","`#189844 <https://github.com/llvm/llvm-project/issues/189844>`__",""
 "`LWG4480 <https://wg21.link/LWG4480>`__","``<stdatomic.h>`` should provide ``ATOMIC_CHAR8_T_LOCK_FREE``","2026-03 (Croydon)","","","`#189845 <https://github.com/llvm/llvm-project/issues/189845>`__",""
 "`LWG4481 <https://wg21.link/LWG4481>`__","Disallow ``chrono::duration<const T, P>``","2026-03 (Croydon)","","","`#189846 <https://github.com/llvm/llvm-project/issues/189846>`__",""
@@ -345,5 +345,4 @@
 "`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>`__",""
 "","","","","","",""

>From a14a9f8337909d62cac1ce3fb6c1882eddcf1e25 Mon Sep 17 00:00:00 2001
From: Fernando Pelliccioni <fpelliccioni at gmail.com>
Date: Tue, 7 Apr 2026 13:57:22 +0200
Subject: [PATCH 3/4] [libc++] Address review: drop unnecessary LWG4477 comment

---
 libcxx/include/__new/placement_new_delete.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/include/__new/placement_new_delete.h b/libcxx/include/__new/placement_new_delete.h
index 92851358a7569..74692f36fd04c 100644
--- a/libcxx/include/__new/placement_new_delete.h
+++ b/libcxx/include/__new/placement_new_delete.h
@@ -27,7 +27,6 @@ operator new(std::size_t, void* __p) _NOEXCEPT {
 operator new[](std::size_t, void* __p) _NOEXCEPT {
   return __p;
 }
-// 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

>From 9d8fe5c8a1688ee0ce85d93a5f922b3ae5eb503b Mon Sep 17 00:00:00 2001
From: Fernando Pelliccioni <fpelliccioni at gmail.com>
Date: Tue, 7 Apr 2026 14:04:22 +0200
Subject: [PATCH 4/4] [libc++] Address review: add LWG4477 tests for placement
 operator delete

---
 .../new.delete/new.delete.placement/new.pass.cpp              | 4 ++++
 .../new.delete/new.delete.placement/new_array.pass.cpp        | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
index 55be3f72508da..b00d6742717c6 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
@@ -26,6 +26,10 @@ TEST_CONSTEXPR_OPERATOR_NEW void test_direct_call() {
   char ch = '*';
   assert(::operator new(1, &ch) == &ch);
   assert(ch == '*');
+
+  // LWG4477: placement operator delete is a no-op and must be usable
+  // in constant expressions.
+  ::operator delete(&ch, &ch);
 }
 
 #ifdef __cpp_lib_constexpr_new
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
index 1f7b08ec641c3..bd5804a4166ad 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
@@ -27,6 +27,10 @@ TEST_CONSTEXPR_OPERATOR_NEW void test_direct_call() {
   char ch = '*';
   assert(::operator new[](1, &ch) == &ch);
   assert(ch == '*');
+
+  // LWG4477: placement operator delete[] is a no-op and must be usable
+  // in constant expressions.
+  ::operator delete[](&ch, &ch);
 }
 
 #ifdef __cpp_lib_constexpr_new



More information about the libcxx-commits mailing list