Skip to content

Commit ba8f629

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 709980e commit ba8f629

File tree

3 files changed

+95
-2
lines changed

3 files changed

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

93137
int main(int, char**) {
@@ -105,5 +149,12 @@ int main(int, char**) {
105149
test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106150
static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107151
#endif
152+
153+
test_value_categories();
154+
test_integer_like_return_types();
155+
156+
static_assert(test_value_categories());
157+
static_assert(test_integer_like_return_types());
158+
108159
return 0;
109160
}
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)