Skip to content

Commit 9146ef5

Browse files
authored
[libc++][string] Assert resize_and_overwrite operation returns integer-like type (#162030)
Verify that the operation passed to resize_and_overwrite returns an integer-like type, matching the behavior of other standard library implementations like GCC's libstdc++ Fixes #160577
1 parent a75565a commit 9146ef5

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

libcxx/include/string

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,8 @@ public:
13121312
# if _LIBCPP_STD_VER >= 23
13131313
template <class _Op>
13141314
_LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) {
1315+
using __result_type = decltype(std::move(__op)(data(), auto(__n)));
1316+
static_assert(__integer_like<__result_type>, "Operation return type must be integer-like");
13151317
size_type __sz = size();
13161318
size_type __cap = capacity();
13171319
if (__n > __cap)

libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "make_string.h"
2222
#include "test_macros.h"
2323
#include "asan_testing.h"
24+
#include "type_algorithms.h"
2425

2526
template <class S>
2627
constexpr void test_appending(std::size_t k, size_t N, size_t new_capacity) {
@@ -77,17 +78,30 @@ constexpr bool test() {
7778
return true;
7879
}
7980

80-
void test_value_categories() {
81+
constexpr bool test_value_categories() {
8182
std::string s;
8283
s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; });
8384
LIBCPP_ASSERT(is_string_asan_correct(s));
8485
s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; });
8586
LIBCPP_ASSERT(is_string_asan_correct(s));
8687
struct RefQualified {
87-
int operator()(char*, std::size_t) && { return 0; }
88+
constexpr int operator()(char*, std::size_t) && { return 0; }
8889
};
8990
s.resize_and_overwrite(10, RefQualified{});
9091
LIBCPP_ASSERT(is_string_asan_correct(s));
92+
return true;
93+
}
94+
95+
constexpr bool test_integer_like_return_types() {
96+
types::for_each(types::integer_types(), []<typename IntegerType> {
97+
std::string s;
98+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> IntegerType {
99+
std::fill(p, p + n, 'f');
100+
return n;
101+
});
102+
assert(s.size() == 10);
103+
});
104+
return true;
91105
}
92106

93107
int main(int, char**) {
@@ -105,5 +119,12 @@ int main(int, char**) {
105119
test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106120
static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107121
#endif
122+
123+
test_value_categories();
124+
test_integer_like_return_types();
125+
126+
static_assert(test_value_categories());
127+
static_assert(test_integer_like_return_types());
128+
108129
return 0;
109130
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
// REQUIRES: std-at-least-c++23
10+
11+
// <string>
12+
13+
// template<class Operation>
14+
// void resize_and_overwrite(size_type n, Operation op)
15+
16+
// Verify that the operation's return type must be integer-like
17+
18+
#include <string>
19+
20+
void test_bool_return_type() {
21+
std::string s;
22+
s.resize_and_overwrite(10, [](char*, std::size_t) {
23+
return true; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
24+
});
25+
}
26+
27+
void test_pointer_return_type() {
28+
std::string s;
29+
s.resize_and_overwrite(10, [](char* p, std::size_t) {
30+
return p; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
31+
// expected-error@*:* {{cannot initialize}}
32+
});
33+
}
34+
35+
void test_float_return_type() {
36+
std::string s;
37+
s.resize_and_overwrite(10, [](char*, std::size_t) {
38+
return 5.0f; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
39+
});
40+
}

0 commit comments

Comments
 (0)