From b031f468580df8e73b5f0464490f1a6f0f178d74 Mon Sep 17 00:00:00 2001 From: Mohamed Atef Date: Fri, 21 Feb 2025 20:13:33 +0200 Subject: [PATCH] [libcxx] implement LWG4148: unique_ptr::operator* should not allow dangling references --- libcxx/docs/Status/Cxx2cIssues.csv | 2 +- libcxx/include/__memory/unique_ptr.h | 7 +++++ .../test/libcxx/memory/unique_ptr.verify.cpp | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/libcxx/memory/unique_ptr.verify.cpp diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index 9bf31c417f3c9..27c5b91235f72 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -103,7 +103,7 @@ "`LWG4142 `__","``format_parse_context::check_dynamic_spec`` should require at least one type","2024-11 (Wrocław)","","","" "`LWG4144 `__","Disallow ``unique_ptr``","2024-11 (Wrocław)","","","" "`LWG4147 `__","Precondition on ``inplace_vector::emplace``","2024-11 (Wrocław)","","","" -"`LWG4148 `__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","","","" +"`LWG4148 `__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","|Complete|","21","" "`LWG4153 `__","Fix extra ""-1"" for ``philox_engine::max()``","2024-11 (Wrocław)","","","" "`LWG4154 `__","The Mandates for ``std::packaged_task``'s constructor from a callable entity should consider decaying","2024-11 (Wrocław)","","","" "`LWG4157 `__","The resolution of LWG3465 was damaged by P2167R3","2024-11 (Wrocław)","","20","" diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 6f1dc98db5a9f..8cdda3548c6ed 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -262,6 +262,13 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const _NOEXCEPT_(_NOEXCEPT_(*std::declval())) { + // TODO(LLVM-21): Remove this workaround +#if !defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER != 1800 + // TODO: use reference_converts_from_temporary_v once implemented. + static_assert( + !__reference_converts_from_temporary(__add_lvalue_reference_t<_Tp>, decltype(*std::declval())), + "Reference type _Tp must not convert from a temporary object"); +#endif return *__ptr_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; } 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..d66a73386912e --- /dev/null +++ b/libcxx/test/libcxx/memory/unique_ptr.verify.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +#include + +struct deleter { + using pointer = long*; + void operator()(pointer) const {} +}; + +int main(int, char**) { + long l = 0; + std::unique_ptr p(&l); + int i = + *p; // expected-error@*:* {{static assertion failed due to requirement '!__reference_converts_from_temporary(const int &, long &)': Reference type _Tp must not convert from a temporary object}} + return 0; +}