[libcxx-commits] [libcxx] [libc++][memory] Implements LWG3307. (PR #99776)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jul 20 12:18:30 PDT 2024


https://github.com/mordante created https://github.com/llvm/llvm-project/pull/99776

As a drive-by added a nodiscard test for allocate_at_least.

Implements
- LWG33307 std::allocator<void>().allocate(n)

>From 425cdff68fe1e377034cba0b2a21ca4d1ba76624 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 20 Jul 2024 21:08:48 +0200
Subject: [PATCH] [libc++][memory] Implements LWG3307.

As a drive-by added a nodiscard test for allocate_at_least.

Implements
- LWG33307 std::allocator<void>().allocate(n)
---
 libcxx/docs/Status/Cxx20Issues.csv            |  2 +-
 libcxx/include/__memory/allocator.h           |  2 ++
 .../allocator.members/allocate.verify.cpp     | 14 ++++++++
 .../allocate_at_least.verify.cpp              | 35 +++++++++++++++++++
 4 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate_at_least.verify.cpp

diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index 1a40a4472a405..4f8118b5a35fb 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -233,7 +233,7 @@
 "`3302 <https://wg21.link/LWG3302>`__","Range adaptor objects ``keys``\  and ``values``\  are unspecified","Prague","|Complete|","16.0","|ranges|"
 "`3303 <https://wg21.link/LWG3303>`__","Bad ""``constexpr``\ "" marker for ``destroy/destroy_n``\ ","Prague","",""
 "`3304 <https://wg21.link/LWG3304>`__","Allocate functions of ``std::polymorphic_allocator``\  should require ``[[nodiscard]]``\ ","Prague","|Complete|","16.0"
-"`3307 <https://wg21.link/LWG3307>`__","``std::allocator<void>().allocate(n)``\ ","Prague","",""
+"`3307 <https://wg21.link/LWG3307>`__","``std::allocator<void>().allocate(n)``\ ","Prague","|Complete|","20.0"
 "`3310 <https://wg21.link/LWG3310>`__","Replace ``SIZE_MAX``\  with ``numeric_limits<size_t>::max()``\ ","Prague","|Complete|","16.0"
 "`3313 <https://wg21.link/LWG3313>`__","``join_view::iterator::operator--``\  is incorrectly constrained","Prague","|Complete|","14.0","|ranges|"
 "`3314 <https://wg21.link/LWG3314>`__","Is stream insertion behavior locale dependent when ``Period::type``\  is ``micro``\ ?","Prague","|Complete|","16.0","|chrono|"
diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h
index 2d8624e771bce..ae1f549626ee4 100644
--- a/libcxx/include/__memory/allocator.h
+++ b/libcxx/include/__memory/allocator.h
@@ -110,6 +110,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {}
 
   _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) {
+    static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type");
     if (__n > allocator_traits<allocator>::max_size(*this))
       __throw_bad_array_new_length();
     if (__libcpp_is_constant_evaluated()) {
@@ -121,6 +122,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
 
 #if _LIBCPP_STD_VER >= 23
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<_Tp*> allocate_at_least(size_t __n) {
+    static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type");
     return {allocate(__n), __n};
   }
 #endif
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp
index b2b6f51e98245..886ce7ac8d4a0 100644
--- a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp
@@ -15,7 +15,21 @@
 
 #include <memory>
 
+struct incomplete;
+
 void f() {
+  {
     std::allocator<int> a;
     a.allocate(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::allocator<void> a;
+    [[maybe_unused]] auto b =
+        a.allocate(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'void'}}
+  }
+  {
+    std::allocator<incomplete> a;
+    [[maybe_unused]] auto b =
+        a.allocate(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'incomplete'}}
+  }
 }
diff --git a/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate_at_least.verify.cpp b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate_at_least.verify.cpp
new file mode 100644
index 0000000000000..cfee54198e099
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate_at_least.verify.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// <memory>
+
+// allocator:
+// T* allocate_at_least(size_t n);
+
+#include <memory>
+
+struct incomplete;
+
+void f() {
+  {
+    std::allocator<int> a;
+    a.allocate_at_least(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::allocator<void> a;
+    [[maybe_unused]] auto b =
+        a.allocate_at_least(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'void'}}
+  }
+  {
+    std::allocator<incomplete> a;
+    [[maybe_unused]] auto b = a.allocate_at_least(
+        3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'incomplete'}}
+  }
+}



More information about the libcxx-commits mailing list