Skip to content

Commit 1975341

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 bf0a6ae commit 1975341

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-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: 60 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,67 @@ 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+
// Test various integer-like types
99+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> int {
100+
std::fill(p, p + n, 'a');
101+
return 5;
102+
});
103+
assert(s.size() == 5);
104+
assert(s == "aaaaa");
105+
106+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned int {
107+
std::fill(p, p + n, 'b');
108+
return 5u;
109+
});
110+
assert(s.size() == 5);
111+
assert(s == "bbbbb");
112+
113+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> long {
114+
std::fill(p, p + n, 'c');
115+
return 5l;
116+
});
117+
assert(s.size() == 5);
118+
assert(s == "ccccc");
119+
120+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned long {
121+
std::fill(p, p + n, 'd');
122+
return 5ul;
123+
});
124+
assert(s.size() == 5);
125+
assert(s == "ddddd");
126+
127+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> long long {
128+
std::fill(p, p + n, 'e');
129+
return 5ll;
130+
});
131+
assert(s.size() == 5);
132+
assert(s == "eeeee");
133+
134+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> unsigned long long {
135+
std::fill(p, p + n, 'f');
136+
return 5ull;
137+
});
138+
assert(s.size() == 5);
139+
assert(s == "fffff");
140+
141+
return true;
91142
}
92143

93144
int main(int, char**) {
@@ -105,5 +156,12 @@ int main(int, char**) {
105156
test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106157
static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107158
#endif
159+
160+
test_value_categories();
161+
test_integer_like_return_types();
162+
163+
static_assert(test_value_categories());
164+
static_assert(test_integer_like_return_types());
165+
108166
return 0;
109167
}
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)