Skip to content

Commit 26834f0

Browse files
committed
[libc++][string] Assert resize_and_overwrite operation returns integer-like type
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 cf85ec5 commit 26834f0

File tree

3 files changed

+100
-2
lines changed

3 files changed

+100
-2
lines changed

libcxx/include/string

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

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

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <algorithm>
1717
#include <cassert>
18+
#include <cstddef>
1819
#include <memory>
1920
#include <string>
2021

@@ -77,17 +78,65 @@ 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+
std::string s;
97+
98+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> int {
99+
(void)n;
100+
std::fill(p, p + 5, 'a');
101+
return 5;
102+
});
103+
assert(s.size() == 5);
104+
105+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned int {
106+
(void)n;
107+
std::fill(p, p + 3, 'b');
108+
return 3u;
109+
});
110+
assert(s.size() == 3);
111+
112+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> long {
113+
(void)n;
114+
std::fill(p, p + 7, 'c');
115+
return 7l;
116+
});
117+
assert(s.size() == 7);
118+
119+
s.resize_and_overwrite(20, [](char* p, std::size_t n) -> unsigned long {
120+
(void)n;
121+
std::fill(p, p + 4, 'd');
122+
return 4ul;
123+
});
124+
assert(s.size() == 4);
125+
126+
s.resize_and_overwrite(15, [](char* p, std::size_t n) -> long long {
127+
(void)n;
128+
std::fill(p, p + 8, 'e');
129+
return 8ll;
130+
});
131+
assert(s.size() == 8);
132+
133+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned long long {
134+
std::fill(p, p + n, 'f');
135+
return n;
136+
});
137+
assert(s.size() == 10);
138+
139+
return true;
91140
}
92141

93142
int main(int, char**) {
@@ -105,5 +154,12 @@ int main(int, char**) {
105154
test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106155
static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107156
#endif
157+
158+
test_value_categories();
159+
test_integer_like_return_types();
160+
161+
static_assert(test_value_categories());
162+
static_assert(test_integer_like_return_types());
163+
108164
return 0;
109165
}
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+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
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)