[libcxx-commits] [libcxx] [libc++][memory] LWG4148: `unique_ptr::operator*` should not allow dangling references (PR #214971)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Aug 8 08:51:05 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

<details>
<summary>Changes</summary>

Implements https://wg21.link/LWG4148

Closes #<!-- -->118362

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


4 Files Affected:

- (modified) libcxx/docs/Status/Cxx26Issues.csv (+1-1) 
- (modified) libcxx/include/__memory/unique_ptr.h (+4) 
- (modified) libcxx/include/__type_traits/reference_converts_from_temporary.h (+7-4) 
- (added) libcxx/test/libcxx/memory/unique_ptr.verify.cpp (+32) 


``````````diff
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index db9bf85b72d4c..1361aaa316178 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -103,7 +103,7 @@
 "`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)","|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>`__",""
+"`LWG4148 <https://wg21.link/LWG4148>`__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","|Complete|","24","`#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>`__",""
 "`LWG4154 <https://wg21.link/LWG4154>`__","The Mandates for ``std::packaged_task``'s constructor from a callable entity should consider decaying","2024-11 (Wrocław)","","","`#118364 <https://github.com/llvm/llvm-project/issues/118364>`__",""
 "`LWG4157 <https://wg21.link/LWG4157>`__","The resolution of LWG3465 was damaged by P2167R3","2024-11 (Wrocław)","|Complete|","20","`#118365 <https://github.com/llvm/llvm-project/issues/118365>`__",""
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index fcae9d84eb991..c8392d35c352f 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -42,6 +42,7 @@
 #include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/nat.h>
+#include <__type_traits/reference_converts_from_temporary.h>
 #include <__type_traits/remove_extent.h>
 #include <__type_traits/remove_reference.h>
 #include <__type_traits/void_t.h>
@@ -237,6 +238,9 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
   template <class _Ptr = pointer, __enable_if_t<__can_dereference<_Ptr>, int> = 0>
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const
       _NOEXCEPT_(_NOEXCEPT_(*std::declval<pointer>())) {
+    static_assert(
+        !__reference_converts_from_temporary_v<__add_lvalue_reference_t<_Tp>, decltype(*std::declval<pointer>())>,
+        "The returned reference must not bind to a temporary object.");
     return *__ptr_;
   }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; }
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
index 31479e43ee2c4..8d879e436cab8 100644
--- a/libcxx/include/__type_traits/reference_converts_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -16,10 +16,13 @@
 #  pragma GCC system_header
 #endif
 
-#if _LIBCPP_STD_VER >= 23
-
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Tp, class _Up>
+inline const bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
+
+#if _LIBCPP_STD_VER >= 23
+
 template <class _Tp, class _Up>
 struct _LIBCPP_NO_SPECIALIZATIONS reference_converts_from_temporary
     : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)> {};
@@ -28,8 +31,8 @@ template <class _Tp, class _Up>
 _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_converts_from_temporary_v =
     __reference_converts_from_temporary(_Tp, _Up);
 
-_LIBCPP_END_NAMESPACE_STD
-
 #endif //  _LIBCPP_STD_VER >= 23
 
+_LIBCPP_END_NAMESPACE_STD
+
 #endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARY_H
diff --git a/libcxx/test/libcxx/memory/unique_ptr.verify.cpp b/libcxx/test/libcxx/memory/unique_ptr.verify.cpp
new file mode 100644
index 0000000000000..e0305e80443bb
--- /dev/null
+++ b/libcxx/test/libcxx/memory/unique_ptr.verify.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++11
+
+// <memory>
+
+#include <memory>
+
+#include "test_macros.h"
+
+struct Deleter {
+  using pointer = long*;
+
+  void operator()(pointer) const {}
+};
+
+void test() {
+  long l = 0;
+  std::unique_ptr<const int, Deleter> p{&l};
+
+// expected-error-re@*:* {{static assertion failed due to requirement {{.+}}The returned reference must not bind to a temporary object.}}
+#if TEST_STD_VER >= 26
+// expected-error@*:* {{returning reference to local temporary object}}
+#endif
+  [[maybe_unused]] int i = *p;
+}

``````````

</details>


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


More information about the libcxx-commits mailing list