[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 06:38:12 PDT 2026
https://github.com/emmett2020 updated https://github.com/llvm/llvm-project/pull/209018
>From 84ac8569141037b772ecfb0d82f67a147d849d4a 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 | 13 +++++-
.../non_pointable.single.verify.cpp | 40 +++++++++++++++++++
3 files changed, 52 insertions(+), 3 deletions(-)
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..e8a9a962fba9a 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");
@@ -619,8 +628,8 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
#endif
template <class _T1, class _D1>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool
-operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
return !__x;
}
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