Skip to content

Commit e6388fe

Browse files
authored
[libc++][memory] Implements LWG3307. (#99776)
As a drive-by added a nodiscard test for allocate_at_least. Implements - LWG33307 std::allocator<void>().allocate(n)
1 parent 6cea818 commit e6388fe

File tree

4 files changed

+52
-1
lines changed

4 files changed

+52
-1
lines changed

libcxx/docs/Status/Cxx20Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@
233233
"`3302 <https://wg21.link/LWG3302>`__","Range adaptor objects ``keys``\ and ``values``\ are unspecified","Prague","|Complete|","16.0","|ranges|"
234234
"`3303 <https://wg21.link/LWG3303>`__","Bad ""``constexpr``\ "" marker for ``destroy/destroy_n``\ ","Prague","",""
235235
"`3304 <https://wg21.link/LWG3304>`__","Allocate functions of ``std::polymorphic_allocator``\ should require ``[[nodiscard]]``\ ","Prague","|Complete|","16.0"
236-
"`3307 <https://wg21.link/LWG3307>`__","``std::allocator<void>().allocate(n)``\ ","Prague","",""
236+
"`3307 <https://wg21.link/LWG3307>`__","``std::allocator<void>().allocate(n)``\ ","Prague","|Complete|","20.0"
237237
"`3310 <https://wg21.link/LWG3310>`__","Replace ``SIZE_MAX``\ with ``numeric_limits<size_t>::max()``\ ","Prague","|Complete|","16.0"
238238
"`3313 <https://wg21.link/LWG3313>`__","``join_view::iterator::operator--``\ is incorrectly constrained","Prague","|Complete|","14.0","|ranges|"
239239
"`3314 <https://wg21.link/LWG3314>`__","Is stream insertion behavior locale dependent when ``Period::type``\ is ``micro``\ ?","Prague","|Complete|","16.0","|chrono|"

libcxx/include/__memory/allocator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
110110
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator(const allocator<_Up>&) _NOEXCEPT {}
111111

112112
_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* allocate(size_t __n) {
113+
static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type");
113114
if (__n > allocator_traits<allocator>::max_size(*this))
114115
__throw_bad_array_new_length();
115116
if (__libcpp_is_constant_evaluated()) {
@@ -121,6 +122,7 @@ class _LIBCPP_TEMPLATE_VIS allocator : private __non_trivial_if<!is_void<_Tp>::v
121122

122123
#if _LIBCPP_STD_VER >= 23
123124
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<_Tp*> allocate_at_least(size_t __n) {
125+
static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type");
124126
return {allocate(__n), __n};
125127
}
126128
#endif

libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,21 @@
1515

1616
#include <memory>
1717

18+
struct incomplete;
19+
1820
void f() {
21+
{
1922
std::allocator<int> a;
2023
a.allocate(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
24+
}
25+
{
26+
std::allocator<void> a;
27+
[[maybe_unused]] auto b =
28+
a.allocate(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'void'}}
29+
}
30+
{
31+
std::allocator<incomplete> a;
32+
[[maybe_unused]] auto b =
33+
a.allocate(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'incomplete'}}
34+
}
2135
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <memory>
12+
13+
// allocator:
14+
// T* allocate_at_least(size_t n);
15+
16+
#include <memory>
17+
18+
struct incomplete;
19+
20+
void f() {
21+
{
22+
std::allocator<int> a;
23+
a.allocate_at_least(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
24+
}
25+
{
26+
std::allocator<void> a;
27+
[[maybe_unused]] auto b =
28+
a.allocate_at_least(3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'void'}}
29+
}
30+
{
31+
std::allocator<incomplete> a;
32+
[[maybe_unused]] auto b = a.allocate_at_least(
33+
3); // expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'incomplete'}}
34+
}
35+
}

0 commit comments

Comments
 (0)