[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:19:12 PDT 2024


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

>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 1/2] [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'}}
+  }
+}

>From 899cc0327d1088c12f75b774f0d0455d04c5983e Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 20 Jul 2024 21:08:46 +0200
Subject: [PATCH 2/2] [libc++][syncbuf] Implements LWG3253.

Note the tests already tested this behaviour and the wording change is NFC.

Implements
- LWG3253 basic_syncbuf::basic_syncbuf() should not be explicit
---
 libcxx/docs/Status/Cxx20Issues.csv | 2 +-
 libcxx/include/syncstream          | 9 +++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index 4f8118b5a35fb..85a8ee2190307 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -172,7 +172,7 @@
 "`3221 <https://wg21.link/LWG3221>`__","Result of ``year_month``\  arithmetic with ``months``\  is ambiguous","Belfast","|Complete|","8.0"
 "`3235 <https://wg21.link/LWG3235>`__","``parse``\  manipulator without abbreviation is not callable","Belfast","",""
 "`3246 <https://wg21.link/LWG3246>`__","What are the constraints on the template parameter of ``basic_format_arg``\ ?","Belfast","","","|format|"
-"`3253 <https://wg21.link/LWG3253>`__","``basic_syncbuf::basic_syncbuf()``\  should not be explicit","Belfast","",""
+"`3253 <https://wg21.link/LWG3253>`__","``basic_syncbuf::basic_syncbuf()``\  should not be explicit","Belfast","|Complete|","20.0"
 "`3245 <https://wg21.link/LWG3245>`__","Unnecessary restriction on ``'%p'``\  parse specifier","Belfast","","","|chrono|"
 "`3244 <https://wg21.link/LWG3244>`__","Constraints for ``Source``\  in |sect|\ [fs.path.req] insufficiently constrainty","Belfast","",""
 "`3241 <https://wg21.link/LWG3241>`__","``chrono-spec``\  grammar ambiguity in |sect|\ [time.format]","Belfast","|Complete|","16.0","|chrono| |format|"
diff --git a/libcxx/include/syncstream b/libcxx/include/syncstream
index e6f35b6f428ed..a0617f4acf5b6 100644
--- a/libcxx/include/syncstream
+++ b/libcxx/include/syncstream
@@ -46,7 +46,9 @@ namespace std {
         using streambuf_type = basic_streambuf<charT, traits>;
 
         // [syncstream.syncbuf.cons], construction and destruction
-        explicit basic_syncbuf(streambuf_type* obuf = nullptr)
+        basic_syncbuf()
+          : basic_syncbuf(nullptr) {}
+        explicit basic_syncbuf(streambuf_type* obuf)
           : basic_syncbuf(obuf, Allocator()) {}
         basic_syncbuf(streambuf_type*, const Allocator&);
         basic_syncbuf(basic_syncbuf&&);
@@ -253,7 +255,10 @@ public:
 
   // [syncstream.syncbuf.cons], construction and destruction
 
-  _LIBCPP_HIDE_FROM_ABI explicit basic_syncbuf(streambuf_type* __obuf = nullptr)
+  _LIBCPP_HIDE_FROM_ABI basic_syncbuf()
+      : basic_syncbuf(nullptr) {}
+
+  _LIBCPP_HIDE_FROM_ABI explicit basic_syncbuf(streambuf_type* __obuf)
       : basic_syncbuf(__obuf, _Allocator()) {}
 
   _LIBCPP_HIDE_FROM_ABI basic_syncbuf(streambuf_type* __obuf, _Allocator const& __alloc)



More information about the libcxx-commits mailing list