[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:34:30 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Emmett (emmett2020)

<details>
<summary>Changes</summary>

Implement LWG 4144 by explicitly rejecting `unique_ptr<T, D>` when `T*` is not a valid type.

This adds a pointability check and tests reference and abominable function types. It also includes a minor formatting cleanup for `unique_ptr`'s `nullptr` comparison operator.

Fixes #<!-- -->118359

---
Full diff: https://github.com/llvm/llvm-project/pull/209018.diff


3 Files Affected:

- (modified) libcxx/docs/Status/Cxx26Issues.csv (+1-1) 
- (modified) libcxx/include/__memory/unique_ptr.h (+11-2) 
- (added) libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp (+42) 


``````````diff
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..22737598ef0b3
--- /dev/null
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/non_pointable.single.verify.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>);
+}

``````````

</details>


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


More information about the libcxx-commits mailing list