[libcxx-commits] [libcxx] [libc++][unique_ptr] Implement LWG 4144: Disallow unique_ptr<T&, D> (PR #209018)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jul 12 08:04:35 PDT 2026


https://github.com/emmett2020 updated https://github.com/llvm/llvm-project/pull/209018

>From c4349f973fed37783692cce1aae993813563a5dd Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Sun, 12 Jul 2026 21:31:47 +0800
Subject: [PATCH] [libcxx][unique_ptr] Implement LWG 4144: Disallow
 unique_ptr<T&, D>

---
 libcxx/docs/Status/Cxx26Issues.csv            |  2 +-
 libcxx/include/__memory/unique_ptr.h          |  9 +++++
 .../non_pointable.single.verify.cpp           | 40 +++++++++++++++++++
 3 files changed, 50 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp

diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 8441da10d78de..c203fa424556a 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -101,7 +101,7 @@
 "`LWG4140 <https://wg21.link/LWG4140>`__","Useless default constructors for bit reference types","2024-11 (Wrocław)","|Complete|","","`#118356 <https://github.com/llvm/llvm-project/issues/118356>`__",""
 "`LWG4141 <https://wg21.link/LWG4141>`__","Improve prohibitions on ""additional storage""","2024-11 (Wrocław)","","","`#118357 <https://github.com/llvm/llvm-project/issues/118357>`__",""
 "`LWG4142 <https://wg21.link/LWG4142>`__","``format_parse_context::check_dynamic_spec`` should require at least one type","2024-11 (Wrocław)","","","`#118358 <https://github.com/llvm/llvm-project/issues/118358>`__",""
-"`LWG4144 <https://wg21.link/LWG4144>`__","Disallow ``unique_ptr<T&, D>``","2024-11 (Wrocław)","","","`#118359 <https://github.com/llvm/llvm-project/issues/118359>`__",""
+"`LWG4144 <https://wg21.link/LWG4144>`__","Disallow ``unique_ptr<T&, D>``","2024-11 (Wrocław)","|Complete|","23","`#118359 <https://github.com/llvm/llvm-project/issues/118359>`__",""
 "`LWG4147 <https://wg21.link/LWG4147>`__","Precondition on ``inplace_vector::emplace``","2024-11 (Wrocław)","","","`#118361 <https://github.com/llvm/llvm-project/issues/118361>`__",""
 "`LWG4148 <https://wg21.link/LWG4148>`__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","","","`#118362 <https://github.com/llvm/llvm-project/issues/118362>`__",""
 "`LWG4153 <https://wg21.link/LWG4153>`__","Fix extra ""-1"" for ``philox_engine::max()``","2024-11 (Wrocław)","","","`#118363 <https://github.com/llvm/llvm-project/issues/118363>`__",""
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 7e68faa15dabb..93878301b0322 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -43,6 +43,7 @@
 #include <__type_traits/is_void.h>
 #include <__type_traits/remove_extent.h>
 #include <__type_traits/remove_reference.h>
+#include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
@@ -100,6 +101,12 @@ inline const bool __can_dereference = false;
 template <class _Tp>
 inline const bool __can_dereference<_Tp, decltype((void)*std::declval<_Tp>())> = true;
 
+template <class _Tp, class = void>
+inline const bool __is_pointable = false;
+
+template <class _Tp>
+inline const bool __is_pointable<_Tp, __void_t<_Tp*> > = true;
+
 #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI)
 #  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__))
 #else
@@ -111,6 +118,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
 public:
   typedef _Tp element_type;
   typedef _Dp deleter_type;
+
+  static_assert(__is_pointable<_Tp>, "unique_ptr<T, D> requires T* to be a valid type");
   using pointer _LIBCPP_NODEBUG = __pointer<_Tp, deleter_type>;
 
   static_assert(!is_rvalue_reference<deleter_type>::value, "the specified deleter type cannot be an rvalue reference");
diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp
new file mode 100644
index 0000000000000..14829629861c6
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// unique_ptr
+
+// A program that instantiates the definition of unique_ptr<T, D> is ill-formed if T* is an invalid type.
+
+// LWG 4144
+
+// XFAIL: FROZEN-CXX03-HEADERS-FIXME
+
+#include <memory>
+
+struct Deleter {
+  typedef int* pointer;
+
+  void operator()(pointer) const;
+};
+
+typedef void Function();
+typedef void AbominableFunction() const;
+
+void pointable_function_type() { (void)sizeof(std::unique_ptr<Function, Deleter>); }
+
+void reference_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}unique_ptr<T, D> requires T* to be a valid type}}
+  (void)sizeof(std::unique_ptr<int&, Deleter>);
+}
+
+void abominable_function_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}unique_ptr<T, D> requires T* to be a valid type}}
+  (void)sizeof(std::unique_ptr<AbominableFunction, Deleter>);
+}



More information about the libcxx-commits mailing list